feat(ui): support build/deploy on UI

This commit is contained in:
Denis Gukov 2021-10-12 16:37:51 +05:00
parent 4ef6b5d484
commit 0f72ce182d
7 changed files with 176 additions and 73 deletions

View File

@ -26,25 +26,22 @@ type RetrieveQueryParams struct {
SortInverted bool
}
// ObjectProperties describe database entities.
// It mainly used for NoSQL implementations (currently BoltDB) to preserve same
// data structure of different implementations and easy change it if required.
type ObjectProperties struct {
TableName string
IsGlobal bool // doesn't belong to other table, for example to project or user.
ForeignColumnSuffix string
PrimaryColumnName string
SortableColumns []string
SortInverted bool
Type reflect.Type
SortInverted bool // sort from high to low object ID by default. It is useful for some NoSQL implementations.
Type reflect.Type // to which type the table bust be mapped.
}
var ErrNotFound = errors.New("no rows in result set")
var ErrInvalidOperation = errors.New("invalid operation")
func ValidateUsername(login string) error {
return nil
}
type Transaction interface{}
type Store interface {
Connect() error
Close() error

View File

@ -25,8 +25,9 @@ type Template struct {
VaultKeyID *int `db:"vault_key_id" json:"vault_key_id"`
VaultKey AccessKey `db:"-" json:"-"`
StartVersion *string `db:"start_version" json:"start_version"`
Type string `db:"type" json:"type"`
Type string `db:"type" json:"type"`
StartVersion *string `db:"start_version" json:"start_version"`
BuildTemplateID *int `db:"build_template_id" json:"build_template_id"`
}
func FillTemplate(d Store, template *Template) (err error) {
@ -35,4 +36,3 @@ func FillTemplate(d Store, template *Template) (err error) {
}
return
}

View File

@ -22,3 +22,8 @@ type UserWithPwd struct {
Pwd string `db:"-" json:"password"` // unhashed password from JSON
User
}
func ValidateUsername(login string) error {
return nil
}

View File

@ -1,3 +1,4 @@
alter table `project__template` add `type` varchar(10) not null default 'task';
alter table `project__template` add `start_version` varchar(20);
alter table project__template add `type` varchar(10) not null default 'task';
alter table project__template add start_version varchar(20);
alter table project__template add build_template_id int references project__template(id);
alter table `task` add `version` varchar(20);

View File

@ -10,8 +10,9 @@ func (d *SqlDb) CreateTemplate(template db.Template) (newTemplate db.Template, e
insertID, err := d.insert(
"id",
"insert into project__template (project_id, inventory_id, repository_id, environment_id, " +
"alias, playbook, arguments, override_args, description, vault_key_id)" +
"values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"alias, playbook, arguments, override_args, description, vault_key_id, `type`, start_version," +
"build_template_id)" +
"values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
template.ProjectID,
template.InventoryID,
template.RepositoryID,
@ -21,7 +22,10 @@ func (d *SqlDb) CreateTemplate(template db.Template) (newTemplate db.Template, e
template.Arguments,
template.OverrideArguments,
template.Description,
template.VaultKeyID)
template.VaultKeyID,
template.Type,
template.StartVersion,
template.BuildTemplateID)
if err != nil {
return
@ -40,8 +44,19 @@ func (d *SqlDb) CreateTemplate(template db.Template) (newTemplate db.Template, e
}
func (d *SqlDb) UpdateTemplate(template db.Template) error {
_, err := d.exec("update project__template set inventory_id=?, repository_id=?, environment_id=?, alias=?, " +
"playbook=?, arguments=?, override_args=?, description=?, vault_key_id=? " +
_, err := d.exec("update project__template set " +
"inventory_id=?, " +
"repository_id=?, " +
"environment_id=?, " +
"alias=?, " +
"playbook=?, " +
"arguments=?, " +
"override_args=?, " +
"description=?, " +
"vault_key_id=?, " +
"`type`=?, " +
"start_version=?," +
"build_template_id=? " +
"where removed = false and id=? and project_id=?",
template.InventoryID,
template.RepositoryID,
@ -52,8 +67,12 @@ func (d *SqlDb) UpdateTemplate(template db.Template) error {
template.OverrideArguments,
template.Description,
template.VaultKeyID,
template.Type,
template.StartVersion,
template.BuildTemplateID,
template.ID,
template.ProjectID)
template.ProjectID,
)
return err
}
@ -67,7 +86,8 @@ func (d *SqlDb) GetTemplates(projectID int, params db.RetrieveQueryParams) (temp
"pt.playbook",
"pt.arguments",
"pt.override_args",
"pt.vault_key_id").
"pt.vault_key_id",
"pt.`type`").
From("project__template pt").
Where("pt.removed = false")

View File

@ -30,6 +30,39 @@
placeholder="Example: site.yml"
></v-text-field>
<v-select
v-model="item.type"
label="Type"
:items="types"
item-value="id"
item-text="name"
:rules="[v => !!v || 'Type is required']"
required
:disabled="formSaving"
></v-select>
<v-text-field
v-if="item.type === 'build'"
v-model="item.start_version"
label="Start Version"
:rules="[v => !!v || 'Start Version is required']"
required
:disabled="formSaving"
placeholder="Example: 0.0.0"
></v-text-field>
<v-select
v-if="item.type === 'deploy'"
v-model="item.build_template_id"
label="Build Template"
:items="buildTemplates"
item-value="id"
item-text="alias"
:rules="[v => !!v || 'Build Template is required']"
required
:disabled="formSaving"
></v-select>
<v-select
v-model="item.inventory_id"
label="Inventory"
@ -62,7 +95,9 @@
required
:disabled="formSaving"
></v-select>
</v-col>
<v-col cols="12" md="6" class="pb-0">
<v-select
v-model="item.vault_key_id"
label="Vault Password"
@ -73,16 +108,6 @@
:disabled="formSaving"
></v-select>
<v-text-field
v-model="cronFormat"
label="Cron"
:disabled="formSaving"
placeholder="Example: * 1 * * * *"
v-if="schedules.length <= 1"
></v-text-field>
</v-col>
<v-col cols="12" md="6" class="pb-0">
<v-textarea
outlined
v-model="item.description"
@ -105,6 +130,15 @@ Example:
"-vvvv"
]'
/>
<v-text-field
class="mt-6"
v-model="cronFormat"
label="Cron"
:disabled="formSaving"
placeholder="Example: * 1 * * * *"
v-if="schedules.length <= 1"
></v-text-field>
</v-col>
</v-row>
</v-form>
@ -149,6 +183,16 @@ export default {
environment: null,
schedules: null,
cronFormat: null,
types: [{
id: 'task',
name: 'Task',
}, {
id: 'build',
name: 'Build',
}, {
id: 'deploy',
name: 'Deploy',
}],
};
},
@ -217,6 +261,13 @@ export default {
url: `/api/project/${this.projectId}/environment`,
responseType: 'json',
})).data;
this.buildTemplates = (await axios({
keys: 'get',
url: `/api/project/${this.projectId}/templates?type=build`,
responseType: 'json',
})).data.filter((template) => template.type === 'build');
this.schedules = this.isNew ? [] : (await axios({
keys: 'get',
url: `/api/project/${this.projectId}/templates/${this.itemId}/schedules`,

View File

@ -1,35 +1,35 @@
<template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
<div v-if="!isLoaded">
<v-progress-linear
indeterminate
color="primary darken-2"
indeterminate
color="primary darken-2"
></v-progress-linear>
</div>
<div v-else>
<EditDialog
:max-width="700"
v-model="editDialog"
save-button-text="Create"
title="New template"
@save="loadItems()"
:max-width="700"
v-model="editDialog"
save-button-text="Create"
title="New template"
@save="loadItems()"
>
<template v-slot:form="{ onSave, onError, needSave, needReset }">
<TemplateForm
:project-id="projectId"
item-id="new"
@save="onSave"
@error="onError"
:need-save="needSave"
:need-reset="needReset"
:project-id="projectId"
item-id="new"
@save="onSave"
@error="onError"
:need-save="needSave"
:need-reset="needReset"
/>
</template>
</EditDialog>
<EditDialog
v-model="newTaskDialog"
save-button-text="Run"
title="New Task"
@save="onTaskCreated"
v-model="newTaskDialog"
save-button-text="Run"
title="New Task"
@save="onTaskCreated"
>
<template v-slot:title={}>
<span class="breadcrumbs__item">{{ templateAlias }}</span>
@ -39,13 +39,13 @@
<template v-slot:form="{ onSave, onError, needSave, needReset }">
<TaskForm
:project-id="projectId"
item-id="new"
:template-id="itemId"
@save="onSave"
@error="onError"
:need-save="needSave"
:need-reset="needReset"
:project-id="projectId"
item-id="new"
:template-id="itemId"
@save="onSave"
@error="onError"
:need-save="needSave"
:need-reset="needReset"
/>
</template>
</EditDialog>
@ -55,20 +55,23 @@
<v-toolbar-title>Task Templates</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn
color="primary"
@click="editItem('new')"
class="mr-1"
>New template</v-btn>
color="primary"
@click="editItem('new')"
class="mr-1"
>New template
</v-btn>
<v-btn icon @click="settingsSheet = true"><v-icon>mdi-cog</v-icon></v-btn>
<v-btn icon @click="settingsSheet = true">
<v-icon>mdi-cog</v-icon>
</v-btn>
</v-toolbar>
<v-data-table
:headers="filteredHeaders"
:items="items"
hide-default-footer
class="mt-4"
:items-per-page="Number.MAX_VALUE"
:headers="filteredHeaders"
:items="items"
hide-default-footer
class="mt-4"
:items-per-page="Number.MAX_VALUE"
>
<template v-slot:item.alias="{ item }">
<router-link :to="`/project/${projectId}/templates/${item.id}`">
@ -90,17 +93,17 @@
<template v-slot:item.actions="{ item }">
<v-btn text color="black" class="pl-1 pr-2" @click="createTask(item.id)">
<v-icon class="pr-1">mdi-play</v-icon>
Run
<v-icon class="pr-1">{{ getTemplateActionIcon(item) }}</v-icon>
{{ getTemplateActionTitle(item) }}
</v-btn>
</template>
</v-data-table>
<TableSettingsSheet
v-model="settingsSheet"
table-name="project__template"
:headers="headers"
@change="onTableSettingsChange"
v-model="settingsSheet"
table-name="project__template"
:headers="headers"
@change="onTableSettingsChange"
/>
</div>
</template>
@ -141,9 +144,9 @@ export default {
isLoaded() {
return this.items
&& this.inventory
&& this.environment
&& this.repositories;
&& this.inventory
&& this.environment
&& this.repositories;
},
},
@ -154,6 +157,32 @@ export default {
});
},
getTemplateActionIcon(item) {
switch (item.type) {
case 'task':
return 'mdi-play';
case 'build':
return 'mdi-wrench';
case 'deploy':
return 'mdi-package-up';
default:
throw new Error();
}
},
getTemplateActionTitle(item) {
switch (item.type) {
case 'task':
return 'Run';
case 'build':
return 'Build';
case 'deploy':
return 'Deploy';
default:
throw new Error();
}
},
createTask(itemId) {
this.itemId = itemId;
this.newTaskDialog = true;