Skip to content

Commit

Permalink
Merge pull request #83 from kaleido-io/stacks-updates
Browse files Browse the repository at this point in the history
Stacks updates
  • Loading branch information
chrisbygrave authored Nov 26, 2024
2 parents 33e4774 + 123e710 commit a11af38
Show file tree
Hide file tree
Showing 10 changed files with 1,038 additions and 647 deletions.
1,306 changes: 663 additions & 643 deletions examples/platform_stack/main.tf

Large diffs are not rendered by default.

4 changes: 0 additions & 4 deletions examples/platform_stack/terraform.tfvars.local_example

This file was deleted.

1 change: 1 addition & 0 deletions kaleido/platform/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ func Resources() []func() resource.Resource {
AMSVariableSetResourceFactory,
FireFlyRegistrationResourceFactory,
AuthenticatorResourceFactory,
StacksResourceFactory,
}
}

Expand Down
8 changes: 8 additions & 0 deletions kaleido/platform/mockserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type mockPlatform struct {
runtimes map[string]*RuntimeAPIModel
services map[string]*ServiceAPIModel
networks map[string]*NetworkAPIModel
stacks map[string]*StacksAPIModel
authenticators map[string]*AuthenticatorAPIModel
networkinitdatas map[string]*NetworkInitData
kmsWallets map[string]*KMSWalletAPIModel
Expand Down Expand Up @@ -67,6 +68,7 @@ func startMockPlatformServer(t *testing.T) *mockPlatform {
runtimes: make(map[string]*RuntimeAPIModel),
services: make(map[string]*ServiceAPIModel),
networks: make(map[string]*NetworkAPIModel),
stacks: make(map[string]*StacksAPIModel),
authenticators: make(map[string]*AuthenticatorAPIModel),
networkinitdatas: make(map[string]*NetworkInitData),
kmsWallets: make(map[string]*KMSWalletAPIModel),
Expand Down Expand Up @@ -185,6 +187,12 @@ func startMockPlatformServer(t *testing.T) *mockPlatform {
mp.register("/api/v1/groups/{group}", http.MethodPatch, mp.patchGroup)
mp.register("/api/v1/groups/{group}", http.MethodDelete, mp.deleteGroup)

// See stacks_test.go
mp.register("/api/v1/environments/{env}/stacks", http.MethodPost, mp.postStacks)
mp.register("/api/v1/environments/{env}/stacks/{stack}", http.MethodGet, mp.getStacks)
mp.register("/api/v1/environments/{env}/stacks/{stack}", http.MethodPut, mp.putStacks)
mp.register("/api/v1/environments/{env}/stacks/{stack}", http.MethodDelete, mp.deleteStacks)

mp.server = httptest.NewServer(mp.router)
return mp
}
Expand Down
6 changes: 6 additions & 0 deletions kaleido/platform/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type RuntimeResourceModel struct {
Environment types.String `tfsdk:"environment"`
Type types.String `tfsdk:"type"`
Name types.String `tfsdk:"name"`
StackID types.String `tfsdk:"stack_id"`
ConfigJSON types.String `tfsdk:"config_json"`
LogLevel types.String `tfsdk:"log_level"`
Size types.String `tfsdk:"size"`
Expand All @@ -50,6 +51,7 @@ type RuntimeAPIModel struct {
Updated *time.Time `json:"updated,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
StackID string `json:"stackId,omitempty"`
Config map[string]interface{} `json:"config"`
LogLevel string `json:"loglevel,omitempty"`
Size string `json:"size,omitempty"`
Expand Down Expand Up @@ -89,6 +91,9 @@ func (r *runtimeResource) Schema(_ context.Context, _ resource.SchemaRequest, re
"name": &schema.StringAttribute{
Required: true,
},
"stack_id": &schema.StringAttribute{
Optional: true,
},
"environment": &schema.StringAttribute{
Required: true,
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Expand Down Expand Up @@ -134,6 +139,7 @@ func (data *RuntimeResourceModel) toAPI(api *RuntimeAPIModel) {
// required fields
api.Type = data.Type.ValueString()
api.Name = data.Name.ValueString()
api.StackID = data.StackID.ValueString()
// optional fields
api.Config = map[string]interface{}{}
if !data.ConfigJSON.IsNull() {
Expand Down
8 changes: 8 additions & 0 deletions kaleido/platform/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ resource "kaleido_platform_runtime" "runtime1" {
environment = "env1"
type = "besu"
name = "runtime1"
stack_id = "stack1"
config_json = jsonencode({
"setting1": "value1"
})
Expand All @@ -47,6 +48,7 @@ resource "kaleido_platform_runtime" "runtime1" {
environment = "env1"
type = "besu"
name = "runtime1"
stack_id = "stack1"
config_json = jsonencode({
"setting1": "value1",
"setting2": "value2",
Expand All @@ -65,6 +67,7 @@ resource "kaleido_platform_runtime" "runtime1" {
environment = "env1"
type = "besu"
name = "runtime1"
stack_id = "stack1"
config_json = jsonencode({
"setting1": "value1",
"setting2": "value2",
Expand Down Expand Up @@ -109,6 +112,7 @@ func TestRuntime1(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(runtime1Resource, "id"),
resource.TestCheckResourceAttr(runtime1Resource, "name", `runtime1`),
resource.TestCheckResourceAttr(runtime1Resource, "stack_id", `stack1`),
resource.TestCheckResourceAttr(runtime1Resource, "type", `besu`),
resource.TestCheckResourceAttr(runtime1Resource, "config_json", `{"setting1":"value1"}`),
resource.TestCheckResourceAttr(runtime1Resource, "log_level", `info`),
Expand All @@ -124,6 +128,7 @@ func TestRuntime1(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(runtime1Resource, "id"),
resource.TestCheckResourceAttr(runtime1Resource, "name", `runtime1`),
resource.TestCheckResourceAttr(runtime1Resource, "stack_id", `stack1`),
resource.TestCheckResourceAttr(runtime1Resource, "type", `besu`),
resource.TestCheckResourceAttr(runtime1Resource, "config_json", `{"setting1":"value1","setting2":"value2"}`),
resource.TestCheckResourceAttr(runtime1Resource, "log_level", `trace`),
Expand All @@ -145,6 +150,7 @@ func TestRuntime1(t *testing.T) {
"updated": "%[3]s",
"type": "besu",
"name": "runtime1",
"stackId": "stack1",
"config": {
"setting1": "value1",
"setting2": "value2"
Expand Down Expand Up @@ -174,6 +180,7 @@ func TestRuntime1(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(runtime1Resource, "id"),
resource.TestCheckResourceAttr(runtime1Resource, "name", `runtime1`),
resource.TestCheckResourceAttr(runtime1Resource, "stack_id", `stack1`),
resource.TestCheckResourceAttr(runtime1Resource, "type", `besu`),
resource.TestCheckResourceAttr(runtime1Resource, "config_json", `{"setting1":"value1","setting2":"value2"}`),
resource.TestCheckResourceAttr(runtime1Resource, "log_level", `trace`),
Expand All @@ -195,6 +202,7 @@ func TestRuntime1(t *testing.T) {
"updated": "%[3]s",
"type": "besu",
"name": "runtime1",
"stackId": "stack1",
"config": {
"setting1": "value1",
"setting2": "value2"
Expand Down
6 changes: 6 additions & 0 deletions kaleido/platform/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type ServiceResourceModel struct {
Runtime types.String `tfsdk:"runtime"`
Type types.String `tfsdk:"type"`
Name types.String `tfsdk:"name"`
StackID types.String `tfsdk:"stack_id"`
EnvironmentMemberID types.String `tfsdk:"environment_member_id"`
ConfigJSON types.String `tfsdk:"config_json"`
Endpoints types.Map `tfsdk:"endpoints"`
Expand All @@ -51,6 +52,7 @@ type ServiceAPIModel struct {
Updated *time.Time `json:"updated,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
StackID string `json:"stackId,omitempty"`
Runtime ServiceAPIRuntimeRef `json:"runtime,omitempty"`
Account string `json:"account,omitempty"`
EnvironmentMemberID string `json:"environmentMemberId,omitempty"`
Expand Down Expand Up @@ -123,6 +125,9 @@ func (r *serviceResource) Schema(_ context.Context, _ resource.SchemaRequest, re
"name": &schema.StringAttribute{
Required: true,
},
"stack_id": &schema.StringAttribute{
Optional: true,
},
"environment_member_id": &schema.StringAttribute{
Computed: true,
},
Expand Down Expand Up @@ -223,6 +228,7 @@ func (data *ServiceResourceModel) toAPI(ctx context.Context, api *ServiceAPIMode
// required fields
api.Type = data.Type.ValueString()
api.Name = data.Name.ValueString()
api.StackID = data.StackID.ValueString()
api.Runtime.ID = data.Runtime.ValueString()
api.Config = map[string]interface{}{}
if !data.ConfigJSON.IsNull() {
Expand Down
5 changes: 5 additions & 0 deletions kaleido/platform/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ resource "kaleido_platform_service" "service1" {
runtime = "runtime1"
type = "besu"
name = "service1"
stack_id = "stack1"
config_json = jsonencode({
"setting1": "value1"
})
Expand All @@ -47,6 +48,7 @@ resource "kaleido_platform_service" "service1" {
runtime = "runtime1"
type = "besu"
name = "service1"
stack_id = "stack1"
config_json = jsonencode({
"setting1": "value1",
"setting2": "value2",
Expand Down Expand Up @@ -123,6 +125,7 @@ func TestService1(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(service1Resource, "id"),
resource.TestCheckResourceAttr(service1Resource, "name", `service1`),
resource.TestCheckResourceAttr(service1Resource, "stack_id", `stack1`),
resource.TestCheckResourceAttr(service1Resource, "type", `besu`),
resource.TestCheckResourceAttr(service1Resource, "config_json", `{"setting1":"value1"}`),
resource.TestCheckResourceAttr(service1Resource, "endpoints.%", `1`),
Expand All @@ -136,6 +139,7 @@ func TestService1(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(service1Resource, "id"),
resource.TestCheckResourceAttr(service1Resource, "name", `service1`),
resource.TestCheckResourceAttr(service1Resource, "stack_id", `stack1`),
resource.TestCheckResourceAttr(service1Resource, "type", `besu`),
resource.TestCheckResourceAttr(service1Resource, "config_json", `{"setting1":"value1","setting2":"value2"}`),
func(s *terraform.State) error {
Expand All @@ -149,6 +153,7 @@ func TestService1(t *testing.T) {
"updated": "%[3]s",
"type": "besu",
"name": "service1",
"stackId": "stack1",
"runtime": {
"id": "runtime1"
},
Expand Down
182 changes: 182 additions & 0 deletions kaleido/platform/stacks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// Copyright © Kaleido, Inc. 2024

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package platform

import (
"context"
"fmt"
"net/http"
"time"

"github.com/hashicorp/terraform-plugin-framework/path"
"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"
)

// stacks interface implementations for the resource and API
type StacksResourceModel struct {
ID types.String `tfsdk:"id"`
Environment types.String `tfsdk:"environment"`
EnvironmentMemberID types.String `tfsdk:"environment_member_id"`
Name types.String `tfsdk:"name"`
Type types.String `tfsdk:"type"`
NetworkType types.String `tfsdk:"network_type"`
}

type StacksAPIModel struct {
ID string `json:"id,omitempty"`
Created *time.Time `json:"created,omitempty"`
Updated *time.Time `json:"updated,omitempty"`
EnvironmentMemberID string `json:"environmentMemberId,omitempty"`
Name string `json:"name"`
Type string `json:"type"`
NetworkType string `json:"networkType,omitempty"`
}

func StacksResourceFactory() resource.Resource {
return &stacksResource{}
}

type stacksResource struct {
commonResource
}

func (r *stacksResource) Metadata(_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = "kaleido_platform_stack"
}

func (r *stacksResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"id": &schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()},
},
"name": &schema.StringAttribute{
Required: true,
},
"type": &schema.StringAttribute{
Required: true,
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
},
"environment": &schema.StringAttribute{
Required: true,
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
},
"environment_member_id": &schema.StringAttribute{
Computed: true,
},
"network_type": &schema.StringAttribute{
Optional: true,
Computed: true,
},
},
}
}

func (data *StacksResourceModel) toAPI(api *StacksAPIModel) {
api.Type = data.Type.ValueString()
api.Name = data.Name.ValueString()
if !data.NetworkType.IsNull() {
api.NetworkType = data.NetworkType.ValueString()
}
}

func (api *StacksAPIModel) toData(data *StacksResourceModel) {
data.ID = types.StringValue(api.ID)
data.EnvironmentMemberID = types.StringValue(api.EnvironmentMemberID)
data.NetworkType = types.StringValue(api.NetworkType)
data.Name = types.StringValue(api.Name)
data.Type = types.StringValue(api.Type)
if api.NetworkType != "" && !data.NetworkType.IsNull() {
data.NetworkType = types.StringValue(api.NetworkType)
}
}

func (r *stacksResource) apiPath(data *StacksResourceModel) string {
path := fmt.Sprintf("/api/v1/environments/%s/stacks", data.Environment.ValueString())
if data.ID.ValueString() != "" {
path = path + "/" + data.ID.ValueString()
}
return path
}

func (r *stacksResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {

var data StacksResourceModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

var api StacksAPIModel
data.toAPI(&api)
ok, _ := r.apiRequest(ctx, http.MethodPost, r.apiPath(&data), api, &api, &resp.Diagnostics)
if !ok {
return
}

api.toData(&data) // need the ID copied over
resp.Diagnostics.Append(resp.State.Set(ctx, data)...)
}

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

var data StacksResourceModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("id"), &data.ID)...)

// Read full current object
var api StacksAPIModel
if ok, _ := r.apiRequest(ctx, http.MethodGet, r.apiPath(&data), nil, &api, &resp.Diagnostics); !ok {
return
}

// Update from plan
data.toAPI(&api)
if ok, _ := r.apiRequest(ctx, http.MethodPut, r.apiPath(&data), api, &api, &resp.Diagnostics); !ok {
return
}

api.toData(&data)
resp.Diagnostics.Append(resp.State.Set(ctx, data)...)
}

func (r *stacksResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data StacksResourceModel
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

var api StacksAPIModel
api.ID = data.ID.ValueString()
ok, status := r.apiRequest(ctx, http.MethodGet, r.apiPath(&data), nil, &api, &resp.Diagnostics, Allow404())
if !ok {
return
}
if status == 404 {
resp.State.RemoveResource(ctx)
return
}

api.toData(&data)
resp.Diagnostics.Append(resp.State.Set(ctx, data)...)
}

func (r *stacksResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data StacksResourceModel
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

_, _ = r.apiRequest(ctx, http.MethodDelete, r.apiPath(&data), nil, nil, &resp.Diagnostics, Allow404())

r.waitForRemoval(ctx, r.apiPath(&data), &resp.Diagnostics)
}
Loading

0 comments on commit a11af38

Please sign in to comment.