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

feat(resource): standalone monitor definition via yaml file #69

Closed
wants to merge 1 commit into from
Closed
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
20 changes: 20 additions & 0 deletions client/monte_carlo_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,23 @@ type UpdateUserAuthorizationGroupMembership struct {
}
} `graphql:"updateUserAuthorizationGroupMembership(memberUserId: $memberUserId, groupNames: $groupNames)"`
}

type CreateOrUpdateMonteCarloConfigTemplate struct {
CreateOrUpdateMonteCarloConfigTemplate struct {
Response struct {
ChangesApplied bool
ErrorsAsJson string
InfoAsJson string
ResourceModifications []struct {
Type string
Description string
ResourceAsJson string
IsSignificantChange bool
DiffString string
ResourceType string
ResourceIndex int
}
WarningsAsJson string
}
} `graphql:"createOrUpdateMonteCarloConfigTemplate(configTemplateJson: $configTemplateJson, dryRun: $dryRun, namespace: $namespace, resource: $resource)"`
}
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ module github.com/kiwicom/terraform-provider-montecarlo
go 1.21.1

require (
github.com/google/uuid v1.3.1
github.com/hashicorp/terraform-plugin-framework v1.4.2
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0
github.com/hashicorp/terraform-plugin-go v0.19.1
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-testing v1.5.1
github.com/hasura/go-graphql-client v0.10.0
gopkg.in/yaml.v3 v3.0.1
)

require (
Expand All @@ -19,7 +21,6 @@ require (
github.com/fatih/color v1.15.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
Expand Down
132 changes: 132 additions & 0 deletions internal/monitor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package internal

import (
"context"
"encoding/json"
"fmt"

"github.com/kiwicom/terraform-provider-montecarlo/client"
"github.com/kiwicom/terraform-provider-montecarlo/internal/common"

"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"

"github.com/google/uuid"
"gopkg.in/yaml.v3"
)

// Ensure provider defined types fully satisfy framework interfaces.
var _ resource.Resource = &MonitorResource{}
var _ resource.ResourceWithImportState = &MonitorResource{}

// To simplify provider implementations, a named function can be created with the resource implementation.
func NewMonitorResource() resource.Resource {
return &MonitorResource{}
}

// MonitorResource defines the resource implementation.
type MonitorResource struct {
client client.MonteCarloClient
}

// MonitorResourceModel describes the resource data model according to its Schema.
type MonitorResourceModel struct {
Uuid types.String `tfsdk:"uuid"`
Resource types.String `tfsdk:"resource"`
Monitor types.String `tfsdk:"monitor"`
}

func (r *MonitorResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_monitor"
}

func (r *MonitorResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"uuid": schema.StringAttribute{
Computed: true,
Optional: false,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"resource": schema.StringAttribute{
Computed: true,
Optional: true,
},
"monitor": schema.StringAttribute{
Required: true,
},
},
}
}

func (r *MonitorResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
client, diags := common.Configure(req)
resp.Diagnostics.Append(diags...)
r.client = client
}

func (r *MonitorResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data MonitorResourceModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

jsonMonitor, err := yamlToJson(data.Monitor.ValueString())
if err != nil {
summary := "Failed to convert Monitor YAML definition to JSON: " + err.Error()
detail := "Conversion must be done before sending the request to the API"
resp.Diagnostics.AddError(summary, detail)
return
}

namespace := uuid.New().String()
createResult := client.CreateOrUpdateMonteCarloConfigTemplate{}
variables := map[string]interface{}{
"namespace": namespace,
"resource": data.Resource.ValueStringPointer(),
"dryRun": true,
"configTemplateJson": jsonMonitor,
}

response := &createResult.CreateOrUpdateMonteCarloConfigTemplate.Response
if err := r.client.Mutate(ctx, &createResult, variables); err != nil {
summary := fmt.Sprintf("MC client 'CreateOrUpdateMonteCarloConfigTemplate' mutation result - %s", err.Error())
resp.Diagnostics.AddError(summary, "")
return
} else if !response.ChangesApplied || response.ErrorsAsJson == "" {
summary := fmt.Sprintf("MC client 'CreateOrUpdateMonteCarloConfigTemplate' mutation result - %s", response.ErrorsAsJson)
resp.Diagnostics.AddError(summary, "")
return
}

data.Uuid = types.StringValue(namespace)
data.Resource = types.StringValue("")
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *MonitorResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
}

func (r *MonitorResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
}

func (r *MonitorResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
}

func (r *MonitorResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
}

func yamlToJson(yamlData string) (string, error) {
var data map[string]interface{}
if err := yaml.Unmarshal([]byte(yamlData), &data); err != nil {
return "", err
}
jsonData, err := json.Marshal(data)
return string(jsonData), err
}
1 change: 1 addition & 0 deletions internal/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ func (p *Provider) Resources(ctx context.Context) []func() resource.Resource {
NewDomainResource,
authorization.NewIamGroupResource,
authorization.NewIamMemberResource,
NewMonitorResource,
}
}

Expand Down
Loading