Merge pull request #2553 from Omicron7/improve-rest-api-and-docs

chore: Improve API docs and fix REST issues.
This commit is contained in:
Denis Gukov 2024-11-26 01:13:09 +05:00 committed by GitHub
commit db8c24dbcb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 249 additions and 53 deletions

View File

@ -107,12 +107,19 @@ func resolveCapability(caps []string, resolved []string, uid string) {
SSHKeyID: &userKey.ID,
BecomeKeyID: &userKey.ID,
Inventory: "Test Inventory",
RepositoryID: &repoID,
})
printError(err)
inventoryID = res.ID
case "environment":
pwd := "test-pass"
env := "{}"
secret := db.EnvironmentSecret{
Type: db.EnvironmentSecretEnv,
Name: "TEST",
Secret: "VALUE",
Operation: "create",
}
res, err := store.CreateEnvironment(db.Environment{
ProjectID: userProject.ID,
Name: "ITI-" + uid,
@ -121,6 +128,14 @@ func resolveCapability(caps []string, resolved []string, uid string) {
ENV: &env,
})
printError(err)
_, err = store.CreateAccessKey(db.AccessKey{
Name: string(secret.Type) + "." + secret.Name,
String: secret.Secret,
EnvironmentID: &res.ID,
ProjectID: &userProject.ID,
Type: db.AccessKeyString,
})
printError(err)
environmentID = res.ID
case "template":
args := "[]"
@ -139,6 +154,7 @@ func resolveCapability(caps []string, resolved []string, uid string) {
ViewID: &view.ID,
App: db.AppAnsible,
GitBranch: &branch,
SurveyVars: []db.SurveyVar{},
})
printError(err)
@ -218,6 +234,7 @@ func alterRequestBody(t *trans.Transaction) {
bodyFieldProcessor("inventory_id", inventoryID, &request)
bodyFieldProcessor("repository_id", repoID, &request)
bodyFieldProcessor("template_id", templateID, &request)
bodyFieldProcessor("build_template_id", nil, &request)
if task != nil {
bodyFieldProcessor("task_id", task.ID, &request)
}

View File

@ -93,17 +93,22 @@ func main() {
h.Before("integration > /api/project/{project_id}/integrations/{integration_id}/matchers > Add Integration Matcher > 204 > application/json", capabilityWrapper("integration"))
h.Before("integration > /api/project/{project_id}/integrations/{integration_id}/matchers/{matcher_id} > Updates Integration Matcher > 204 > application/json", capabilityWrapper("integrationmatcher"))
h.Before("project > /api/project/{project_id}/keys > Add access key > 201 > application/json", capabilityWrapper("access_key"))
h.Before("project > /api/project/{project_id}/keys/{key_id} > Updates access key > 204 > application/json", capabilityWrapper("access_key"))
h.Before("project > /api/project/{project_id}/keys/{key_id} > Removes access key > 204 > application/json", capabilityWrapper("access_key"))
h.Before("project > /api/project/{project_id}/repositories > Add repository > 204 > application/json", capabilityWrapper("access_key"))
h.Before("project > /api/project/{project_id}/repositories > Add repository > 201 > application/json", capabilityWrapper("access_key"))
h.Before("project > /api/project/{project_id}/repositories/{repository_id} > Get repository > 200 > application/json", capabilityWrapper("repository"))
h.Before("project > /api/project/{project_id}/repositories/{repository_id} > Updates repository > 204 > application/json", capabilityWrapper("repository"))
h.Before("project > /api/project/{project_id}/repositories/{repository_id} > Removes repository > 204 > application/json", capabilityWrapper("repository"))
h.Before("project > /api/project/{project_id}/inventory > create inventory > 201 > application/json", capabilityWrapper("inventory"))
h.Before("project > /api/project/{project_id}/inventory/{inventory_id} > Get inventory > 200 > application/json", capabilityWrapper("inventory"))
h.Before("project > /api/project/{project_id}/inventory/{inventory_id} > Updates inventory > 204 > application/json", capabilityWrapper("inventory"))
h.Before("project > /api/project/{project_id}/inventory/{inventory_id} > Removes inventory > 204 > application/json", capabilityWrapper("inventory"))
h.Before("project > /api/project/{project_id}/environment > Add environment > 201 > application/json", capabilityWrapper("environment"))
h.Before("project > /api/project/{project_id}/environment/{environment_id} > Get environment > 200 > application/json", capabilityWrapper("environment"))
h.Before("project > /api/project/{project_id}/environment/{environment_id} > Update environment > 204 > application/json", capabilityWrapper("environment"))
h.Before("project > /api/project/{project_id}/environment/{environment_id} > Removes environment > 204 > application/json", capabilityWrapper("environment"))

View File

@ -80,10 +80,15 @@ definitions:
type: string
x-example: test@ansiblesemaphore.test
example: test@ansiblesemaphore.test
password:
type: string
format: password
alert:
type: boolean
admin:
type: boolean
external:
type: boolean
UserPutRequest:
type: object
@ -104,6 +109,7 @@ definitions:
type: boolean
admin:
type: boolean
User:
type: object
properties:
@ -122,6 +128,8 @@ definitions:
type: boolean
admin:
type: boolean
external:
type: boolean
ProjectUser:
type: object
@ -133,10 +141,13 @@ definitions:
type: string
username:
type: string
role:
type: string
enum: [owner, manager, task_runner, guest]
ProjectBackup:
type: object
example: {"meta":{"name":"homelab","alert":true,"alert_chat":"Test","max_parallel_tasks":0},"templates":[{"inventory":"Build","repository":"Demo","environment":"Empty","name":"Build","playbook":"build.yml","arguments":"[]","allow_override_args_in_task":false,"description":"Build Job","vault_key":null,"type":"build","start_version":"1.0.0","build_template":null,"view":"Build","autorun":false,"survey_vars":[],"suppress_success_alerts":false,"cron":"* * * * *"}],"repositories":[{"name":"Demo","git_url":"https://github.com/semaphoreui/demo-project.git","git_branch":"main","ssh_key":"None"}],"keys":[{"name":"None","type":"none"},{"name":"Vault Password","type":"login_password"}],"views":[{"title":"Build","position":0}],"inventories":[{"name":"Build","inventory":"","ssh_key":"None","become_key":"None","type":"static"},{"name":"Dev","inventory":"","ssh_key":"None","become_key":"None","type":"file"},{"name":"Prod","inventory":"","ssh_key":"None","become_key":"None","type":"file"}],"environments":[{"name":"Empty","password":null,"json":"{}","env":null}]}
example: {"meta":{"name":"homelab","alert":true,"alert_chat":"Test","max_parallel_tasks":0,"type":null},"templates":[{"inventory":"Build","repository":"Demo","environment":"Empty","name":"Build","playbook":"build.yml","arguments":"[]","allow_override_args_in_task":false,"description":"Build Job","vault_key":null,"type":"build","start_version":"1.0.0","build_template":null,"view":"Build","autorun":false,"survey_vars":[],"suppress_success_alerts":false,"cron":"* * * * *"}],"repositories":[{"name":"Demo","git_url":"https://github.com/semaphoreui/demo-project.git","git_branch":"main","ssh_key":"None"}],"keys":[{"name":"None","type":"none"},{"name":"Vault Password","type":"login_password"}],"views":[{"title":"Build","position":0}],"inventories":[{"name":"Build","inventory":"","ssh_key":"None","become_key":"None","type":"static"},{"name":"Dev","inventory":"","ssh_key":"None","become_key":"None","type":"file"},{"name":"Prod","inventory":"","ssh_key":"None","become_key":"None","type":"file"}],"environments":[{"name":"Empty","password":null,"json":"{}","env":null}]}
properties:
meta:
type: object
@ -152,6 +163,10 @@ definitions:
max_parallel_tasks:
type: integer
minimum: 0
type:
type:
- string
- 'null'
templates:
type: array
items:
@ -304,6 +319,13 @@ definitions:
max_parallel_tasks:
type: integer
minimum: 0
type:
type:
- string
- 'null'
demo:
description: Create Demo project resources?
type: boolean
Project:
type: object
properties:
@ -326,10 +348,16 @@ definitions:
max_parallel_tasks:
type: integer
minimum: 0
type:
type:
- string
- 'null'
AccessKeyRequest:
type: object
properties:
id:
type: integer
name:
type: string
x-example: None
@ -342,6 +370,8 @@ definitions:
type: integer
minimum: 1
x-example: 2
override_secret:
type: boolean
login_password:
type: object
properties:
@ -360,6 +390,10 @@ definitions:
type: string
x-example: user
example: user
passphrase:
type: string
x-example: passphrase
example: passphrase
private_key:
type: string
x-example: private key
@ -378,32 +412,40 @@ definitions:
enum: [none, ssh, login_password]
project_id:
type: integer
login_password:
EnvironmentSecret:
type: object
properties:
password:
id:
type: integer
name:
type: string
x-example: password
example: password
login:
type:
type: string
x-example: username
example: username
ssh:
enum: [env, var]
EnvironmentSecretRequest:
type: object
properties:
login:
id:
type: integer
name:
type: string
x-example: user
example: user
private_key:
secret:
type: string
x-example: private key
example: private key
type:
type: string
enum: [env, var]
operation:
type: string
enum: [create, update, delete]
EnvironmentRequest:
type: object
properties:
id:
type: integer
example: 1
name:
type: string
example: Test
@ -418,6 +460,10 @@ definitions:
env:
type: string
example: '{}'
secrets:
type: array
items:
$ref: '#/definitions/EnvironmentSecretRequest'
Environment:
type: object
@ -439,10 +485,16 @@ definitions:
env:
type: string
example: '{}'
secrets:
type: array
items:
$ref: '#/definitions/EnvironmentSecret'
InventoryRequest:
type: object
properties:
id:
type: integer
name:
type: string
example: Test
@ -457,9 +509,12 @@ definitions:
become_key_id:
type: integer
minimum: 1
repository_id:
type: integer
minimum: 1
type:
type: string
enum: [static, static-yaml, file]
enum: [static, static-yaml, file, terraform-workspace]
Inventory:
type: object
@ -477,9 +532,11 @@ definitions:
type: integer
become_key_id:
type: integer
repository_id:
type: integer
type:
type: string
enum: [static, static-yaml, file]
enum: [static, static-yaml, file, terraform-workspace]
Integration:
type: object
@ -600,6 +657,8 @@ definitions:
RepositoryRequest:
type: object
properties:
id:
type: integer
name:
type: string
example: Test
@ -674,6 +733,9 @@ definitions:
TemplateRequest:
type: object
properties:
id:
type: integer
example: 1
project_id:
type: integer
minimum: 1
@ -723,6 +785,16 @@ definitions:
type: array
items:
$ref: "#/definitions/TemplateSurveyVar"
type:
type: string
enum: ["", build, deploy]
start_version:
type: string
build_template_id:
type: integer
autorun:
type: boolean
Template:
type: object
properties:
@ -765,6 +837,28 @@ definitions:
git_branch:
type: string
example: main
type:
type: string
enum: ["", build, deploy]
start_version:
type:
- string
- 'null'
build_template_id:
type:
- integer
- 'null'
autorun:
type: boolean
survey_vars:
type: array
items:
$ref: "#/definitions/TemplateSurveyVar"
vaults:
type: array
items:
$ref: "#/definitions/TemplateVault"
TemplateSurveyVar:
type: object
properties:
@ -776,12 +870,28 @@ definitions:
type: string
type:
type: string
example: String => "", Integer => "int"
enum: ["", int, enum, secret] # String => "", Integer => "int"
example: int
required:
type: boolean
values:
type: array
items:
$ref: "#/definitions/TemplateSurveyVarValue"
TemplateSurveyVarValue:
type: object
properties:
name:
type: string
value:
type: string
TemplateVault:
type: object
properties:
id:
type: integer
name:
type: string
example: default
@ -797,6 +907,7 @@ definitions:
type:
- string
- 'null'
example: path/to/script-client.py
ScheduleRequest:
type: object
@ -1283,6 +1394,8 @@ paths:
responses:
201:
description: Created project
schema:
$ref: "#/definitions/Project"
/projects/restore:
post:
tags:
@ -1344,10 +1457,12 @@ paths:
in: body
required: true
schema:
type: object
properties:
name:
type: string
allOf:
- $ref: '#/definitions/ProjectRequest'
- properties:
id:
type: integer
minimum: 1
responses:
204:
description: Project saved
@ -1483,6 +1598,8 @@ paths:
enum: [owner, manager, task_runner, guest]
example: owner
summary: Update user role
tags:
- project
responses:
204:
description: User updated
@ -1704,8 +1821,10 @@ paths:
schema:
$ref: "#/definitions/AccessKeyRequest"
responses:
204:
201:
description: Access Key created
schema:
$ref: "#/definitions/AccessKey"
400:
description: Bad type
/project/{project_id}/keys/{key_id}:
@ -1775,12 +1894,24 @@ paths:
schema:
$ref: "#/definitions/RepositoryRequest"
responses:
204:
201:
description: Repository created
schema:
$ref: "#/definitions/Repository"
/project/{project_id}/repositories/{repository_id}:
parameters:
- $ref: "#/parameters/project_id"
- $ref: "#/parameters/repository_id"
get:
tags:
- project
summary: Get repository
responses:
200:
description: repository object
schema:
$ref: "#/definitions/Repository"
put:
tags:
- project
@ -1851,6 +1982,15 @@ paths:
parameters:
- $ref: "#/parameters/project_id"
- $ref: "#/parameters/inventory_id"
get:
tags:
- project
summary: Get inventory
responses:
200:
description: inventory object
schema:
$ref: "#/definitions/Inventory"
put:
tags:
- project
@ -1913,12 +2053,23 @@ paths:
schema:
$ref: "#/definitions/EnvironmentRequest"
responses:
204:
201:
description: Environment created
schema:
$ref: "#/definitions/Environment"
/project/{project_id}/environment/{environment_id}:
parameters:
- $ref: "#/parameters/project_id"
- $ref: "#/parameters/environment_id"
get:
tags:
- project
summary: Get environment
responses:
200:
description: environment object
schema:
$ref: "#/definitions/Environment"
put:
tags:
- project
@ -1980,7 +2131,7 @@ paths:
- project
summary: create template
parameters:
- name: templateyes
- name: template
in: body
required: true
schema:
@ -1989,7 +2140,7 @@ paths:
201:
description: template created
schema:
$ref: "#/definitions/TemplateRequest"
$ref: "#/definitions/Template"
/project/{project_id}/templates/{template_id}:
parameters:
- $ref: "#/parameters/project_id"

View File

@ -50,11 +50,18 @@ func updateEnvironmentSecrets(store db.Store, env db.Environment) error {
continue
}
err = store.UpdateAccessKey(db.AccessKey{
updateKey := db.AccessKey{
ID: key.ID,
ProjectID: key.ProjectID,
Name: string(secret.Type) + "." + secret.Name,
String: secret.Secret,
Type: db.AccessKeyString,
})
}
if secret.Secret != "" {
updateKey.String = secret.Secret
updateKey.OverrideSecret = true
}
err = store.UpdateAccessKey(updateKey)
}
}
@ -197,7 +204,16 @@ func AddEnvironment(w http.ResponseWriter, r *http.Request) {
//return
}
w.WriteHeader(http.StatusNoContent)
// Reload env
env, err = helpers.Store(r).GetEnvironment(newEnv.ProjectID, newEnv.ID)
if err != nil {
helpers.WriteError(w, err)
return
}
// Use empty array to avoid null in JSON
env.Secrets = []db.EnvironmentSecret{}
helpers.WriteJSON(w, http.StatusCreated, env)
}
// RemoveEnvironment deletes an environment from the database

