Skip to content

Commit

Permalink
Merge pull request #78 from kaleido-io/runtime-storage
Browse files Browse the repository at this point in the history
[runtime] Support for storageSize, storageType, zone, and subZone
  • Loading branch information
peterbroadhurst authored Aug 29, 2024
2 parents aff6ff5 + 19db498 commit 216464d
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/go.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ jobs:
- uses: actions/checkout@v4
with:
path: 'terraform-provider-kaleido'

- uses: hashicorp/setup-terraform@v3
with:
terraform_version: "1.8.5"
terraform_wrapper: false

- name: Set up Go
uses: actions/setup-go@v5
Expand Down
50 changes: 49 additions & 1 deletion kaleido/platform/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ type RuntimeResourceModel struct {
Size types.String `tfsdk:"size"`
EnvironmentMemberID types.String `tfsdk:"environment_member_id"`
Stopped types.Bool `tfsdk:"stopped"`
Zone types.String `tfsdk:"zone"`
SubZone types.String `tfsdk:"sub_zone"`
StorageSize types.Int64 `tfsdk:"storage_size"`
StorageType types.String `tfsdk:"storage_type"`
}

type RuntimeAPIModel struct {
Expand All @@ -52,7 +56,11 @@ type RuntimeAPIModel struct {
EnvironmentMemberID string `json:"environmentMemberId,omitempty"`
Status string `json:"status,omitempty"`
Deleted bool `json:"deleted,omitempty"`
Stopped bool `json:"stopped,omitempty"`
Stopped bool `json:"stopped"`
Zone string `json:"zone,omitempty"`
SubZone string `json:"subZone,omitempty"`
StorageSize int64 `json:"storageSize,omitempty"`
StorageType string `json:"storageType,omitempty"`
}

func RuntimeResourceFactory() resource.Resource {
Expand Down Expand Up @@ -103,6 +111,21 @@ func (r *runtimeResource) Schema(_ context.Context, _ resource.SchemaRequest, re
Optional: true,
Computed: true,
},
"zone": &schema.StringAttribute{
Optional: true,
Computed: true,
},
"sub_zone": &schema.StringAttribute{
Optional: true,
},
"storage_size": &schema.Int64Attribute{
Optional: true,
// may be computed for certain storage required runtime types, but we will not track it if the user did not provide it
},
"storage_type": &schema.StringAttribute{
Optional: true,
// may be computed for certain runtime types, but we will not track it if the user did not provide it
},
},
}
}
Expand All @@ -125,6 +148,18 @@ func (data *RuntimeResourceModel) toAPI(api *RuntimeAPIModel) {
if !data.Stopped.IsNull() {
api.Stopped = data.Stopped.ValueBool()
}
if !data.Zone.IsNull() {
api.Zone = data.Zone.ValueString()
}
if !data.SubZone.IsNull() {
api.SubZone = data.SubZone.ValueString()
}
if !data.StorageSize.IsNull() {
api.StorageSize = data.StorageSize.ValueInt64()
}
if !data.StorageType.IsNull() {
api.StorageType = data.StorageType.ValueString()
}
}

