Skip to content

Commit

Permalink
Spinnaker Application Enhancements (#7) (#8)
Browse files Browse the repository at this point in the history
Enhancements to Spinnaker application resource:
- Add support for cloud providers
- Add support for permissions
- Implemented Update method
- Improved error messages for Spinnaker application

Co-authored-by: James Guido <[email protected]>
  • Loading branch information
guido9j and James Guido authored Jun 14, 2023
1 parent fed04ca commit c8b83ec
Show file tree
Hide file tree
Showing 14 changed files with 149 additions and 53 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ https://spinnaker.io/concepts/
$ git clone [email protected]:homedepot/terraform-provider-spinnaker.git
$ cd terraform-provider-spinnaker/
$ go build
$ go test./...
$ go test ./...
```

## Using the provider
Expand Down
18 changes: 18 additions & 0 deletions docs/resources/spinnaker_application.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,30 @@ resource "spinnaker_application" "terraformtest" {
}
```

```hcl
resource "spinnaker_application" "terraformtest" {
application = "terraformtest"
email = "[email protected]"
cloud_providers = [
"kubernetes",
"appengine"
]
permissions {
read = [ "group1", "group2", "group3" ]
write = [ "group1" ]
execute = [ "group1", "group2" ]
}
}
```

## Argument Reference

- `application` - (Required) Spinnaker application name.
- `email` - (Required) Application owner email.
- `description` - (Optional) Description. (Default: `""`)
- `platform_health_only` - (Optional) Consider only cloud provider health when executing tasks. (Default: `false`)
- `platform_health_only_show_override` - (Optional) Show health override option for each operation. (Default: `false`)
- `cloud_providers` - (Optional) Array list of cloud providers.
- `permissions` - (Optional) Array of permissions in key/value pairs. Valid permission keys are `read`, `write` and `execute`. Permission value is array list of groups.

## Attribute Reference
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module github.com/guido9j/terraform-provider-spinnaker
module terraform-provider-spinnaker

go 1.18

Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/plugin"

"github.com/guido9j/terraform-provider-spinnaker/spinnaker"
"terraform-provider-spinnaker/spinnaker"
)

