mirror of
https://github.com/semaphoreui/semaphore.git
synced 2024-11-23 20:35:24 +01:00
feat(apps): add migration '' -> 'ansible'
This commit is contained in:
parent
c4916703f0
commit
26c3479f8a
@ -70,6 +70,7 @@ func GetMigrations() []Migration {
|
|||||||
{Version: "2.9.100"},
|
{Version: "2.9.100"},
|
||||||
{Version: "2.10.12"},
|
{Version: "2.10.12"},
|
||||||
{Version: "2.10.15"},
|
{Version: "2.10.15"},
|
||||||
|
{Version: "2.10.16"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@ func (d *BoltDb) ApplyMigration(m db.Migration) (err error) {
|
|||||||
err = migration_2_8_91{migration{d.db}}.Apply()
|
err = migration_2_8_91{migration{d.db}}.Apply()
|
||||||
case "2.10.12":
|
case "2.10.12":
|
||||||
err = migration_2_10_12{migration{d.db}}.Apply()
|
err = migration_2_10_12{migration{d.db}}.Apply()
|
||||||
|
case "2.10.16":
|
||||||
|
err = migration_2_10_16{migration{d.db}}.Apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
38
db/bolt/migration_2_10_16.go
Normal file
38
db/bolt/migration_2_10_16.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package bolt
|
||||||
|
|
||||||
|
type migration_2_10_16 struct {
|
||||||
|
migration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d migration_2_10_16) Apply() (err error) {
|
||||||
|
projectIDs, err := d.getProjectIDs()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
templates := make(map[string]map[string]map[string]interface{})
|
||||||
|
|
||||||
|
for _, projectID := range projectIDs {
|
||||||
|
var err2 error
|
||||||
|
templates[projectID], err2 = d.getObjects(projectID, "template")
|
||||||
|
if err2 != nil {
|
||||||
|
return err2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for projectID, projectTemplates := range templates {
|
||||||
|
for repoID, tpl := range projectTemplates {
|
||||||
|
if tpl["app"] != nil && tpl["app"] != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tpl["app"] = "ansible"
|
||||||
|
err = d.setObject(projectID, "template", repoID, tpl)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
88
db/bolt/migration_2_10_16_test.go
Normal file
88
db/bolt/migration_2_10_16_test.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package bolt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"go.etcd.io/bbolt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMigration_2_10_16_Apply(t *testing.T) {
|
||||||
|
store := CreateTestStore()
|
||||||
|
|
||||||
|
err := store.db.Update(func(tx *bbolt.Tx) error {
|
||||||
|
b, err := tx.CreateBucketIfNotExists([]byte("project"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = b.Put([]byte("0000000001"), []byte("{}"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := tx.CreateBucketIfNotExists([]byte("project__template_0000000001"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = r.Put([]byte("0000000001"),
|
||||||
|
[]byte("{\"id\":\"1\",\"project_id\":\"1\"}"))
|
||||||
|
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = migration_2_10_16{migration{store.db}}.Apply()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var repo map[string]interface{}
|
||||||
|
err = store.db.View(func(tx *bbolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte("project__template_0000000001"))
|
||||||
|
str := string(b.Get([]byte("0000000001")))
|
||||||
|
return json.Unmarshal([]byte(str), &repo)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if repo["app"] == nil {
|
||||||
|
t.Fatal("app must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
if repo["app"].(string) != "ansible" {
|
||||||
|
t.Fatal("invalid app: " + repo["app"].(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if repo["alias"] != nil {
|
||||||
|
t.Fatal("alias must be deleted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMigration_2_10_16_Apply2(t *testing.T) {
|
||||||
|
store := CreateTestStore()
|
||||||
|
|
||||||
|
err := store.db.Update(func(tx *bbolt.Tx) error {
|
||||||
|
b, err := tx.CreateBucketIfNotExists([]byte("project"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = b.Put([]byte("0000000001"), []byte("{}"))
|
||||||
|
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = migration_2_10_16{migration{store.db}}.Apply()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
1
db/sql/migrations/v2.10.16.sql
Normal file
1
db/sql/migrations/v2.10.16.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
update `project__template` set `app` = 'ansible' where `app` = '';
|
@ -11,8 +11,7 @@
|
|||||||
@save="onSave"
|
@save="onSave"
|
||||||
>
|
>
|
||||||
<template v-slot:form="{ onSave, onError, needSave, needReset }">
|
<template v-slot:form="{ onSave, onError, needSave, needReset }">
|
||||||
<TerraformTemplateForm
|
<TemplateForm
|
||||||
v-if="['terraform', 'tofu'].includes(itemApp)"
|
|
||||||
:project-id="projectId"
|
:project-id="projectId"
|
||||||
:item-id="itemId"
|
:item-id="itemId"
|
||||||
@save="onSave"
|
@save="onSave"
|
||||||
@ -21,27 +20,7 @@
|
|||||||
:need-reset="needReset"
|
:need-reset="needReset"
|
||||||
:source-item-id="sourceItemId"
|
:source-item-id="sourceItemId"
|
||||||
:app="itemApp"
|
:app="itemApp"
|
||||||
/>
|
:fields="fields"
|
||||||
<TemplateForm
|
|
||||||
v-else-if="['', 'ansible'].includes(itemApp)"
|
|
||||||
:project-id="projectId"
|
|
||||||
:item-id="itemId"
|
|
||||||
@save="onSave"
|
|
||||||
@error="onError"
|
|
||||||
:need-save="needSave"
|
|
||||||
:need-reset="needReset"
|
|
||||||
:source-item-id="sourceItemId"
|
|
||||||
/>
|
|
||||||
<ShellTemplateForm
|
|
||||||
v-else
|
|
||||||
:project-id="projectId"
|
|
||||||
:item-id="itemId"
|
|
||||||
@save="onSave"
|
|
||||||
@error="onError"
|
|
||||||
:need-save="needSave"
|
|
||||||
:need-reset="needReset"
|
|
||||||
:source-item-id="sourceItemId"
|
|
||||||
:app-id="itemApp"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</EditDialog>
|
</EditDialog>
|
||||||
@ -53,16 +32,57 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import TerraformTemplateForm from './TerraformTemplateForm.vue';
|
|
||||||
import ShellTemplateForm from './ShellTemplateForm.vue';
|
|
||||||
import TemplateForm from './TemplateForm.vue';
|
import TemplateForm from './TemplateForm.vue';
|
||||||
import EditDialog from './EditDialog.vue';
|
import EditDialog from './EditDialog.vue';
|
||||||
import AppsMixin from './AppsMixin';
|
import AppsMixin from './AppsMixin';
|
||||||
|
|
||||||
|
const ANSIBLE_FIELDS = {
|
||||||
|
playbook: {
|
||||||
|
label: 'playbookFilename',
|
||||||
|
},
|
||||||
|
inventory: {
|
||||||
|
label: 'inventory2',
|
||||||
|
},
|
||||||
|
repository: {
|
||||||
|
label: 'repository',
|
||||||
|
},
|
||||||
|
environment: {
|
||||||
|
label: 'environment3',
|
||||||
|
},
|
||||||
|
vault: {
|
||||||
|
label: 'vaultPassword2',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const TERRAFORM_FIELDS = {
|
||||||
|
...ANSIBLE_FIELDS,
|
||||||
|
playbook: {
|
||||||
|
label: 'Subdirectory path (Optional)',
|
||||||
|
},
|
||||||
|
inventory: {
|
||||||
|
label: 'Default Workspace',
|
||||||
|
},
|
||||||
|
vault: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const UNKNOWN_APP_FIELDS = {
|
||||||
|
...ANSIBLE_FIELDS,
|
||||||
|
playbook: {
|
||||||
|
label: 'Script Filename',
|
||||||
|
},
|
||||||
|
inventory: undefined,
|
||||||
|
vault: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const APP_FIELDS = {
|
||||||
|
'': ANSIBLE_FIELDS,
|
||||||
|
ansible: ANSIBLE_FIELDS,
|
||||||
|
terraform: TERRAFORM_FIELDS,
|
||||||
|
tofu: TERRAFORM_FIELDS,
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ShellTemplateForm,
|
|
||||||
TerraformTemplateForm,
|
|
||||||
TemplateForm,
|
TemplateForm,
|
||||||
EditDialog,
|
EditDialog,
|
||||||
},
|
},
|
||||||
@ -83,6 +103,12 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
fields() {
|
||||||
|
return APP_FIELDS[this.itemApp] || UNKNOWN_APP_FIELDS;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
async dialog(val) {
|
async dialog(val) {
|
||||||
this.$emit('input', val);
|
this.$emit('input', val);
|
||||||
|
@ -148,18 +148,19 @@
|
|||||||
|
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="item.playbook"
|
v-model="item.playbook"
|
||||||
:label="$t('playbookFilename')"
|
:label="fieldLabel('playbook')"
|
||||||
:rules="[v => !!v || $t('playbook_filename_required')]"
|
:rules="[v => !!v || $t('playbook_filename_required')]"
|
||||||
outlined
|
outlined
|
||||||
dense
|
dense
|
||||||
required
|
required
|
||||||
:disabled="formSaving"
|
:disabled="formSaving"
|
||||||
:placeholder="$t('exampleSiteyml')"
|
:placeholder="$t('exampleSiteyml')"
|
||||||
|
v-if="needField('playbook')"
|
||||||
></v-text-field>
|
></v-text-field>
|
||||||
|
|
||||||
<v-select
|
<v-select
|
||||||
v-model="item.inventory_id"
|
v-model="item.inventory_id"
|
||||||
:label="$t('inventory2')"
|
:label="fieldLabel('inventory')"
|
||||||
:items="inventory"
|
:items="inventory"
|
||||||
item-value="id"
|
item-value="id"
|
||||||
item-text="name"
|
item-text="name"
|
||||||
@ -167,11 +168,12 @@
|
|||||||
dense
|
dense
|
||||||
required
|
required
|
||||||
:disabled="formSaving"
|
:disabled="formSaving"
|
||||||
|
v-if="needField('inventory')"
|
||||||
></v-select>
|
></v-select>
|
||||||
|
|
||||||
<v-select
|
<v-select
|
||||||
v-model="item.repository_id"
|
v-model="item.repository_id"
|
||||||
:label="$t('repository') + ' *'"
|
:label="fieldLabel('repository')"
|
||||||
:items="repositories"
|
:items="repositories"
|
||||||
item-value="id"
|
item-value="id"
|
||||||
item-text="name"
|
item-text="name"
|
||||||
@ -180,11 +182,12 @@
|
|||||||
dense
|
dense
|
||||||
required
|
required
|
||||||
:disabled="formSaving"
|
:disabled="formSaving"
|
||||||
|
v-if="needField('repository')"
|
||||||
></v-select>
|
></v-select>
|
||||||
|
|
||||||
<v-select
|
<v-select
|
||||||
v-model="item.environment_id"
|
v-model="item.environment_id"
|
||||||
:label="$t('environment3')"
|
:label="fieldLabel('environment')"
|
||||||
:items="environment"
|
:items="environment"
|
||||||
item-value="id"
|
item-value="id"
|
||||||
item-text="name"
|
item-text="name"
|
||||||
@ -193,12 +196,13 @@
|
|||||||
dense
|
dense
|
||||||
required
|
required
|
||||||
:disabled="formSaving"
|
:disabled="formSaving"
|
||||||
|
v-if="needField('environment')"
|
||||||
></v-select>
|
></v-select>
|
||||||
|
|
||||||
<v-select
|
<v-select
|
||||||
v-if="itemTypeIndex === 0"
|
v-if="itemTypeIndex === 0 && needField('vault')"
|
||||||
v-model="item.vault_key_id"
|
v-model="item.vault_key_id"
|
||||||
:label="$t('vaultPassword')"
|
:label="fieldLabel('vault')"
|
||||||
clearable
|
clearable
|
||||||
:items="loginPasswordKeys"
|
:items="loginPasswordKeys"
|
||||||
item-value="id"
|
item-value="id"
|
||||||
@ -212,9 +216,9 @@
|
|||||||
<v-col cols="12" md="6" class="pb-0">
|
<v-col cols="12" md="6" class="pb-0">
|
||||||
|
|
||||||
<v-select
|
<v-select
|
||||||
v-if="itemTypeIndex > 0"
|
v-if="itemTypeIndex > 0 && needField('vault')"
|
||||||
v-model="item.vault_key_id"
|
v-model="item.vault_key_id"
|
||||||
:label="$t('vaultPassword2')"
|
:label="fieldLabel('vault')"
|
||||||
clearable
|
clearable
|
||||||
:items="loginPasswordKeys"
|
:items="loginPasswordKeys"
|
||||||
item-value="id"
|
item-value="id"
|
||||||
@ -336,6 +340,7 @@ export default {
|
|||||||
|
|
||||||
props: {
|
props: {
|
||||||
sourceItemId: Number,
|
sourceItemId: Number,
|
||||||
|
fields: Array,
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
@ -428,6 +433,14 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
fieldLabel(f) {
|
||||||
|
return this.$t(this.fields[f]);
|
||||||
|
},
|
||||||
|
|
||||||
|
needField(f) {
|
||||||
|
return this.fields[f] != null;
|
||||||
|
},
|
||||||
|
|
||||||
setSurveyVars(v) {
|
setSurveyVars(v) {
|
||||||
this.item.survey_vars = v;
|
this.item.survey_vars = v;
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user