mirror of
https://github.com/semaphoreui/semaphore.git
synced 2024-12-04 07:11:05 +01:00
feat(backup): support integrations
This commit is contained in:
parent
a11b977332
commit
618018dd9e
@ -38,8 +38,8 @@ const (
|
|||||||
|
|
||||||
type IntegrationMatcher struct {
|
type IntegrationMatcher struct {
|
||||||
ID int `db:"id" json:"id" backup:"-"`
|
ID int `db:"id" json:"id" backup:"-"`
|
||||||
|
IntegrationID int `db:"integration_id" json:"integration_id" backup:"-"`
|
||||||
Name string `db:"name" json:"name"`
|
Name string `db:"name" json:"name"`
|
||||||
IntegrationID int `db:"integration_id" json:"integration_id"`
|
|
||||||
MatchType IntegrationMatchType `db:"match_type" json:"match_type"`
|
MatchType IntegrationMatchType `db:"match_type" json:"match_type"`
|
||||||
Method IntegrationMatchMethodType `db:"method" json:"method"`
|
Method IntegrationMatchMethodType `db:"method" json:"method"`
|
||||||
BodyDataType IntegrationBodyDataType `db:"body_data_type" json:"body_data_type"`
|
BodyDataType IntegrationBodyDataType `db:"body_data_type" json:"body_data_type"`
|
||||||
@ -56,8 +56,8 @@ const (
|
|||||||
|
|
||||||
type IntegrationExtractValue struct {
|
type IntegrationExtractValue struct {
|
||||||
ID int `db:"id" json:"id" backup:"-"`
|
ID int `db:"id" json:"id" backup:"-"`
|
||||||
Name string `db:"name" json:"name"`
|
|
||||||
IntegrationID int `db:"integration_id" json:"integration_id" backup:"-"`
|
IntegrationID int `db:"integration_id" json:"integration_id" backup:"-"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
ValueSource IntegrationExtractValueSource `db:"value_source" json:"value_source"`
|
ValueSource IntegrationExtractValueSource `db:"value_source" json:"value_source"`
|
||||||
BodyDataType IntegrationBodyDataType `db:"body_data_type" json:"body_data_type"`
|
BodyDataType IntegrationBodyDataType `db:"body_data_type" json:"body_data_type"`
|
||||||
Key string `db:"key" json:"key"`
|
Key string `db:"key" json:"key"`
|
||||||
|
@ -108,53 +108,89 @@ func (b *BackupDB) makeUniqueNames() {
|
|||||||
}, func(item *db.View, name string) {
|
}, func(item *db.View, name string) {
|
||||||
item.Title = name
|
item.Title = name
|
||||||
})
|
})
|
||||||
|
|
||||||
|
makeUniqueNames(b.integrations, func(item *db.Integration) string {
|
||||||
|
return item.Name
|
||||||
|
}, func(item *db.Integration, name string) {
|
||||||
|
item.Name = name
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BackupDB) new(projectID int, store db.Store) (*BackupDB, error) {
|
func (b *BackupDB) load(projectID int, store db.Store) (err error) {
|
||||||
var err error
|
|
||||||
|
|
||||||
b.templates, err = store.GetTemplates(projectID, db.TemplateFilter{}, db.RetrieveQueryParams{})
|
b.templates, err = store.GetTemplates(projectID, db.TemplateFilter{}, db.RetrieveQueryParams{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b.repositories, err = store.GetRepositories(projectID, db.RetrieveQueryParams{})
|
b.repositories, err = store.GetRepositories(projectID, db.RetrieveQueryParams{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b.keys, err = store.GetAccessKeys(projectID, db.RetrieveQueryParams{})
|
b.keys, err = store.GetAccessKeys(projectID, db.RetrieveQueryParams{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b.views, err = store.GetViews(projectID)
|
b.views, err = store.GetViews(projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b.inventories, err = store.GetInventories(projectID, db.RetrieveQueryParams{})
|
b.inventories, err = store.GetInventories(projectID, db.RetrieveQueryParams{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b.environments, err = store.GetEnvironments(projectID, db.RetrieveQueryParams{})
|
b.environments, err = store.GetEnvironments(projectID, db.RetrieveQueryParams{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
schedules, err := store.GetSchedules()
|
schedules, err := store.GetSchedules()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b.schedules = getSchedulesByProject(projectID, schedules)
|
b.schedules = getSchedulesByProject(projectID, schedules)
|
||||||
|
|
||||||
b.meta, err = store.GetProject(projectID)
|
b.meta, err = store.GetProject(projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b.integrationProjAliases, err = store.GetIntegrationAliases(projectID, nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b.integrations, err = store.GetIntegrations(projectID, db.RetrieveQueryParams{})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b.integrationAliases = make(map[int][]db.IntegrationAlias)
|
||||||
|
b.integrationMatchers = make(map[int][]db.IntegrationMatcher)
|
||||||
|
b.integrationExtractValues = make(map[int][]db.IntegrationExtractValue)
|
||||||
|
for _, o := range b.integrations {
|
||||||
|
b.integrationAliases[o.ID], err = store.GetIntegrationAliases(projectID, &o.ID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.integrationMatchers[o.ID], err = store.GetIntegrationMatchers(projectID, db.RetrieveQueryParams{}, o.ID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.integrationExtractValues[o.ID], err = store.GetIntegrationExtractValues(projectID, db.RetrieveQueryParams{}, o.ID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b.makeUniqueNames()
|
b.makeUniqueNames()
|
||||||
|
|
||||||
return b, nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BackupDB) format() (*BackupFormat, error) {
|
func (b *BackupDB) format() (*BackupFormat, error) {
|
||||||
@ -247,25 +283,64 @@ func (b *BackupDB) format() (*BackupFormat, error) {
|
|||||||
Vaults: vaults,
|
Vaults: vaults,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
integrations := make([]BackupIntegration, len(b.integrations))
|
||||||
|
for i, o := range b.integrations {
|
||||||
|
|
||||||
|
var aliases []string
|
||||||
|
|
||||||
|
for _, a := range b.integrationAliases[o.ID] {
|
||||||
|
aliases = append(aliases, a.Alias)
|
||||||
|
}
|
||||||
|
|
||||||
|
tplName, _ := findNameByID[db.Template](o.TemplateID, b.templates)
|
||||||
|
|
||||||
|
if tplName == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var keyName *string
|
||||||
|
|
||||||
|
if o.AuthSecretID != nil {
|
||||||
|
keyName, _ = findNameByID[db.AccessKey](*o.AuthSecretID, b.keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
integrations[i] = BackupIntegration{
|
||||||
|
Integration: o,
|
||||||
|
Aliases: aliases,
|
||||||
|
Matchers: b.integrationMatchers[o.ID],
|
||||||
|
ExtractValues: b.integrationExtractValues[o.ID],
|
||||||
|
Template: *tplName,
|
||||||
|
AuthSecret: keyName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var integrationAliases []string
|
||||||
|
|
||||||
|
for _, alias := range b.integrationProjAliases {
|
||||||
|
integrationAliases = append(integrationAliases, alias.Alias)
|
||||||
|
}
|
||||||
|
|
||||||
return &BackupFormat{
|
return &BackupFormat{
|
||||||
Meta: BackupMeta{
|
Meta: BackupMeta{
|
||||||
b.meta,
|
b.meta,
|
||||||
},
|
},
|
||||||
Inventories: inventories,
|
Inventories: inventories,
|
||||||
Environments: environments,
|
Environments: environments,
|
||||||
Views: views,
|
Views: views,
|
||||||
Repositories: repositories,
|
Repositories: repositories,
|
||||||
Keys: keys,
|
Keys: keys,
|
||||||
Templates: templates,
|
Templates: templates,
|
||||||
|
Integration: integrations,
|
||||||
|
IntegrationAliases: integrationAliases,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetBackup(projectID int, store db.Store) (*BackupFormat, error) {
|
func GetBackup(projectID int, store db.Store) (*BackupFormat, error) {
|
||||||
backup := BackupDB{}
|
backup := BackupDB{}
|
||||||
if _, err := backup.new(projectID, store); err != nil {
|
if err := backup.load(projectID, store); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return backup.format()
|
return backup.format()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,6 +274,7 @@ func (e BackupTemplate) Restore(store db.Store, b *BackupDB) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.Vaults != nil {
|
if e.Vaults != nil {
|
||||||
for _, vault := range e.Vaults {
|
for _, vault := range e.Vaults {
|
||||||
var VaultKeyID int
|
var VaultKeyID int
|
||||||
@ -297,6 +298,55 @@ func (e BackupTemplate) Restore(store db.Store, b *BackupDB) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e BackupIntegration) Restore(store db.Store, b *BackupDB) error {
|
||||||
|
var authSecretID *int
|
||||||
|
|
||||||
|
if e.AuthSecret == nil {
|
||||||
|
authSecretID = nil
|
||||||
|
} else if k := findEntityByName[db.AccessKey](e.AuthSecret, b.keys); k == nil {
|
||||||
|
authSecretID = nil
|
||||||
|
} else {
|
||||||
|
authSecretID = &((*k).ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
tpl := findEntityByName[db.Template](&e.Template, b.templates)
|
||||||
|
if tpl == nil {
|
||||||
|
return fmt.Errorf("template does not exist in templates[].name")
|
||||||
|
}
|
||||||
|
|
||||||
|
integration := e.Integration
|
||||||
|
integration.ProjectID = b.meta.ID
|
||||||
|
integration.AuthSecretID = authSecretID
|
||||||
|
integration.TemplateID = tpl.ID
|
||||||
|
|
||||||
|
newIntegration, err := store.CreateIntegration(integration)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.integrations = append(b.integrations, newIntegration)
|
||||||
|
|
||||||
|
for _, m := range e.Matchers {
|
||||||
|
m.IntegrationID = newIntegration.ID
|
||||||
|
_, _ = store.CreateIntegrationMatcher(b.meta.ID, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range e.ExtractValues {
|
||||||
|
v.IntegrationID = newIntegration.ID
|
||||||
|
_, _ = store.CreateIntegrationExtractValue(b.meta.ID, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, a := range e.Aliases {
|
||||||
|
alias := db.IntegrationAlias{
|
||||||
|
Alias: a,
|
||||||
|
ProjectID: b.meta.ID,
|
||||||
|
IntegrationID: &newIntegration.ID,
|
||||||
|
}
|
||||||
|
_, _ = store.CreateIntegrationAlias(alias)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (backup *BackupFormat) Verify() error {
|
func (backup *BackupFormat) Verify() error {
|
||||||
for i, o := range backup.Environments {
|
for i, o := range backup.Environments {
|
||||||
if err := o.Verify(backup); err != nil {
|
if err := o.Verify(backup); err != nil {
|
||||||
@ -399,5 +449,19 @@ func (backup *BackupFormat) Restore(user db.User, store db.Store) (*db.Project,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i, o := range backup.Integration {
|
||||||
|
if err := o.Restore(store, &b); err != nil {
|
||||||
|
return nil, fmt.Errorf("error at integrations[%d]: %s", i, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range backup.IntegrationAliases {
|
||||||
|
alias := db.IntegrationAlias{
|
||||||
|
Alias: o,
|
||||||
|
ProjectID: b.meta.ID,
|
||||||
|
}
|
||||||
|
_, _ = store.CreateIntegrationAlias(alias)
|
||||||
|
}
|
||||||
|
|
||||||
return &newProject, nil
|
return &newProject, nil
|
||||||
}
|
}
|
||||||
|
@ -13,16 +13,24 @@ type BackupDB struct {
|
|||||||
inventories []db.Inventory
|
inventories []db.Inventory
|
||||||
environments []db.Environment
|
environments []db.Environment
|
||||||
schedules []db.Schedule
|
schedules []db.Schedule
|
||||||
|
|
||||||
|
integrationProjAliases []db.IntegrationAlias
|
||||||
|
integrations []db.Integration
|
||||||
|
integrationAliases map[int][]db.IntegrationAlias
|
||||||
|
integrationMatchers map[int][]db.IntegrationMatcher
|
||||||
|
integrationExtractValues map[int][]db.IntegrationExtractValue
|
||||||
}
|
}
|
||||||
|
|
||||||
type BackupFormat struct {
|
type BackupFormat struct {
|
||||||
Meta BackupMeta `backup:"meta"`
|
Meta BackupMeta `backup:"meta"`
|
||||||
Templates []BackupTemplate `backup:"templates"`
|
Templates []BackupTemplate `backup:"templates"`
|
||||||
Repositories []BackupRepository `backup:"repositories"`
|
Repositories []BackupRepository `backup:"repositories"`
|
||||||
Keys []BackupAccessKey `backup:"keys"`
|
Keys []BackupAccessKey `backup:"keys"`
|
||||||
Views []BackupView `backup:"views"`
|
Views []BackupView `backup:"views"`
|
||||||
Inventories []BackupInventory `backup:"inventories"`
|
Inventories []BackupInventory `backup:"inventories"`
|
||||||
Environments []BackupEnvironment `backup:"environments"`
|
Environments []BackupEnvironment `backup:"environments"`
|
||||||
|
Integration []BackupIntegration `backup:"integrations"`
|
||||||
|
IntegrationAliases []string `backup:"integration_aliases"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BackupMeta struct {
|
type BackupMeta struct {
|
||||||
@ -72,6 +80,15 @@ type BackupTemplateVault struct {
|
|||||||
VaultKey string `backup:"vault_key"`
|
VaultKey string `backup:"vault_key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BackupIntegration struct {
|
||||||
|
db.Integration
|
||||||
|
Aliases []string `backup:"aliases"`
|
||||||
|
Matchers []db.IntegrationMatcher `backup:"matchers"`
|
||||||
|
ExtractValues []db.IntegrationExtractValue `backup:"extract_values"`
|
||||||
|
Template string `backup:"template"`
|
||||||
|
AuthSecret *string `backup:"auth_secret"`
|
||||||
|
}
|
||||||
|
|
||||||
type BackupEntry interface {
|
type BackupEntry interface {
|
||||||
GetName() string
|
GetName() string
|
||||||
Verify(backup *BackupFormat) error
|
Verify(backup *BackupFormat) error
|
||||||
|
Loading…
Reference in New Issue
Block a user