func main() {
Expand Down
60 changes: 49 additions & 11 deletions spinnaker/api/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import (
"strings"
"time"

"github.com/antihax/optional"
"github.com/antihax/optional"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/mitchellh/mapstructure"

gate "github.com/spinnaker/spin/cmd/gateclient"
gateapi "github.com/spinnaker/spin/gateapi"
gateapi "github.com/spinnaker/spin/gateapi"
)

func GetApplication(client *gate.GatewayClient, applicationName string, dest interface{}) error {
Expand All @@ -23,7 +25,7 @@ func GetApplication(client *gate.GatewayClient, applicationName string, dest int
}

if err != nil {
return err
return FormatAPIErrorMessage ("ApplicationControllerApi.GetApplicationUsingGET", err)
}

if err := mapstructure.Decode(app, dest); err != nil {
Expand All @@ -33,10 +35,19 @@ func GetApplication(client *gate.GatewayClient, applicationName string, dest int
return nil
}

func CreateApplication(client *gate.GatewayClient, applicationName, email,
applicationDescription string, platformHealthOnly, platformHealthOnlyShowOverride bool) error {
func CreateOrUpdateApplication(client *gate.GatewayClient, applicationName, email,
applicationDescription string, platformHealthOnly, platformHealthOnlyShowOverride bool,
cloud_providers []interface{}, permissions *schema.Set) error {

app := map[string]interface{}{
jobType := "createApplication"
jobDescription := fmt.Sprintf("Create Application: %s", applicationName)
app, resp, err := client.ApplicationControllerApi.GetApplicationUsingGET(client.Context, applicationName, &gateapi.ApplicationControllerApiGetApplicationUsingGETOpts{Expand: optional.NewBool(false)})
if resp != nil && resp.StatusCode == http.StatusOK && err == nil {
jobType = "updateApplication"
jobDescription = fmt.Sprintf("Update Application: %s", applicationName)
}

app = map[string]interface{}{
"instancePort": 80,
"name": applicationName,
"email": email,
Expand All @@ -45,15 +56,42 @@ func CreateApplication(client *gate.GatewayClient, applicationName, email,
"description": applicationDescription,
}

if len(cloud_providers) > 0 {
providers_csv := ""
for i := range cloud_providers {
if (i > 0) { providers_csv += "," }
providers_csv += cloud_providers[i].(string)
}
app["cloudProviders"] = providers_csv
}

if permissions.Len() == 1 {
permissions_object := make(map[string]interface{})
list := permissions.List()
for k, value := range list[0].(map[string]interface{}) {
switch key := k; key {
case "read":
permissions_object["READ"] = value
case "execute":
permissions_object["EXECUTE"] = value
case "write":
permissions_object["WRITE"] = value
default:
return fmt.Errorf("invalid permissions type of %s", key)
}
}
app["permissions"] = permissions_object
}

createAppTask := map[string]interface{}{
"job": []interface{}{map[string]interface{}{"type": "createApplication", "application": app}},
"job": []interface{}{map[string]interface{}{"type": jobType, "application": app}},
"application": applicationName,
"description": fmt.Sprintf("Create Application: %s", applicationName),
"description": jobDescription,
}

ref, _, err := client.TaskControllerApi.TaskUsingPOST1(client.Context, createAppTask)
if err != nil {
return err
return FormatAPIErrorMessage ("TaskControllerApi.TaskUsingPOST1", err)
}

toks := strings.Split(ref["ref"].(string), "/")
Expand All @@ -71,7 +109,7 @@ func CreateApplication(client *gate.GatewayClient, applicationName, email,
}

if err != nil {
return err
return FormatAPIErrorMessage ("TaskControllerApi.GetTaskUsingGET1", err)
}
if resp.StatusCode < 200 || resp.StatusCode > 299 {
return fmt.Errorf("Encountered an error saving application, status code: %d\n", resp.StatusCode)
Expand Down Expand Up @@ -100,7 +138,7 @@ func DeleteAppliation(client *gate.GatewayClient, applicationName string) error
_, resp, err := client.TaskControllerApi.TaskUsingPOST1(client.Context, deleteAppTask)

if err != nil {
return err
return FormatAPIErrorMessage ("TaskControllerApi.TaskUsingPOST1", err)
}

if resp.StatusCode != http.StatusOK {
Expand Down
17 changes: 4 additions & 13 deletions spinnaker/api/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,13 @@ import (

"github.com/mitchellh/mapstructure"
gate "github.com/spinnaker/spin/cmd/gateclient"
gate_swagger "github.com/spinnaker/spin/gateapi"
)

func FormatAPIErrorMessage(function_name string, err error) error {
switch err_sw := err.(type) {
case gate_swagger.GenericSwaggerError:
return fmt.Errorf("%s: %s() response payload: %s", err_sw.Error(), function_name, err_sw.Body())
}
return fmt.Errorf("%s: From %s()", err, function_name)
}

func CreatePipeline(client *gate.GatewayClient, pipeline interface{}) error {
resp, err := client.PipelineControllerApi.SavePipelineUsingPOST(client.Context, pipeline, nil)

if err != nil {
return FormatAPIErrorMessage ("PipelineControllerApi.SavePipelineUsingPOST", err)
return FormatAPIErrorMessage ("PipelineControllerApi.SavePipelineUsingPOST", err)
}

if resp.StatusCode != http.StatusOK {
Expand All @@ -42,7 +33,7 @@ func GetPipeline(client *gate.GatewayClient, applicationName, pipelineName strin
}
return jsonMap, fmt.Errorf("Encountered an error getting pipeline %s, %s\n",
pipelineName,
FormatAPIErrorMessage ("PipelineControllerApi.GetPipelineConfigUsingGET", err))
FormatAPIErrorMessage ("PipelineControllerApi.GetPipelineConfigUsingGET", err))
}

if resp.StatusCode != http.StatusOK {
Expand All @@ -67,7 +58,7 @@ func UpdatePipeline(client *gate.GatewayClient, pipelineID string, pipeline inte
_, resp, err := client.PipelineControllerApi.UpdatePipelineUsingPUT(client.Context, pipelineID, pipeline)

if err != nil {
return FormatAPIErrorMessage ("PipelineControllerApi.UpdatePipelineUsingPUT", err)
return FormatAPIErrorMessage ("PipelineControllerApi.UpdatePipelineUsingPUT", err)
}

if resp.StatusCode != http.StatusOK {
Expand All @@ -81,7 +72,7 @@ func DeletePipeline(client *gate.GatewayClient, applicationName, pipelineName st
resp, err := client.PipelineControllerApi.DeletePipelineUsingDELETE(client.Context, applicationName, pipelineName)

if err != nil {
return FormatAPIErrorMessage ("PipelineControllerApi.DeletePipelineUsingDELETE", err)
return FormatAPIErrorMessage ("PipelineControllerApi.DeletePipelineUsingDELETE", err)
}

if resp.StatusCode != http.StatusOK {
Expand Down
15 changes: 15 additions & 0 deletions spinnaker/api/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package api

import (
"fmt"
gate_swagger "github.com/spinnaker/spin/gateapi"
)

func FormatAPIErrorMessage(function_name string, err error) error {
switch err_sw := err.(type) {
case gate_swagger.GenericSwaggerError:
return fmt.Errorf("%s: %s() response payload: %s", err_sw.Error(), function_name, err_sw.Body())
}
return fmt.Errorf("%s: From %s()", err, function_name)
}

10 changes: 5 additions & 5 deletions spinnaker/provider.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package spinnaker

import (
"os"
"io/ioutil"
"os"
"io"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/spinnaker/spin/cmd/output"
"github.com/spinnaker/spin/cmd/output"
gate "github.com/spinnaker/spin/cmd/gateclient"
)

Expand Down Expand Up @@ -88,7 +88,7 @@ func providerConfigureFunc(data *schema.ResourceData) (interface{}, error) {
if err != nil {
return nil, err
}
ui := output.NewUI(quiet, noColor, outputFormater, ioutil.Discard, ioutil.Discard)
ui := output.NewUI(quiet, noColor, outputFormater, io.Discard, io.Discard)

client, err := gate.NewGateClient(ui, server, defaultHeaders, config, ignoreCertErrors)
if err != nil {
Expand Down
8 changes: 4 additions & 4 deletions spinnaker/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package spinnaker

import (
"os"
"fmt"
"fmt"
"testing"
"context"
"context"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

var testAccProviders map[string]*schema.Provider
Expand Down
54 changes: 44 additions & 10 deletions spinnaker/resource_application.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package spinnaker
import (
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/guido9j/terraform-provider-spinnaker/spinnaker/api"
"terraform-provider-spinnaker/spinnaker/api"
)

func resourceApplication() *schema.Resource {
Expand Down Expand Up @@ -35,10 +35,46 @@ func resourceApplication() *schema.Resource {
Optional: true,
Default: "",
},
"cloud_providers": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"permissions": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"read": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"execute": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"write": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
},
Create: resourceApplicationCreate,
Create: resourceApplicationCreateOrUpdate,
Read: resourceApplicationRead,
Update: resourceApplicationUpdate,
Update: resourceApplicationCreateOrUpdate,
Delete: resourceApplicationDelete,
Exists: resourceApplicationExists,
}
Expand All @@ -51,16 +87,18 @@ type applicationRead struct {
} `json:"attributes"`
}

func resourceApplicationCreate(data *schema.ResourceData, meta interface{}) error {
func resourceApplicationCreateOrUpdate(data *schema.ResourceData, meta interface{}) error {
clientConfig := meta.(gateConfig)
client := clientConfig.client
application := data.Get("application").(string)
email := data.Get("email").(string)
description := data.Get("description").(string)
platform_health_only := data.Get("platform_health_only").(bool)
platform_health_only_show_override := data.Get("platform_health_only_show_override").(bool)
cloud_providers := data.Get("cloud_providers").([]interface{})
permissions := data.Get("permissions").(*schema.Set)

if err := api.CreateApplication(client, application, email, description, platform_health_only, platform_health_only_show_override); err != nil {
if err := api.CreateOrUpdateApplication(client, application, email, description, platform_health_only, platform_health_only_show_override, cloud_providers, permissions); err != nil {
return err
}

Expand All @@ -79,10 +117,6 @@ func resourceApplicationRead(data *schema.ResourceData, meta interface{}) error
return readApplication(data, app)
}

func resourceApplicationUpdate(data *schema.ResourceData, meta interface{}) error {
return nil
}

func resourceApplicationDelete(data *schema.ResourceData, meta interface{}) error {
clientConfig := meta.(gateConfig)
client := clientConfig.client
Expand Down
2 changes: 1 addition & 1 deletion spinnaker/resource_application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccSpinnakerApplication_basic(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions spinnaker/resource_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/guido9j/terraform-provider-spinnaker/spinnaker/api"
"terraform-provider-spinnaker/spinnaker/api"
)

func resourcePipeline() *schema.Resource {
Expand Down
Loading

0 comments on commit c8b83ec

Please sign in to comment.