Skip to content
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 1.13.0 (Unreleased)

FEATURES:

* **New Resource:** `turbot_rollout` ([#195](https://github.com/turbot/terraform-provider-turbot/issues/195))

## 1.12.3 (TBD)

BUG FIXES:
Expand Down
98 changes: 98 additions & 0 deletions apiClient/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -746,3 +746,101 @@ func (client *Client) GetTurbotWorkspaceVersion() (*semver.Version, error) {
}
return version, nil
}

// rollout
// filter and description are removed for a workaround, will be removed after a Core change.
func createRolloutMutation() string {
return `mutation CreateRollout($input: CreateRolloutInput!) {
rollout: createRollout(input: $input) {
title
status
description
recipients
phases
turbot {
id
parentId
akas
title
}
accounts {
items {
turbot {
id
}
}
}
guardrails {
items {
turbot {
id
}
}
}
}
}`
}

func readRolloutQuery(id string) string {
return fmt.Sprintf(`{
rollout(id: "%s") {
description
status
title
recipients
phases
accounts {
items {
turbot {
id
}
}
}
guardrails {
items {
turbot {
id
}
}
}
turbot {
id
akas
title
parentId
}
}
}`, id)
}

func updateRolloutMutation() string {
return `mutation UpdateRollout($input: UpdateRolloutInput!) {
rollout: updateRollout(input: $input) {
title
status
description
recipients
phases
turbot {
id
parentId
akas
title
}
accounts {
items {
turbot {
id
}
}
}
guardrails {
items {
turbot {
id
}
}
}
}
}`
}
39 changes: 39 additions & 0 deletions apiClient/rollout.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package apiClient

func (client *Client) CreateRollout(input map[string]interface{}) (*Rollout, error) {
query := createRolloutMutation()
responseData := &RolloutResponse{}
variables := map[string]interface{}{
"input": input,
}

// execute api call
if err := client.doRequest(query, variables, responseData); err != nil {
return nil, client.handleCreateError(err, input, "rollout")
}
return &responseData.Rollout, nil
}

func (client *Client) ReadRollout(id string) (*Rollout, error) {
query := readRolloutQuery(id)
responseData := &RolloutResponse{}

// execute api call
if err := client.doRequest(query, nil, responseData); err != nil {
return nil, client.handleReadError(err, id, "rollout")
}
return &responseData.Rollout, nil
}

func (client *Client) UpdateRollout(input map[string]interface{}) (*Rollout, error) {
query := updateRolloutMutation()
responseData := &RolloutResponse{}
variables := map[string]interface{}{
"input": input,
}
// execute api call
if err := client.doRequest(query, variables, responseData); err != nil {
return nil, client.handleUpdateError(err, input, "rollout")
}
return &responseData.Rollout, nil
}
51 changes: 51 additions & 0 deletions apiClient/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,3 +535,54 @@ type TurbotWatchMetadata struct {
ResourceId string
FavoriteId string
}

// Rollout
type RolloutResponse struct {
Rollout Rollout
}

type Rollout struct {
Turbot TurbotResourceMetadata
Description string
Status string
Title string
Recipients []string
Accounts struct {
Items []struct {
Turbot TurbotResourceMetadata
}
}
Guardrails struct {
Items []struct {
Turbot TurbotResourceMetadata
}
}
Phases RolloutPhases `json:"phases"`
}

type RolloutPhases struct {
Draft *TurbotRolloutDraftPhaseMetadata `json:"draft,omitempty"`
Preview *TurbotRolloutPreviewPhaseMetadata `json:"preview,omitempty"`
Check *TurbotRolloutPhaseMetadata `json:"check,omitempty"`
Enforce *TurbotRolloutPhaseMetadata `json:"enforce,omitempty"`
Detach *TurbotRolloutPhaseMetadata `json:"detach,omitempty"`
}

type TurbotRolloutPhaseMetadata struct {
StartAt string `json:"startAt,omitempty"`
StartNotice string `json:"startNotice,omitempty"`
StartEarlyIf string `json:"startEarlyIf,omitempty"`
WarnAt []string `json:"warnAt,omitempty"`
Recipients []string `json:"recipients,omitempty"`
}

type TurbotRolloutDraftPhaseMetadata struct {
StartAt string `json:"startAt,omitempty"`
}

type TurbotRolloutPreviewPhaseMetadata struct {
StartAt string `json:"startAt,omitempty"`
StartNotice string `json:"startNotice,omitempty"`
StartEarlyIf string `json:"startEarlyIf,omitempty"`
Recipients []string `json:"recipients,omitempty"`
}
9 changes: 8 additions & 1 deletion errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package errors

import (
"fmt"
"github.com/pkg/errors"
"net/http"
"regexp"
"strconv"
"strings"

"github.com/pkg/errors"
)

func NotFoundError(err error) bool {
Expand All @@ -21,6 +22,12 @@ func FailedValidationError(err error) bool {
return expectedErr.Match([]byte(err.Error()))
}

func ForbiddenError(err error) bool {
forbiddenErr := "graphql: Forbidden: Insufficient permissions for resource(?i)"
expectedErr := regexp.MustCompile(forbiddenErr)
return expectedErr.Match([]byte(err.Error()))
}

func ExtractErrorCode(err error) (int, error) {
// error returned from machinebox/graphql is of graphql type
// errorNon200Template = "graphql: server returned a non-200 status code: 503"
Expand Down
1 change: 1 addition & 0 deletions turbot/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func Provider() terraform.ResourceProvider {
},

ResourcesMap: map[string]*schema.Resource{
"turbot_rollout": resourceTurbotRollout(),
"turbot_control_mute": resourceTurbotControlMute(),
"turbot_file": resourceTurbotFile(),
"turbot_folder": resourceTurbotFolder(),
Expand Down
14 changes: 14 additions & 0 deletions turbot/resource_data_helpers.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package turbot

import (
"reflect"

"github.com/hashicorp/terraform/helper/schema"
"github.com/iancoleman/strcase"
"github.com/turbot/terraform-provider-turbot/apiClient"
Expand Down Expand Up @@ -58,3 +60,15 @@ func storeAkas(aka, propertyName string, d *schema.ResourceData, meta interface{
d.Set(propertyName, akas)
return nil
}

// given an attribute, check for if the attribute contains a nil value
func isNil(i interface{}) bool {
if i == nil {
return true
}
switch reflect.TypeOf(i).Kind() {
case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Slice:
return reflect.ValueOf(i).IsNil()
}
return false
}
Loading