func (api *RuntimeAPIModel) toData(data *RuntimeResourceModel) {
Expand All @@ -133,6 +168,19 @@ func (api *RuntimeAPIModel) toData(data *RuntimeResourceModel) {
data.LogLevel = types.StringValue(api.LogLevel)
data.Size = types.StringValue(api.Size)
data.Stopped = types.BoolValue(api.Stopped)
data.Zone = types.StringValue(api.Zone)
if api.SubZone != "" { // the API should only return a subzone if a subzone was specified
data.SubZone = types.StringValue(api.SubZone)
}
// For storage - it is optional for the user and conditional for the runtime based on its type.
// We can't mark it computed as a result, so we only track API storage state if the user provided desired
// storage state.
if api.StorageSize > 0 && !data.StorageSize.IsNull() {
data.StorageSize = types.Int64Value(api.StorageSize)
}
if api.StorageType != "" && !data.StorageType.IsNull() {
data.StorageType = types.StringValue(api.StorageType)
}
}

func (r *runtimeResource) apiPath(data *RuntimeResourceModel) string {
Expand Down
102 changes: 101 additions & 1 deletion kaleido/platform/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,31 @@ resource "kaleido_platform_runtime" "runtime1" {
config_json = jsonencode({
"setting1": "value1"
})
zone = "use2"
storage_size = 10
storage_type = "default"
}
`

var runtimeStep2 = `
resource "kaleido_platform_runtime" "runtime1" {
environment = "env1"
type = "besu"
name = "runtime1"
config_json = jsonencode({
"setting1": "value1",
"setting2": "value2",
})
log_level = "trace"
size = "large"
stopped = false
zone = "use2"
storage_size = 20
storage_type = "default"
}
`

var runtimeStep3 = `
resource "kaleido_platform_runtime" "runtime1" {
environment = "env1"
type = "besu"
Expand All @@ -51,6 +72,9 @@ resource "kaleido_platform_runtime" "runtime1" {
log_level = "trace"
size = "large"
stopped = true
zone = "use2"
storage_size = 20
storage_type = "default"
}
`

Expand All @@ -65,6 +89,10 @@ func TestRuntime1(t *testing.T) {
"GET /api/v1/environments/{env}/runtimes/{runtime}",
"PUT /api/v1/environments/{env}/runtimes/{runtime}",
"GET /api/v1/environments/{env}/runtimes/{runtime}",
"GET /api/v1/environments/{env}/runtimes/{runtime}",
"GET /api/v1/environments/{env}/runtimes/{runtime}",
"PUT /api/v1/environments/{env}/runtimes/{runtime}",
"GET /api/v1/environments/{env}/runtimes/{runtime}",
"DELETE /api/v1/environments/{env}/runtimes/{runtime}",
"GET /api/v1/environments/{env}/runtimes/{runtime}",
})
Expand All @@ -86,10 +114,63 @@ func TestRuntime1(t *testing.T) {
resource.TestCheckResourceAttr(runtime1Resource, "log_level", `info`),
resource.TestCheckResourceAttr(runtime1Resource, "size", `small`),
resource.TestCheckResourceAttr(runtime1Resource, "stopped", `false`),
resource.TestCheckResourceAttr(runtime1Resource, "zone", "use2"),
resource.TestCheckResourceAttr(runtime1Resource, "storage_size", "10"),
resource.TestCheckResourceAttr(runtime1Resource, "storage_type", "default"),
),
},
{
Config: providerConfig + runtimeStep2,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(runtime1Resource, "id"),
resource.TestCheckResourceAttr(runtime1Resource, "name", `runtime1`),
resource.TestCheckResourceAttr(runtime1Resource, "type", `besu`),
resource.TestCheckResourceAttr(runtime1Resource, "config_json", `{"setting1":"value1","setting2":"value2"}`),
resource.TestCheckResourceAttr(runtime1Resource, "log_level", `trace`),
resource.TestCheckResourceAttr(runtime1Resource, "size", `large`),
resource.TestCheckResourceAttr(runtime1Resource, "stopped", `false`),
resource.TestCheckResourceAttr(runtime1Resource, "zone", "use2"),
resource.TestCheckResourceAttr(runtime1Resource, "storage_size", "20"),
resource.TestCheckResourceAttr(runtime1Resource, "storage_type", "default"),
func(s *terraform.State) error {
// Compare the final result on the mock-server side
id := s.RootModule().Resources[runtime1Resource].Primary.Attributes["id"]
rt := mp.runtimes[fmt.Sprintf("env1/%s", id)]
// Note the pending status is allowed to remain in runtimes, as they require at least one
// service to be created to get out of pending.
testJSONEqual(t, rt, fmt.Sprintf(`
{
"id": "%[1]s",
"created": "%[2]s",
"updated": "%[3]s",
"type": "besu",
"name": "runtime1",
"config": {
"setting1": "value1",
"setting2": "value2"
},
"loglevel": "trace",
"size": "large",
"environmentMemberId": "%[4]s",
"status": "pending",
"stopped": false,
"zone": "use2",
"storageSize": 20,
"storageType": "default"
}
`,
// generated fields that vary per test run
id,
rt.Created.UTC().Format(time.RFC3339Nano),
rt.Updated.UTC().Format(time.RFC3339Nano),
rt.EnvironmentMemberID,
))
return nil
},
),
},
{
Config: providerConfig + runtimeStep3,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(runtime1Resource, "id"),
resource.TestCheckResourceAttr(runtime1Resource, "name", `runtime1`),
Expand All @@ -98,6 +179,9 @@ func TestRuntime1(t *testing.T) {
resource.TestCheckResourceAttr(runtime1Resource, "log_level", `trace`),
resource.TestCheckResourceAttr(runtime1Resource, "size", `large`),
resource.TestCheckResourceAttr(runtime1Resource, "stopped", `true`),
resource.TestCheckResourceAttr(runtime1Resource, "zone", "use2"),
resource.TestCheckResourceAttr(runtime1Resource, "storage_size", "20"),
resource.TestCheckResourceAttr(runtime1Resource, "storage_type", "default"),
func(s *terraform.State) error {
// Compare the final result on the mock-server side
id := s.RootModule().Resources[runtime1Resource].Primary.Attributes["id"]
Expand All @@ -119,7 +203,10 @@ func TestRuntime1(t *testing.T) {
"size": "large",
"environmentMemberId": "%[4]s",
"status": "pending",
"stopped": true
"stopped": true,
"zone": "use2",
"storageSize": 20,
"storageType": "default"
}
`,
// generated fields that vary per test run
Expand Down Expand Up @@ -161,6 +248,16 @@ func (mp *mockPlatform) postRuntime(res http.ResponseWriter, req *http.Request)
if rt.Size == "" {
rt.Size = "small"
}
if rt.Zone == "" {
rt.Zone = "default"
}
// if they provide a SubZone its just returned back
if rt.StorageType == "" {
rt.StorageType = "default"
}
if rt.StorageSize <= 0 {
rt.StorageSize = 50
}
rt.Status = "pending"
mp.runtimes[mux.Vars(req)["env"]+"/"+rt.ID] = &rt
mp.respond(res, &rt, 201)
Expand All @@ -176,6 +273,9 @@ func (mp *mockPlatform) putRuntime(res http.ResponseWriter, req *http.Request) {
now := time.Now().UTC()
newRT.Created = rt.Created
newRT.Updated = &now
if rt.StorageSize > 0 && newRT.StorageSize < rt.StorageSize {
mp.respond(res, nil, 400)
}
newRT.Status = "pending"
mp.runtimes[mux.Vars(req)["env"]+"/"+mux.Vars(req)["runtime"]] = &newRT
mp.respond(res, &newRT, 200)
Expand Down

0 comments on commit 216464d

Please sign in to comment.