View File

@ -101,7 +101,14 @@ func AddKey(w http.ResponseWriter, r *http.Request) {
Description: fmt.Sprintf("Access Key %s created", key.Name),
})
w.WriteHeader(http.StatusNoContent)
// Reload key to drop sensitive fields
key, err = helpers.Store(r).GetAccessKey(*newKey.ProjectID, newKey.ID)
if err != nil {
helpers.WriteError(w, err)
return
}
helpers.WriteJSON(w, http.StatusCreated, key)
}
// UpdateKey updates key in database

View File

@ -5,10 +5,10 @@ import (
"fmt"
"net/http"
"github.com/gorilla/context"
"github.com/semaphoreui/semaphore/api/helpers"
"github.com/semaphoreui/semaphore/db"
"github.com/semaphoreui/semaphore/util"
"github.com/gorilla/context"
)
// RepositoryMiddleware ensures a repository exists and loads it to the context
@ -98,7 +98,7 @@ func AddRepository(w http.ResponseWriter, r *http.Request) {
Description: fmt.Sprintf("Repository %s created", repository.GitURL),
})
w.WriteHeader(http.StatusNoContent)
helpers.WriteJSON(w, http.StatusCreated, newRepo)
}
// UpdateRepository updates the values of a repository in the database

View File

@ -11,8 +11,8 @@ func (d *SqlDb) CreateProject(project db.Project) (newProject db.Project, err er
insertId, err := d.insert(
"id",
"insert into project(name, created, type) values (?, ?, ?)",
project.Name, project.Created, project.Type)
"insert into project(name, created, type, alert, alert_chat, max_parallel_tasks) values (?, ?, ?, ?, ?, ?)",
project.Name, project.Created, project.Type, project.Alert, project.AlertChat, project.MaxParallelTasks)
if err != nil {
return