Skip to content

Commit

Permalink
fix: for function update
Browse files Browse the repository at this point in the history
  • Loading branch information
andrew-s committed Aug 7, 2024
1 parent 83cd774 commit 3b82604
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 16 deletions.
29 changes: 26 additions & 3 deletions internal/resources/resource_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ func (r *FunctionResource) Schema(_ context.Context, _ resource.SchemaRequest, r
Required: false,
Computed: true,
Description: "Unique identifier for the function, assigned automatically upon creation.",
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"revision": schema.StringAttribute{
Required: false,
Computed: true,
Description: "Function revision",
},
"project_id": schema.StringAttribute{
Required: true,
Expand Down Expand Up @@ -287,6 +295,7 @@ func (r *FunctionResource) Create(ctx context.Context, req resource.CreateReques

// Set resource fields
plan.ID = types.StringValue(function.Id)
plan.Revision = types.StringValue(function.Revision)
plan.ProjectID = types.StringValue(function.ProjectId)
plan.Version = types.StringValue(function.Version)
plan.Name = types.StringValue(function.Name)
Expand Down Expand Up @@ -342,6 +351,7 @@ func (r *FunctionResource) Read(ctx context.Context, req resource.ReadRequest, r

// Overwrite state with refreshed state
state.ID = types.StringValue(function.Id)
state.Revision = types.StringValue(function.Revision)
state.ProjectID = types.StringValue(function.ProjectId)
state.Version = types.StringValue(function.Version)
state.Name = types.StringValue(function.Name)
Expand Down Expand Up @@ -379,9 +389,17 @@ func (r *FunctionResource) Read(ctx context.Context, req resource.ReadRequest, r
// Update updates the resource and sets the updated Terraform state on success.
func (r *FunctionResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {

// retrieve state, used for revision information
var state FunctionResourceModel
diags := req.State.Get(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

// Retrieve values from plan
var plan FunctionResourceModel
diags := req.Plan.Get(ctx, &plan)
diags = req.Plan.Get(ctx, &plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
Expand Down Expand Up @@ -422,17 +440,18 @@ func (r *FunctionResource) Update(ctx context.Context, req resource.UpdateReques

_, httpRes, err := r.client.FunctionsAPI.FunctionsUpdate(ctx, plan.ID.ValueString()).Function(openapiclient.Function{
Id: plan.ID.ValueString(),
Revision: state.Revision.ValueString(),
ProjectId: plan.ProjectID.ValueString(),
Version: plan.Version.ValueString(),
Name: plan.Name.ValueString(),
Description: plan.Name.ValueString(),
Description: plan.Description.ValueString(),
Image: plan.Image.ValueString(),
Type: openapiclient.FunctionType(plan.FunctionType.ValueString()),
Size: *functionSize,
Port: int32(plan.Port.ValueInt64()),
Routes: functionRoutes,
Scaling: openapiclient.FunctionScaling{
Type: plan.Scaling.Type.String(),
Type: plan.Scaling.Type.ValueString(),
Low: int32(plan.Scaling.Low.ValueInt64()),
High: int32(plan.Scaling.High.ValueInt64()),
},
Expand Down Expand Up @@ -461,6 +480,7 @@ func (r *FunctionResource) Update(ctx context.Context, req resource.UpdateReques
// Update resource state with updated items

plan.ID = types.StringValue(function.Id)
plan.Revision = types.StringValue(function.Revision)
plan.ProjectID = types.StringValue(function.ProjectId)
plan.Version = types.StringValue(function.Version)
plan.Name = types.StringValue(function.Name)
Expand All @@ -477,6 +497,8 @@ func (r *FunctionResource) Update(ctx context.Context, req resource.UpdateReques
//plan.Route = OpenAPIToRoutes(ctx, function.Routes)
plan.Scaling = Scaling{
Type: types.StringValue(function.Scaling.Type),
Low: types.Int64Value(int64(function.Scaling.Low)),
High: types.Int64Value(int64(function.Scaling.High)),
}
plan.Deployment = OpenAPIDeploymentsToDeployments(function.Deployments)

Expand Down Expand Up @@ -518,6 +540,7 @@ func (r *FunctionResource) Delete(ctx context.Context, req resource.DeleteReques
// FunctionResourceModel maps the resource schema data.
type FunctionResourceModel struct {
ID types.String `tfsdk:"id"`
Revision types.String `tfsdk:"revision"`
ProjectID types.String `tfsdk:"project_id"`
Name types.String `tfsdk:"name"`
Version types.String `tfsdk:"version"`
Expand Down
47 changes: 47 additions & 0 deletions tests/modules/single_function_update/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
data "qernal_provider" "digitalocean" {
name = "digitalocean"
}

resource "qernal_function" "function" {
project_id = var.project_id
version = "1.0.0"
name = var.function_name
description = "Hello world"
image = "testcontainers/helloworld:1.1.0"
port = 80
type = "http"

scaling = {
high = 80
low = 20
type = "cpu"
}

size = {
cpu = 128
memory = 128
}
compliance = ["ipv6"] // TODO: allow this to be blank

deployment {
location = {
provider_id = data.qernal_provider.digitalocean.id
country = "GB"
}

replicas = {
min = 1
max = 1
affinity = {
cloud = false
cluster = false
}
}
}

route {
path = "/*"
methods = ["GET", "HEAD"]
weight = 100
}
}
11 changes: 11 additions & 0 deletions tests/modules/single_function_update/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
terraform {
required_providers {
qernal = {
source = "registry.terraform.io/qernal/qernal"
version = "1.0.0"
}
}
}

provider "qernal" {
}
7 changes: 7 additions & 0 deletions tests/modules/single_function_update/vars.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
variable "project_id" {
type = string
}

variable "function_name" {
type = string
}
154 changes: 141 additions & 13 deletions tests/qernal_function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,20 @@ package tests
import (
"fmt"
"os"
"strings"
"testing"
"time"

"github.com/google/uuid"
"github.com/gruntwork-io/terratest/modules/files"
http_helper "github.com/gruntwork-io/terratest/modules/http-helper"
"github.com/gruntwork-io/terratest/modules/terraform"
)

func validateResponseBody(status int, body string) bool {
if status == 200 && strings.Contains(body, "Hello Word") {
return true
}
// func validateResponseBody(status int, body string) bool {
// if status == 200 && strings.Contains(body, "Hello Word") {
// return true
// }

return false
}
// return false
// }

func TestValidFunction(t *testing.T) {
t.Parallel()
Expand Down Expand Up @@ -71,11 +68,142 @@ func TestValidFunction(t *testing.T) {
// tfFunctionName := terraform.Output(t, terraformOptions, "function_name")
// assert.Equal(t, functionName, tfFunctionName)

// validate our function deployed
host, err := getDefaultHost(projId)
// // validate our function deployed
// host, err := getDefaultHost(projId)
// if err != nil {
// t.Fatal(err)
// }

// http_helper.HttpGetWithRetryWithCustomValidation(t, fmt.Sprintf("https://%s/", host), nil, 30, 3*time.Second, validateResponseBody)
}

func TestUpdateFunction(t *testing.T) {
t.Parallel()

// create org
orgId, _, err := createOrg()
if err != nil {
t.Fatal("failed to create org")
}

// create project
projId, _, err := createProj(orgId)
if err != nil {
t.Fatal("failed to create project")
}

// define a project name and validate it in the response
functionName := uuid.NewString()
functionNameUpdated := uuid.NewString()
moduleName := "./modules/single_function_update"

// copy provider.tf
defer os.Remove(fmt.Sprintf("%s/provider.tf", moduleName))
err = files.CopyFile("./modules/provider.tf", fmt.Sprintf("%s/provider.tf", moduleName))
if err != nil {
t.Fatal(err)
t.Fatal("failed to copy provider file")
}

http_helper.HttpGetWithRetryWithCustomValidation(t, fmt.Sprintf("https://%s/", host), nil, 30, 3*time.Second, validateResponseBody)
defer func() {
if err := cleanupTerraformFiles(moduleName); err != nil {
t.Logf("Warning: Failed to clean up Terraform files: %v", err)
}
}()

// initial creation
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: moduleName,
Vars: map[string]interface{}{
"project_id": projId,
"function_name": functionName,
},
})

defer deleteOrg(orgId)
defer deleteProj(projId)
defer terraform.Destroy(t, terraformOptions)

terraform.InitAndApply(t, terraformOptions)

// update
terraformOptionsUpdate := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: moduleName,
Vars: map[string]interface{}{
"project_id": projId,
"function_name": functionNameUpdated,
},
})

terraform.InitAndApply(t, terraformOptionsUpdate)

// validate output
// tfFunctionName := terraform.Output(t, terraformOptions, "function_name")
// assert.Equal(t, functionName, tfFunctionName)

// // validate our function deployed
// host, err := getDefaultHost(projId)
// if err != nil {
// t.Fatal(err)
// }

// http_helper.HttpGetWithRetryWithCustomValidation(t, fmt.Sprintf("https://%s/", host), nil, 30, 3*time.Second, validateResponseBody)
}

// func TestValidFunctionWithSecret(t *testing.T) {
// t.Parallel()

// // create org
// orgId, _, err := createOrg()
// if err != nil {
// t.Fatal("failed to create org")
// }

// // create project
// projId, _, err := createProj(orgId)
// if err != nil {
// t.Fatal("failed to create project")
// }

// // define a project name and validate it in the response
// functionName := uuid.NewString()
// moduleName := "./modules/single_function"

// // copy provider.tf
// defer os.Remove(fmt.Sprintf("%s/provider.tf", moduleName))
// err = files.CopyFile("./modules/provider.tf", fmt.Sprintf("%s/provider.tf", moduleName))
// if err != nil {
// t.Fatal("failed to copy provider file")
// }

// defer func() {
// if err := cleanupTerraformFiles(moduleName); err != nil {
// t.Logf("Warning: Failed to clean up Terraform files: %v", err)
// }
// }()

// terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
// TerraformDir: moduleName,
// Vars: map[string]interface{}{
// "project_id": projId,
// "function_name": functionName,
// },
// })

// defer deleteOrg(orgId)
// defer deleteProj(projId)
// defer terraform.Destroy(t, terraformOptions)

// terraform.InitAndApply(t, terraformOptions)

// // validate output
// // tfFunctionName := terraform.Output(t, terraformOptions, "function_name")
// // assert.Equal(t, functionName, tfFunctionName)

// // validate our function deployed
// host, err := getDefaultHost(projId)
// if err != nil {
// t.Fatal(err)
// }

// http_helper.HttpGetWithRetryWithCustomValidation(t, fmt.Sprintf("https://%s/", host), nil, 30, 3*time.Second, validateResponseBody)
// }

0 comments on commit 3b82604

Please sign in to comment.