Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advanced task and workflows 'apply' command #210

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
743 changes: 743 additions & 0 deletions cmd/apply.go

Large diffs are not rendered by default.

286 changes: 286 additions & 0 deletions cmd/apply_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
package cmd

import (
"github.com/uselagoon/lagoon-cli/internal/lagoon/client"
"github.com/uselagoon/lagoon-cli/internal/schema"
"io"
"net/http"
"net/http/httptest"
"os"
"reflect"
"testing"
)

func TestApplyAdvancedTaskDefinitions(t *testing.T) {
forceAction = true
type testInput struct {
in []AdvancedTasksFileInput
response string
}
var testCases = map[string]struct {
input *testInput
name string
description string
wantErr bool
}{
"valid-tasks": {
input: &testInput{
in: []AdvancedTasksFileInput{
{
ID: 1,
Name: "Custom task",
Description: "A custom advanced task definition",
Type: "COMMAND",
Command: "$BIN_PATH/lagoon-cli",
Service: "cli",
GroupName: "project-high-cotton",
Project: "high-cotton",
Environment: "Master",
EnvironmentID: 3,
Permission: "DEVELOPER",
Arguments: []schema.AdvancedTaskDefinitionArgument{
{
Name: "scan",
Type: "STRING",
},
},
},
},
response: "testdata/addAdvancedTaskResponse.json",
},
},
}

for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
testServer := httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, _ *http.Request) {
file, err := os.Open(tt.input.response)
if err != nil {
t.Fatalf("couldn't open file: %v", err)
}
_, err = io.Copy(w, file)
if err != nil {
t.Fatalf("couldn't write file contents to HTTP: %v", err)
}
}))
defer testServer.Close()
lc := client.New(testServer.URL, "", "", "", false)

if err := ApplyAdvancedTaskDefinitions(lc, tt.input.in); (err != nil) != tt.wantErr {
t.Errorf("ApplyAdvancedTaskDefinitions() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

func TestApplyWorkflows(t *testing.T) {
forceAction = true
type testInput struct {
in []WorkflowsFileInput
response string
}
var testCases = map[string]struct {
input *testInput
name string
description string
wantErr bool
}{
"valid-workflow": {
input: &testInput{
in: []WorkflowsFileInput{
{
ID: 1,
Name: "Teardown ephemeral environment after PR close",
Event: "GithubPRClosed",
AdvancedTaskDefinitionID: 1,
Target: "PROJECT",
Project: "high-cotton",
Environment: "Master",
Cron: "*/15 * * * *",
Settings: Settings{
true,
},
},
},
response: "testdata/addWorkflowResponse.json",
},
description: "Check if valid workflow configuration can be applied",
wantErr: false,
},
}

for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
testServer := httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, _ *http.Request) {
file, err := os.Open(tt.input.response)
if err != nil {
t.Fatalf("couldn't open file: %v", err)
}
_, err = io.Copy(w, file)
if err != nil {
t.Fatalf("couldn't write file contents to HTTP: %v", err)
}
}))
defer testServer.Close()
lc := client.New(testServer.URL, "", "", "", false)

if err := ApplyWorkflows(lc, tt.input.in); (err != nil) != tt.wantErr {
t.Errorf("ApplyWorkflows() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

func TestReadConfigFile(t *testing.T) {
type testInput struct {
in string
}
var testCases = map[string]struct {
input *testInput
name string
description string
want *FileConfigRoot
wantErr bool
}{
"valid-tasks-yaml": {
input: &testInput{
in: "testdata/tasks.yml",
},
wantErr: false,
want: &FileConfigRoot{
Tasks: []AdvancedTasksFileInput{
{
Name: "Custom Advanced Task",
Description: "A custom advanced task defined inside a yml file",
GroupName: "amazeeio",
Project: "high-cotton",
Environment: "Master",
Type: "COMMAND",
Command: "$BIN_PATH/lagoon-cli",
Service: "cli",
Permission: "DEVELOPER",
}, {
Name: "ClamAV scan",
Description: "An anti-virus scan ran from an image",
Project: "high-cotton",
Environment: "Master",
Type: "IMAGE",
Image: "uselagoon/clamav:latest",
Service: "cli",
Permission: "MAINTAINER",
Arguments: []schema.AdvancedTaskDefinitionArgument{
{
Name: "scan",
Type: "STRING",
},
},
},
},
},
},
"invalid-tasks-yaml": {
input: &testInput{
in: "testdata/tasks.yml.invalid",
},
wantErr: true,
want: nil,
},
"valid-workflows-yaml": {
input: &testInput{
in: "testdata/workflows.yml",
},
wantErr: false,
want: &FileConfigRoot{
Workflows: []WorkflowsFileInput{
{
Name: "Teardown ephemeral environment after PR close",
Event: "GithubPRClosed",
AdvancedTaskDefinition: "Teardown PR",
Target: "PROJECT",
Project: "high-cotton",
Environment: "Master",
}, {
Name: "Run ClamAV scan on push",
Event: "GithubPush",
AdvancedTaskDefinition: "ClamAV scan",
Target: "GROUP",
Project: "high-cotton",
Environment: "Master",
},
},
},
},
"invalid-workflows-yaml": {
input: &testInput{
in: "testdata/workflows.yml.invalid",
},
wantErr: true,
want: nil,
},
}

for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
got, err := ReadConfigFile(tt.input.in)
if (err != nil) != tt.wantErr {
t.Errorf("Reading config file error = %v, wantErr %v", err, tt.wantErr)
return
}
if err != nil && !reflect.DeepEqual(got, tt.want) {
t.Errorf("Reading config file does not match: got = %v, want %v", got, tt.want)
}
})
}
}

