Skip to content

Commit

Permalink
Add Create/Update/Delete terraform handlers (#10)
Browse files Browse the repository at this point in the history
Signed-off-by: Viorel Dodin <[email protected]>
  • Loading branch information
DodinViorel committed Apr 19, 2024
1 parent f3086e0 commit ff7ac8c
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 78 deletions.
29 changes: 22 additions & 7 deletions examples/resources/cop_example/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,29 @@ terraform {
}

provider "observability" {
tenant = "47a01df9-54a0-472b-96b8-7c8f64eb7cbf"
auth_method = "oauth"
url = "https://alameda-c0-test-02.saas.appd-test.com"
tenant="0eb4e853-34fb-4f77-b3fc-b9cd3b462366"
auth_method="service-principal"
url="https://aiops-dev.saas.appd-test.com"
secrets_file="/home/vdodin/aiops_secret.json"
}

resource "observability_object" "ns" {
type_name = "fmm:namespace"
object_id = "aws"

resource "observability_object" "conn" {
type_name = "anzen:cloudConnection"
object_id = "just-terraform-testing"
layer_type = "TENANT"
layer_id = "47a01df9-54a0-472b-96b8-7c8f64eb7cbf"
layer_id = "0eb4e853-34fb-4f77-b3fc-b9cd3b462366"
data = jsonencode(
{
"cloudType": "AWS",
"connectionName": "just-terraform-testing",
"region": "us-east-2",
"accessKey": "**********",
"secretAccessKey": "**********",
"s3AccessLogBucket": "s3://s3-sanity-logging/",
"athenaOutputBucket": "s3://s3-sanity-athena-logs/",
"createTimestamp": "",
"accountId": "81892134343434"
}
)
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/apex/log v1.9.0
github.com/hashicorp/terraform-plugin-docs v0.18.0
github.com/hashicorp/terraform-plugin-framework v1.7.0
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
golang.org/x/oauth2 v0.19.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ github.com/hashicorp/terraform-plugin-docs v0.18.0 h1:2bINhzXc+yDeAcafurshCrIjtd
github.com/hashicorp/terraform-plugin-docs v0.18.0/go.mod h1:iIUfaJpdUmpi+rI42Kgq+63jAjI8aZVTyxp3Bvk9Hg8=
github.com/hashicorp/terraform-plugin-framework v1.7.0 h1:wOULbVmfONnJo9iq7/q+iBOBJul5vRovaYJIu2cY/Pw=
github.com/hashicorp/terraform-plugin-framework v1.7.0/go.mod h1:jY9Id+3KbZ17OMpulgnWLSfwxNVYSoYBQFTgsx044CI=
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc=
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg=
github.com/hashicorp/terraform-plugin-go v0.22.1 h1:iTS7WHNVrn7uhe3cojtvWWn83cm2Z6ryIUDTRO0EV7w=
github.com/hashicorp/terraform-plugin-go v0.22.1/go.mod h1:qrjnqRghvQ6KnDbB12XeZ4FluclYwptntoWCr9QaXTI=
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
Expand Down
4 changes: 4 additions & 0 deletions internal/api/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,7 @@ const (
typeAPIPath = "/knowledge-store/v1/types/"
objectAPIPath = "/knowledge-store/v1/objects/"
)

const (
jsonContentType = "application/json"
)
48 changes: 15 additions & 33 deletions internal/api/objectapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package api

import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
Expand All @@ -17,24 +16,18 @@ import (
// CreateObject is a method used to POST the knowledge store object
// based on the fullyQualifiedTypeName with the payload set in the body
// layerID which will be the tenant and layerType (TENANT/SOLUTION/...)
func (ac *AppdClient) CreateObject(fullyQualifiedTypeName, layerID, layerType string, body map[string]interface{}) error {
func (ac *AppdClient) CreateObject(fullyQualifiedTypeName, layerID, layerType string, body []byte) error {
url := ac.URL + objectAPIPath + fullyQualifiedTypeName

bodyPayload := make(map[string]interface{})
result, err := json.Marshal(bodyPayload)
if err != nil {
return err
}
bodyReader := bytes.NewReader(result)
bodyReader := bytes.NewReader(body)
req, err := http.NewRequest(http.MethodPost, url, bodyReader) //nolint:noctx // To be removed in the future
if err != nil {
return fmt.Errorf("failed to create a request for %q: %w", url, err)
}

// Add headers
contentType := "application/json"
req.Header.Add("Content-Type", contentType)
req.Header.Add("Accept", contentType)
req.Header.Add("Content-Type", jsonContentType)
req.Header.Add("Accept", jsonContentType)
req.Header.Add("Authorization", "Bearer "+ac.Token)

req.Header.Add("layer-id", layerID)
Expand All @@ -58,24 +51,17 @@ func (ac *AppdClient) CreateObject(fullyQualifiedTypeName, layerID, layerType st
// UpdateObject is a method used to PUT the knowledge store object
// based on the fullyQualifiedTypeName with the payload set in the body
// layerID which will be the tenant and layerType (TENANT/SOLUTION/...)
func (ac *AppdClient) UpdateObject(fullyQualifiedTypeName, layerID, layerType string, body map[string]interface{}) error {
url := ac.URL + objectAPIPath + fullyQualifiedTypeName

bodyPayload := make(map[string]interface{})
result, err := json.Marshal(bodyPayload)
if err != nil {
return err
}
bodyReader := bytes.NewReader(result)
req, err := http.NewRequest(http.MethodPut, url, bodyReader) //nolint:noctx // To be removed in the future
func (ac *AppdClient) UpdateObject(fullyQualifiedTypeName, objectID, layerID, layerType string, body []byte) error {
url := ac.URL + objectAPIPath + fullyQualifiedTypeName + "/" + objectID
bodyReader := bytes.NewReader(body)
req, err := http.NewRequest(http.MethodPut, url, bodyReader)
if err != nil {
return fmt.Errorf("failed to create a request for %q: %w", url, err)
}

// Add headers
contentType := "application/json"
req.Header.Add("Content-Type", contentType)
req.Header.Add("Accept", contentType)
req.Header.Add("Content-Type", jsonContentType)
req.Header.Add("Accept", jsonContentType)
req.Header.Add("Authorization", "Bearer "+ac.Token)

req.Header.Add("layer-id", layerID)
Expand All @@ -90,7 +76,7 @@ func (ac *AppdClient) UpdateObject(fullyQualifiedTypeName, layerID, layerType st
defer resp.Body.Close()

if resp.StatusCode/100 != 2 {
return fmt.Errorf("failed to POST request to %q (status %v): %s", req.URL.String(), resp.StatusCode, resp.Status)
return fmt.Errorf("failed to PUT request to %q (status %v): %s", req.URL.String(), resp.StatusCode, resp.Status)
}

return nil
Expand All @@ -114,10 +100,8 @@ func (ac *AppdClient) GetObject(fullyQualifiedTypeName, objectID, layerID, layer
}

// Add headers
contentType := "application/json"

req.Header.Add("Content-Type", contentType)
req.Header.Add("Accept", contentType)
req.Header.Add("Content-Type", jsonContentType)
req.Header.Add("Accept", jsonContentType)
req.Header.Add("Authorization", "Bearer "+ac.Token)

req.Header.Add("layer-id", layerID)
Expand Down Expand Up @@ -153,10 +137,8 @@ func (ac *AppdClient) DeleteObject(fullyQualifiedTypeName, objectID, layerID, la
}

// Add headers
contentType := "application/json"

req.Header.Add("Content-Type", contentType)
req.Header.Add("Accept", contentType)
req.Header.Add("Content-Type", jsonContentType)
req.Header.Add("Accept", jsonContentType)
req.Header.Add("Authorization", "Bearer "+ac.Token)

req.Header.Add("layer-id", layerID)
Expand Down
6 changes: 2 additions & 4 deletions internal/api/typeapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ func (ac *AppdClient) GetType(fullyQualifiedTypeName string) ([]byte, error) {
}

// Add headers
contentType := "application/json"

req.Header.Add("Content-Type", contentType)
req.Header.Add("Accept", contentType)
req.Header.Add("Content-Type", jsonContentType)
req.Header.Add("Accept", jsonContentType)
req.Header.Add("Authorization", "Bearer "+ac.Token)

// Do request
Expand Down
49 changes: 49 additions & 0 deletions internal/provider/jsonvalidator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//
// SPDX-License-Identifier: MPL-2.0

package provider

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

"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)

type IsValidJSONString struct {
JSONString string
}

func (v IsValidJSONString) Description(_ context.Context) string {
return fmt.Sprintf("value %s must be a valid json encoding string", v.JSONString)
}

func (v IsValidJSONString) MarkdownDescription(ctx context.Context) string {
return v.Description(ctx)
}

//nolint:gocritic // Terraform framework requires the method signature to be as is
func (v IsValidJSONString) ValidateString(ctx context.Context, request validator.StringRequest, response *validator.StringResponse) {
if request.ConfigValue.IsNull() || request.ConfigValue.IsUnknown() {
return
}

value := request.ConfigValue

if json.Valid([]byte(value.ValueString())) {
return
}

v.JSONString = value.ValueString()

response.Diagnostics.Append(validatordiag.InvalidAttributeValueMatchDiagnostic(
request.Path,
v.Description(ctx),
value.String(),
))
}
Loading

0 comments on commit ff7ac8c

Please sign in to comment.