func Test_validateTasks(t *testing.T) {
type testInput struct {
in string
}
var testCases = map[string]struct {
input *testInput
name string
description string
want string
wantErr bool
}{
"valid-tasks-yaml": {
input: &testInput{
in: "testdata/tasks.yml",
},
description: "Checks to see if valid config does not return an error",
wantErr: false,
want: "",
},
"missing-tasks-config-yaml": {
input: &testInput{
in: "testdata/tasks.yml.missing",
},
description: "Checks to see if invalid config throws an exception",
wantErr: true,
want: "validation checks failed",
},
}

for _, tt := range testCases {
config, err := ReadConfigFile(tt.input.in)
if err != nil {
t.Errorf("Reading config file error = %v", err)
return
}

t.Run(tt.name, func(t *testing.T) {
_, err = PreprocessAdvancedTaskDefinitionsInputValidation(config.Tasks)
if (err != nil) != tt.wantErr {
t.Errorf("Validating config file error = %v, wantErr %v", err, tt.wantErr)
return
}

if err != nil && !reflect.DeepEqual(err.Error(), tt.want) {
t.Errorf("Validating config file checks failed: got = %v, want %v", err, tt.want)
}
})
}
}
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`)
rootCmd.AddCommand(addCmd)
rootCmd.AddCommand(applyCmd)
rootCmd.AddCommand(configCmd)
rootCmd.AddCommand(deleteCmd)
rootCmd.AddCommand(deployCmd)
Expand Down
2 changes: 2 additions & 0 deletions cmd/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ var groupRole string
var jsonPatch string
var revealValue bool
var listAllProjects bool
var showWorkflows bool
var showAdvancedTasks bool
var noHeader bool

// These are available to all cmds and are set either by flags (-p and -e) or via `lagoon-cli/app` when entering a directory that has a valid lagoon project
Expand Down
25 changes: 25 additions & 0 deletions cmd/testdata/addAdvancedTaskResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"data": {
"addAdvancedTaskDefinition": {
"id": 1,
"name": "Custom task",
"description": "A custom advanced task definition",
"type": "COMMAND",
"command": "$BIN_PATH/lagoon-cli",
"service": "cli",
"groupName": "project-high-cotton",
"project": 18,
"environment": 3,
"permission": "DEVELOPER",
"advancedTaskDefinitionArguments": [
{
"id": 31,
"name": "scan",
"type": "STRING"
}
],
"deleted": "0000-00-00 00:00:00",
"created": "2021-12-17 17:20:50"
}
}
}
14 changes: 14 additions & 0 deletions cmd/testdata/addWorkflowResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"data": {
"addWorkflow": {
"id": 1,
"name": "Teardown ephemeral environment after PR close",
"event": "GithubPRClosed",
"project": 18,
"advancedTaskDefinition": {
"id": 1,
"name": "Custom task"
}
}
}
}
21 changes: 21 additions & 0 deletions cmd/testdata/tasks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
tasks:
- name: "Custom Advanced Task"
description: "A custom advanced task defined inside a yml file"
group: "amazeeio"
project: "high-cotton"
environment: "Master"
type: "COMMAND"
command: "$BIN_PATH/lagoon-cli"
service: "cli"
permission: "DEVELOPER"
- name: "ClamAV scan"
description: "An anti-virus scan ran from an image"
project: "high-cotton"
environment: "Master"
type: "IMAGE"
image: "uselagoon/clamav:latest"
service: "cli"
permission: "MAINTAINER"
arguments:
- name: "scan"
type: "STRING"
10 changes: 10 additions & 0 deletions cmd/testdata/tasks.yml.invalid
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
tasks:
- name: "Custom Advanced Task"
description: "A custom advanced task defined inside a yml file"
group: "amazeeio"
project: "high-cotton"
environment: "Master"
type: "COMMAND"
command: "$BIN_PATH/lagoon-cli"
service: "cli"
permission: "DEVELOPER"
7 changes: 7 additions & 0 deletions cmd/testdata/tasks.yml.missing
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
tasks:
- name: "Custom Advanced Task"
description: "A custom advanced task defined inside a yml file"
type: "COMMAND"
command: "$BIN_PATH/lagoon-cli"
service: "cli"
permission: "DEVELOPER"
8 changes: 8 additions & 0 deletions cmd/testdata/tasks_response.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"data": {
"addUser": {
"id": "b6d33fb6-6b7c-4144-bf90-f7ac6ec47f2e",
"email": "[email protected]"
}
}
}
Loading