diff --git a/go.mod b/go.mod index a041882..d2580ab 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/hashicorp/terraform-plugin-log v0.8.0 github.com/hashicorp/terraform-plugin-testing v1.2.0 github.com/stretchr/testify v1.8.4 - gitswarm.f5net.com/terraform-providers/f5osclient v1.0.5 + gitswarm.f5net.com/terraform-providers/f5osclient v1.0.7 ) require ( diff --git a/go.sum b/go.sum index c6e0cc8..f5a0c97 100644 --- a/go.sum +++ b/go.sum @@ -218,8 +218,8 @@ github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6e github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zclconf/go-cty v1.13.1 h1:0a6bRwuiSHtAmqCqNOE+c2oHgepv0ctoxU4FUe43kwc= github.com/zclconf/go-cty v1.13.1/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0= -gitswarm.f5net.com/terraform-providers/f5osclient v1.0.5 h1:BAHOti8Jy0N/B6z8apUpYteCA5K11zcE5W8yHQHiWOc= -gitswarm.f5net.com/terraform-providers/f5osclient v1.0.5/go.mod h1:k+4tg9l6yO3FlFh3dkXGc+Wl+LOB/AXu302hAX6nhDU= +gitswarm.f5net.com/terraform-providers/f5osclient v1.0.7 h1:46YL6qdeG0lOkZwZH+nVAOspoEmQSl+N79p9hUL7JvU= +gitswarm.f5net.com/terraform-providers/f5osclient v1.0.7/go.mod h1:k+4tg9l6yO3FlFh3dkXGc+Wl+LOB/AXu302hAX6nhDU= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 8d23ba2..5099e95 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -34,7 +34,6 @@ type F5osProviderModel struct { Port types.Int64 `tfsdk:"port"` TeemDisable types.Bool `tfsdk:"teem_disable"` DisableSslVerify types.Bool `tfsdk:"disable_tls_verify"` - // TrustedCertpath types.String `tfsdk:"trusted_cert_path"` } type TeemData struct { ResourceName string @@ -74,10 +73,6 @@ func (p *F5osProvider) Schema(ctx context.Context, req provider.SchemaRequest, r MarkdownDescription: "Port Number to be used to make API calls to HOST", Optional: true, }, - // "trusted_cert_path": schema.StringAttribute{ - // MarkdownDescription: "Valid Trusted CA Certificate path", - // Optional: true, - // }, "disable_tls_verify": schema.BoolAttribute{ MarkdownDescription: "`disable_tls_verify` controls whether a client verifies the server's certificate chain and host name. default it is set to `true`. If `disable_tls_verify` is true, crypto/tls accepts any certificate presented by the server and any host name in that certificate. In this mode, TLS is susceptible to machine-in-the-middle attacks unless custom verification is used.\ncan be provided by `DISABLE_TLS_VERIFY` environment variable.\n\n~> **NOTE** If it is set to `false`, certificate/ca certificates should be added to `trusted store` of host where we are running this provider.", Optional: true, @@ -181,12 +176,7 @@ func (p *F5osProvider) Configure(ctx context.Context, req provider.ConfigureRequ } client, err := f5ossdk.NewSession(f5osConfig) if err != nil { - resp.Diagnostics.AddError( - "Unable to Create f5os Client", - "An unexpected error occurred when creating the f5os client connection."+ - "If the error is not clear, please contact the provider developers.\n\n"+ - "f5os Client Error: "+err.Error(), - ) + resp.Diagnostics.AddError(fmt.Sprintf("%+v", err.Error()), "") return } client.Teem = teemDisable diff --git a/internal/provider/tenant_image_resource.go b/internal/provider/tenant_image_resource.go index 4baf6e0..69c3851 100644 --- a/internal/provider/tenant_image_resource.go +++ b/internal/provider/tenant_image_resource.go @@ -160,13 +160,14 @@ func (r *TenantImageResource) Create(ctx context.Context, req resource.CreateReq if data.UploadFromPath.IsNull() { respByte, err := r.importImage(ctx, data) if err != nil { - resp.Diagnostics.AddError("F5OS Client Error:", fmt.Sprintf("Unable to Import Image, got error: %s", err)) + resp.Diagnostics.AddError("[F5OS]Unable to Import Image:", fmt.Sprintf("%s", err)) return } if string(respByte) != "Import Image Transfer Success" { - resp.Diagnostics.AddError("Client Error", "Import Image failed") + resp.Diagnostics.AddError("[F5OS]", "Import Image failed") return } + } else { respByte, err := r.uploadImage(ctx, data) if err != nil { diff --git a/internal/provider/tenant_resource.go b/internal/provider/tenant_resource.go index 7815d3d..ca1af34 100644 --- a/internal/provider/tenant_resource.go +++ b/internal/provider/tenant_resource.go @@ -4,6 +4,8 @@ import ( "context" "fmt" "strconv" + "strings" + "time" "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" @@ -109,7 +111,6 @@ func (r *TenantResource) Schema(ctx context.Context, req resource.SchemaRequest, Validators: []validator.String{ stringvalidator.OneOf([]string{"one", "small", "medium", "large"}...), }, - // Default: stringdefault.StaticString("one"), }, "dag_ipv6_prefix_length": schema.Int64Attribute{ MarkdownDescription: "Configuring DAG Global IPv6 Prefix Length,value Range from `1` to `128`.Default is `128`.", @@ -227,9 +228,11 @@ func (r *TenantResource) Create(ctx context.Context, req resource.CreateRequest, return } } + stop := r.client.F5OsKeepAlive(15 * time.Second) imageObj, err := r.client.GetImage(data.ImageName.ValueString()) if err != nil { - resp.Diagnostics.AddError("Unable to Get Image Details", fmt.Sprintf("Error:%s", err)) + stop <- true + resp.Diagnostics.AddError(fmt.Sprintf("%v", err), "") return } var availableFlag = true @@ -239,11 +242,12 @@ func (r *TenantResource) Create(ctx context.Context, req resource.CreateRequest, } } if !availableFlag { - resp.Diagnostics.AddError("Unable to Get Image Details", fmt.Sprintf("Get Image: %s failed with error:%s", data.ImageName.ValueString(), "not-present")) + stop <- true + resp.Diagnostics.AddError(fmt.Sprintf("%v", err), "") return } - tenantConfig := getTenantCreateConfig(ctx, req, resp) + tenantConfig := r.getTenantCreateConfig(ctx, req, resp) if data.Type.ValueString() == "BIG-IP-Next" { tenantConfig.F5TenantsTenant[0].Config.DeploymentFile = data.DeploymentFile.ValueString() @@ -254,14 +258,20 @@ func (r *TenantResource) Create(ctx context.Context, req resource.CreateRequest, teemInfo := make(map[string]interface{}) teemInfo["teemData"] = r.teemData r.client.Metadata = teemInfo - err = r.client.SendTeem(teemInfo) - if err != nil { - resp.Diagnostics.AddError("Teem Error", fmt.Sprintf("Sending Teem Data failed: %s", err)) - } + _ = r.client.SendTeem(teemInfo) + // if err != nil { + // resp.Diagnostics.AddError("Teem Error", fmt.Sprintf("Sending Teem Data failed: %s", err)) + // } + tflog.Info(ctx, fmt.Sprintf("Timeout :%+v", int(data.Timeout.ValueInt64()))) respByte, err := r.client.CreateTenant(tenantConfig, int(data.Timeout.ValueInt64())) if err != nil { - resp.Diagnostics.AddError("F5OS Client Error:", fmt.Sprintf("Tenant Deploy failed, got error: %s", err)) - _ = r.client.DeleteTenant(data.Name.ValueString()) + resp.Diagnostics.AddError(fmt.Sprintf("%v", err.Error()), "") + if strings.Contains(err.Error(), "400 Bad Request") { + stop <- true + return + } + // _ = r.client.DeleteTenant(data.Name.ValueString()) + stop <- true return } tflog.Info(ctx, fmt.Sprintf("tenantConfig Response:%+v", string(respByte))) @@ -271,9 +281,11 @@ func (r *TenantResource) Create(ctx context.Context, req resource.CreateRequest, respByte2, err := r.client.GetTenant(data.Name.ValueString()) if err != nil { - resp.Diagnostics.AddError("F5OS Client Error", fmt.Sprintf("Unable to Read/Get Tenants, got error: %s", err)) + stop <- true + resp.Diagnostics.AddError(fmt.Sprintf("%v", err.Error()), "") return } + stop <- true tflog.Info(ctx, fmt.Sprintf("get tenantConfig :%+v", respByte2)) r.tenantResourceModeltoState(ctx, respByte2, data) // mutex.Unlock() @@ -292,11 +304,14 @@ func (r *TenantResource) Read(ctx context.Context, req resource.ReadRequest, res return } //respByte, err := r.client.GetTenant(data.Name.ValueString()) + stop := r.client.F5OsKeepAlive(15 * time.Second) respByte, err := r.client.GetTenant(data.Id.ValueString()) if err != nil { - resp.Diagnostics.AddError("F5OS Client Error", fmt.Sprintf("Unable to Read/Get Tenants, got error: %s", err)) + stop <- true + resp.Diagnostics.AddError(fmt.Sprintf("%v", err.Error()), "") return } + stop <- true r.tenantResourceModeltoState(ctx, respByte, data) // Save updated data into Terraform state @@ -312,15 +327,17 @@ func (r *TenantResource) Update(ctx context.Context, req resource.UpdateRequest, if resp.Diagnostics.HasError() { return } - tenantConfig := getTenantUpdateConfig(ctx, req, resp) + tenantConfig := r.getTenantUpdateConfig(ctx, req, resp) if data.Type.ValueString() == "BIG-IP-Next" { tenantConfig.F5TenantsTenants.Tenant[0].Config.DeploymentFile = data.DeploymentFile.ValueString() } tflog.Info(ctx, fmt.Sprintf("[Update] tenantConfig :%+v", tenantConfig)) // mutex.Lock() + stop := r.client.F5OsKeepAlive(15 * time.Second) respByte, err := r.client.UpdateTenant(tenantConfig, int(data.Timeout.ValueInt64())) if err != nil { + stop <- true resp.Diagnostics.AddError("F5OS Client Error:", fmt.Sprintf("Tenant Deploy failed, got error: %s", err)) return } @@ -328,9 +345,11 @@ func (r *TenantResource) Update(ctx context.Context, req resource.UpdateRequest, respByte2, err := r.client.GetTenant(data.Name.ValueString()) if err != nil { - resp.Diagnostics.AddError("F5OS Client Error", fmt.Sprintf("Unable to Read/Get Tenants, got error: %s", err)) + stop <- true + resp.Diagnostics.AddError(fmt.Sprintf("%v", err.Error()), "") return } + stop <- true r.tenantResourceModeltoState(ctx, respByte2, data) tflog.Info(ctx, fmt.Sprintf("Updated State:%+v", data)) // mutex.Unlock() @@ -347,10 +366,11 @@ func (r *TenantResource) Delete(ctx context.Context, req resource.DeleteRequest, if resp.Diagnostics.HasError() { return } - + stop := r.client.F5OsKeepAlive(15 * time.Second) err := r.client.DeleteTenant(data.Name.ValueString()) + stop <- true if err != nil { - resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to Delete Imported Image, got error: %s", err)) + resp.Diagnostics.AddError(fmt.Sprintf("%v", err.Error()), "") return } } @@ -395,7 +415,7 @@ func (r *TenantResource) tenantResourceModeltoState(ctx context.Context, respDat data.Cryptos = types.StringValue(respData.F5TenantsTenant[0].State.Cryptos) } -func getTenantCreateConfig(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) *f5ossdk.F5ReqTenants { +func (r *TenantResource) getTenantCreateConfig(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) *f5ossdk.F5ReqTenants { var data *TenantResourceModel // Read Terraform plan data into the model @@ -418,11 +438,21 @@ func getTenantCreateConfig(ctx context.Context, req resource.CreateRequest, resp // tenantSubbj.Config.MacData.F5TenantL2InlineMacBlockSize = data.MacBlockSize.ValueString() // } // tenantSubbj.Config.MacData.F5TenantL2InlineMacBlockSize = data.MacBlockSize.ValueString() - if data.Memory.IsNull() { - tenantSubbj.Config.Memory = 3.5*1024*int(data.CpuCores.ValueInt64()) + (512) - } else { + if !data.Memory.IsNull() && !data.Memory.IsUnknown() { tenantSubbj.Config.Memory = int(data.Memory.ValueInt64()) + } else { + tflog.Info(ctx, fmt.Sprintf("r.client.PlatformType:%+v", r.client.PlatformType)) + if r.client.PlatformType == "r2800" || r.client.PlatformType == "r2000" || r.client.PlatformType == "r4000" || r.client.PlatformType == "r4800" { + tenantSubbj.Config.Memory = 3 * 1024 * int(data.CpuCores.ValueInt64()) + } else { + tenantSubbj.Config.Memory = (3.5 * 1024 * int(data.CpuCores.ValueInt64())) + (512) + } } + + // tenantSubbj.Config.Memory = 3.5*1024*int(data.CpuCores.ValueInt64()) + (512) + // } else { + + // } data.Vlans.ElementsAs(ctx, &tenantSubbj.Config.Vlans, false) tenantSubbj.Config.PrefixLength = int(data.MgmtPrefix.ValueInt64()) tenantSubbj.Config.RunningState = data.RunningState.ValueString() @@ -435,7 +465,7 @@ func getTenantCreateConfig(ctx context.Context, req resource.CreateRequest, resp return tenantConfig } -func getTenantUpdateConfig(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) *f5ossdk.F5ReqTenantsPatch { +func (r *TenantResource) getTenantUpdateConfig(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) *f5ossdk.F5ReqTenantsPatch { var data *TenantResourceModel // Read Terraform plan data into the model @@ -451,13 +481,15 @@ func getTenantUpdateConfig(ctx context.Context, req resource.UpdateRequest, resp tenantSubbj.Config.VcpuCoresPerNode = int(data.CpuCores.ValueInt64()) tenantSubbj.Config.DagIpv6PrefixLength = int(data.DagIpv6prefixLength.ValueInt64()) tenantSubbj.Config.MacData.F5TenantL2InlineMacBlockSize = data.MacBlockSize.ValueString() - if data.Memory.IsNull() { - tenantSubbj.Config.Memory = 3.5*1024*int(data.CpuCores.ValueInt64()) + (512) - } else { + if !data.Memory.IsNull() && !data.Memory.IsUnknown() { tenantSubbj.Config.Memory = int(data.Memory.ValueInt64()) + } else { + if r.client.PlatformType == "r2800" || r.client.PlatformType == "r2000" || r.client.PlatformType == "r4000" || r.client.PlatformType == "r4800" { + tenantSubbj.Config.Memory = 3 * 1024 * int(data.CpuCores.ValueInt64()) + } else { + tenantSubbj.Config.Memory = (3.5 * 1024 * int(data.CpuCores.ValueInt64())) + (512) + } } - //tenantSubbj.Config.Memory = 3.5*1024*int(data.CpuCores.ValueInt64()) + (512) - //tenantSubbj.Config.Memory = int(data.Memory.ValueInt64()) data.Nodes.ElementsAs(ctx, &tenantSubbj.Config.Nodes, false) data.Vlans.ElementsAs(ctx, &tenantSubbj.Config.Vlans, false) tenantSubbj.Config.PrefixLength = int(data.MgmtPrefix.ValueInt64()) diff --git a/internal/provider/tenant_resource_test.go b/internal/provider/tenant_resource_test.go index 366fe07..b9ffe95 100644 --- a/internal/provider/tenant_resource_test.go +++ b/internal/provider/tenant_resource_test.go @@ -145,9 +145,15 @@ func TestUnitTenantDeployResourceUnitTC1(t *testing.T) { w.WriteHeader(http.StatusOK) if r.Method == "GET" && (count == 0 || count == 1 || count == 2) { _, _ = fmt.Fprintf(w, "%s", loadFixtureString("./fixtures/tenant_config.json")) - } - if r.Method == "GET" && (count == 3 || count == 4 || count == 5) { + } else if r.Method == "GET" && (count == 3 || count == 4 || count == 5) { _, _ = fmt.Fprintf(w, "%s", loadFixtureString("./fixtures/tenant_update_config.json")) + } else if r.Method == "GET" { + _, _ = fmt.Fprintf(w, ` + {"ietf-restconf:errors": {"error": [{ + "error-type": "application", + "error-tag": "invalid-value", + "error-message": "uri keypath not found" + }]}}`) } count++ }) @@ -197,6 +203,21 @@ func TestUnitTenantDeployResourceUnitTC2(t *testing.T) { w.WriteHeader(http.StatusOK) _, _ = fmt.Fprintf(w, "%s", loadFixtureString("./fixtures/platform_r4k_state.json")) }) + mux.HandleFunc("/restconf/data/f5-tenant-images:images/image=BIGIP-17.1.0-0.0.16.ALL-F5OS.qcow2.zip.bundle", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintf(w, `{ + "f5-tenant-images:image": [ + { + "name": "BIGIP-17.1.0-0.0.16.ALL-F5OS.qcow2.zip.bundle", + "in-use": false, + "type": "vm-image", + "status": "replicated", + "date": "2023-8-17", + "size": "2.27 GB" + } + ] + }`) + }) mux.HandleFunc("/restconf/data/f5-tenants:tenants", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusCreated) _, _ = fmt.Fprintf(w, ``) @@ -205,9 +226,20 @@ func TestUnitTenantDeployResourceUnitTC2(t *testing.T) { w.WriteHeader(http.StatusOK) _, _ = fmt.Fprintf(w, "%s", loadFixtureString("./fixtures/tenant_r4k_get_status.json")) }) + var count = 0 mux.HandleFunc("/restconf/data/f5-tenants:tenants/tenant=testtenant-ecosys2", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) - _, _ = fmt.Fprintf(w, "%s", loadFixtureString("./fixtures/tenant_r4k_config.json")) + if r.Method == "GET" && (count == 0 || count == 1 || count == 2) { + _, _ = fmt.Fprintf(w, "%s", loadFixtureString("./fixtures/tenant_r4k_config.json")) + } else if r.Method == "GET" { + _, _ = fmt.Fprintf(w, ` + {"ietf-restconf:errors": {"error": [{ + "error-type": "application", + "error-tag": "invalid-value", + "error-message": "uri keypath not found" + }]}}`) + } + count++ }) defer teardown() @@ -250,6 +282,21 @@ func TestUnitTenantDeployResourceUnitTC3(t *testing.T) { w.WriteHeader(http.StatusNoContent) _, _ = fmt.Fprintf(w, ``) }) + mux.HandleFunc("/restconf/data/f5-tenant-images:images/image=BIGIP-17.1.0-0.0.16.ALL-F5OS.qcow2.zip.bundle", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprintf(w, `{ + "f5-tenant-images:image": [ + { + "name": "BIGIP-17.1.0-0.0.16.ALL-F5OS.qcow2.zip.bundle", + "in-use": false, + "type": "vm-image", + "status": "replicated", + "date": "2023-8-17", + "size": "2.27 GB" + } + ] + }`) + }) mux.HandleFunc("/restconf/data/f5-tenants:tenants", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusCreated) _, _ = fmt.Fprintf(w, ``) @@ -268,7 +315,7 @@ func TestUnitTenantDeployResourceUnitTC3(t *testing.T) { // Read testing { Config: testAccTenantDeployResourceTC3Config, - ExpectError: regexp.MustCompile("Tenant Deploy failed, got error"), + ExpectError: regexp.MustCompile("Tenant Deployment Pending"), }, }, }) diff --git a/internal/provider/vlan_resource.go b/internal/provider/vlan_resource.go index afa3cb5..40aa963 100644 --- a/internal/provider/vlan_resource.go +++ b/internal/provider/vlan_resource.go @@ -129,13 +129,13 @@ func (r *VlanResource) Read(ctx context.Context, req resource.ReadRequest, resp tflog.Info(ctx, fmt.Sprintf("[READ] Vlan :%+v", data.Id.ValueString())) vlanId, err := strconv.Atoi(data.Id.ValueString()) if err != nil { - resp.Diagnostics.AddError("F5OS Client Error", fmt.Sprintf("String to Int conversion failed, got error: %s", err)) + resp.Diagnostics.AddError(fmt.Sprintf("[F5OS] %v", err), fmt.Sprintf("String to Int conversion failed for ID:%s", data.Id.ValueString())) return } tflog.Info(ctx, fmt.Sprintf("[READ] Vlan :%+v", vlanId)) partData, err := r.client.GetVlan(vlanId) if err != nil { - resp.Diagnostics.AddError("F5OS Client Error", fmt.Sprintf("Unable to Read/Get Vlan, got error: %s", err)) + resp.Diagnostics.AddError(fmt.Sprintf("%v", err), fmt.Sprintf("Unable to Read/Get Vlan ID:%d", vlanId)) return } tflog.Debug(ctx, fmt.Sprintf("VlanResp :%+v", partData)) diff --git a/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/.gitlab-ci.yml b/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/.gitlab-ci.yml index 8aa3f2c..73bc5e2 100644 --- a/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/.gitlab-ci.yml +++ b/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/.gitlab-ci.yml @@ -18,12 +18,38 @@ stages: - test - report -unit_test: +# unit_test: +# stage: test +# before_script: +# - go mod download +# script: +# - go test -coverprofile=coverage_report $(go list ./... | grep -v /vendor/) +# - go tool cover -html=coverage_report -o coverage_report.html +# artifacts: +# paths: +# - "$CI_PROJECT_DIR/coverage_report.html" +# expire_in: "1 days" +# coverage: '/coverage: \d+\.\d+\% of statements/' + +func_test1: + stage: test + before_script: + - go mod download + script: + - go test -coverprofile=coverage_report -v -timeout 120m -run=TestDeployTenantTC3 + - go tool cover -html=coverage_report -o coverage_report.html + artifacts: + paths: + - "$CI_PROJECT_DIR/coverage_report.html" + expire_in: "1 days" + coverage: '/coverage: \d+\.\d+\% of statements/' + +func_test2: stage: test before_script: - go mod download script: - - go test -coverprofile=coverage_report $(go list ./... | grep -v /vendor/) + - go test -coverprofile=coverage_report -v -timeout 120m -run=TestDeployTenantTC4 - go tool cover -html=coverage_report -o coverage_report.html artifacts: paths: @@ -34,7 +60,9 @@ unit_test: pages: stage: report dependencies: - - unit_test + # - unit_test + - func_test1 + - func_test2 script: - echo 'cleaning old pages' - rm -rf public diff --git a/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/f5os.go b/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/f5os.go index fb5a86f..021caaf 100644 --- a/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/f5os.go +++ b/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/f5os.go @@ -78,15 +78,17 @@ type F5os struct { PlatformVersion string UriRoot string } +type requestError struct { + ErrorType string `json:"error-type,omitempty"` + ErrorTag string `json:"error-tag,omitempty"` + ErrorPath string `json:"error-path,omitempty"` + ErrorMessage string `json:"error-message,omitempty"` +} + type F5osError struct { IetfRestconfErrors struct { - Error []struct { - ErrorType string `json:"error-type"` - ErrorTag string `json:"error-tag"` - ErrorPath string `json:"error-path"` - ErrorMessage string `json:"error-message"` - } `json:"error"` - } `json:"ietf-restconf:errors"` + Error []requestError `json:"error,omitempty"` + } `json:"ietf-restconf:errors,omitempty"` } // Upload contains information about a file upload status @@ -167,7 +169,7 @@ func NewSession(f5osObj *F5osConfig) (*F5os, error) { f5osObj.ConfigOptions = defaultConfigOptions } tr := &http.Transport{} - f5osLogger.Info("[NewSession]", "DisableSSLVerify", hclog.Fmt("%+v", f5osObj.DisableSSLVerify)) + // f5osLogger.Info("[NewSession]", "DisableSSLVerify", hclog.Fmt("%+v", f5osObj.DisableSSLVerify)) tr.TLSClientConfig = &tls.Config{ InsecureSkipVerify: f5osObj.DisableSSLVerify, } @@ -215,9 +217,22 @@ func NewSession(f5osObj *F5osConfig) (*F5os, error) { } defer res.Body.Close() respData, err := io.ReadAll(res.Body) - f5osLogger.Debug("[NewSession]", "Status Code:", hclog.Fmt("%+v", res.StatusCode)) + f5osLogger.Info("[NewSession]", "Status Code:", hclog.Fmt("%+v", res.StatusCode)) if res.StatusCode == 401 { - return nil, fmt.Errorf("%+v with error:%+v", res.Status, string(respData)) + mapData := make(map[string]interface{}) + json.Unmarshal(respData, &mapData) + errorNew := struct { + Status string `json:"status"` + Message string `json:"message"` + Details json.RawMessage `json:"details"` + }{ + Status: res.Status, + Message: mapData["ietf-restconf:errors"].(map[string]interface{})["error"].([]interface{})[0].(map[string]interface{})["error-tag"].(string), + Details: json.RawMessage(string(respData)), + } + jsonData, _ := json.Marshal(errorNew) + return nil, fmt.Errorf("%+v", string(jsonData)) + //return nil, fmt.Errorf("\"message\": \"%+v\", \"deatils\": \"%+v\"", res.Status, string(respData)) } if err != nil { return nil, err @@ -288,6 +303,73 @@ func (p *F5os) doRequest(op, path string, body []byte) ([]byte, error) { return nil, nil } +func (p *F5os) doTenantRequest(op, path string, body []byte) ([]byte, error) { + f5osLogger.Debug("[doTenantRequest]", "Request path", hclog.Fmt("%+v", path)) + if len(body) > 0 { + f5osLogger.Debug("[doTenantRequest]", "Request body", hclog.Fmt("%+v", string(body))) + } + req, err := http.NewRequest(op, path, bytes.NewBuffer(body)) + if err != nil { + return nil, err + } + req.Header.Set("X-Auth-Token", p.Token) + req.Header.Set("Content-Type", contentTypeHeader) + client := &http.Client{ + Transport: p.Transport, + Timeout: p.ConfigOptions.APICallTimeout, + } + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + f5osLogger.Info("[doTenantRequest]", "Resp CODE", hclog.Fmt("%+v", resp.StatusCode)) + if resp.StatusCode == 200 || resp.StatusCode == 201 { + return io.ReadAll(resp.Body) + } + if resp.StatusCode >= 400 { + respData, _ := io.ReadAll(resp.Body) + mapData := make(map[string]interface{}) + json.Unmarshal(respData, &mapData) + errMsg := "" + if val, ok := mapData["ietf-restconf:errors"]; ok { + if val.(map[string]interface{})["error"].([]interface{})[0].(map[string]interface{})["error-message"] != nil { + errMsg = val.(map[string]interface{})["error"].([]interface{})[0].(map[string]interface{})["error-message"].(string) + } + } + f5osLogger.Info("[doTenantRequest]", "Resp Msg", hclog.Fmt("%+v", errMsg)) + json.Unmarshal(respData, &mapData) + errorNew := struct { + Status string `json:"status"` + Message string `json:"message"` + Details json.RawMessage `json:"details"` + }{ + Status: resp.Status, + Message: errMsg, + Details: json.RawMessage(string(respData)), + } + jsonData, _ := json.Marshal(errorNew) + return nil, fmt.Errorf("%+v", string(jsonData)) + + // byteData, _ := io.ReadAll(resp.Body) + // var errorNew F5osError + // json.Unmarshal(byteData, &errorNew) + // return nil, errorNew.Error() + + // byteData, _ := io.ReadAll(resp.Body) + // errorNew := struct { + // Message string `json:"message"` + // Details json.RawMessage `json:"details"` + // }{ + // Message: resp.Status, + // Details: json.RawMessage(string(byteData)), + // } + // jsonData, _ := json.Marshal(errorNew) + // return nil, fmt.Errorf("%+v", string(jsonData)) + } + return nil, nil +} + func (p *F5os) SendTeem(teemDataInput interface{}) error { recordData := &RawTelemetry{} teemData := teemDataInput.(map[string]interface{})["teemData"] @@ -325,6 +407,12 @@ func (p *F5os) GetRequest(path string) ([]byte, error) { return p.doRequest("GET", url, nil) } +func (p *F5os) GetTenantRequest(path string) ([]byte, error) { + url := fmt.Sprintf("%s%s%s", p.Host, p.UriRoot, path) + f5osLogger.Info("[GetTenantRequest]", "Request path", hclog.Fmt("%+v", url)) + return p.doTenantRequest("GET", url, nil) +} + func (p *F5os) DeleteRequest(path string) error { url := fmt.Sprintf("%s%s%s", p.Host, p.UriRoot, path) f5osLogger.Debug("[DeleteRequest]", "Request path", hclog.Fmt("%+v", url)) @@ -348,6 +436,13 @@ func (p *F5os) PatchRequest(path string, body []byte) ([]byte, error) { return p.doRequest("PATCH", url, body) } +func (p *F5os) PostTenantRequest(path string, body []byte) ([]byte, error) { + url := fmt.Sprintf("%s%s%s", p.Host, p.UriRoot, path) + f5osLogger.Debug("[PostTenantRequest]", "Request path", hclog.Fmt("%+v", url)) + // return p.doTenantRequest("POST", url, body) + return p.doTenantRequest("POST", url, body) +} + func (p *F5os) PostRequest(path string, body []byte) ([]byte, error) { url := fmt.Sprintf("%s%s%s", p.Host, p.UriRoot, path) f5osLogger.Debug("[PostRequest]", "Request path", hclog.Fmt("%+v", url)) @@ -886,6 +981,7 @@ func (p *F5os) setPlatformType() ([]byte, error) { //check state key present in above response map object if val.(map[string]interface{})["state"].(map[string]interface{})["description"] != nil { p.PlatformType = "rSeries Platform" + p.PlatformType = val.(map[string]interface{})["state"].(map[string]interface{})["description"].(string) uriPlatformVersion := "/openconfig-system:system/f5-system-image:image/state/install" p.setPlatformVersion(uriPlatformVersion) } diff --git a/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/partition.go b/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/partition.go index 141b8f4..d6bd2af 100644 --- a/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/partition.go +++ b/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/partition.go @@ -304,7 +304,7 @@ func (p *F5os) VlanConfig(vlanConfig *F5ReqVlansConfig) ([]byte, error) { func (p *F5os) GetVlan(vlanId int) (*F5RespVlan, error) { url := fmt.Sprintf("%s/vlan=%d", uriVlan, vlanId) f5osVlan := &F5RespVlan{} - byteData, err := p.GetRequest(url) + byteData, err := p.GetTenantRequest(url) if err != nil { return nil, err } diff --git a/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/tenant.go b/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/tenant.go index 866ce69..7e3ef18 100644 --- a/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/tenant.go +++ b/vendor/gitswarm.f5net.com/terraform-providers/f5osclient/tenant.go @@ -29,18 +29,66 @@ const ( uriTenant = "/f5-tenants:tenants" ) +func (p *F5os) GetImageVerify(imageName string) (*F5RespTenantImagesStatus, error) { + imgFldr := strings.Join(strings.Split(imageName, ".")[0:7], ".") + imgYaml := fmt.Sprintf("%s.yaml", imgFldr) + imgList := []string{imageName, imgFldr, imgYaml} + timOut := 360 + t1 := time.Now() + for _, img := range imgList { + // add timeout for each image + for { + t2 := time.Now() + timeDiff := t2.Sub(t1) + if timeDiff.Seconds() > float64(timOut) { + return nil, fmt.Errorf("image verification still in In Progress with Timeout Period, please increase timeout") + } + imagenew := fmt.Sprintf("/image=%s", img) + url := fmt.Sprintf("%s%s", uriTenantImage, imagenew) + f5osLogger.Info("[GetImageVerify]", "Request path", hclog.Fmt("%+v", url)) + imagesStatus := &F5RespTenantImagesStatus{} + byteData, err := p.GetTenantRequest(url) + f5osLogger.Debug("[GetImageVerify]", "Image Resp:", hclog.Fmt("%+v", string(byteData))) + if err != nil { + if strings.Contains(err.Error(), "uri keypath not found") { + continue + } + } + for _, val := range imagesStatus.TenantImages { + if val.Name == img && (val.Status == "replicated" || val.Status == "processed" || val.Status == "verified") { + continue + } + // return imagesStatus, nil + } + } + } + return nil, nil +} + func (p *F5os) GetImage(imageName string) (*F5RespTenantImagesStatus, error) { imagenew := fmt.Sprintf("/image=%s", imageName) url := fmt.Sprintf("%s%s", uriTenantImage, imagenew) f5osLogger.Info("[GetImage]", "Request path", hclog.Fmt("%+v", url)) imagesStatus := &F5RespTenantImagesStatus{} - byteData, err := p.GetRequest(url) + byteData, err := p.GetTenantRequest(url) if err != nil { + if strings.Contains(err.Error(), "uri keypath not found") { + errorNew := struct { + Status string `json:"status"` + Message string `json:"message"` + Details json.RawMessage `json:"details"` + }{ + Status: "404 Not Found", + Message: fmt.Sprintf("Tenant Image (%s) not found", imageName), + Details: json.RawMessage(err.Error()), + } + jsonData, _ := json.Marshal(errorNew) + return nil, fmt.Errorf("%+v", string(jsonData)) + // return nil, fmt.Errorf("Tenant Image (%s) not found", imageName) + } return nil, err } - if strings.Contains(string(byteData), "uri keypath not found") { - return nil, fmt.Errorf("Tenant Image (%s) not found", imageName) - } + f5osLogger.Debug("[GetImage]", "Image Resp:", hclog.Fmt("%+v", string(byteData))) json.Unmarshal(byteData, imagesStatus) f5osLogger.Debug("[GetImage]", "Image Struct:", hclog.Fmt("%+v", imagesStatus)) return imagesStatus, nil @@ -237,16 +285,78 @@ func (p *F5os) DeleteTenantImage(tenantImage string) error { return fmt.Errorf("delete Tenant Image failed with:%+v", respMap) } +// https://{{velos_chassis1_system_controller_ip}}:443/api + +func (p *F5os) GetApi() ([]byte, error) { + url := fmt.Sprintf("%s%s", p.Host, "/api") + url = strings.Replace(url, "8888", "443", -1) + byteData, err := p.doTenantRequest("GET", url, []byte("")) + if err != nil { + return byteData, err + } + f5osLogger.Debug("[GetApi]", "Api Resp", hclog.Fmt("%+v", string(byteData))) + return byteData, nil +} + +func (p *F5os) F5OsKeepAlive(delay time.Duration) chan bool { + stop := make(chan bool) + go func() { + for { + select { + case <-time.After(delay): + _, _ = p.GetApi() + // f5osLogger.Info("[schedule]", "RequestGetApi ", hclog.Fmt("%+v", string(resp))) + case <-stop: + return + } + } + }() + return stop +} + +func (p *F5os) CreateTenantAndGetApi(tenantObj *F5ReqTenants, timeOut int) ([]byte, error) { + // create a channel to run the CreateTenant function + chan1 := make(chan []byte) + err1 := make(chan error) + // create a channel to run the GetApi function + chan2 := make(chan []byte) + err2 := make(chan error) + + go func() { + resp, err := p.CreateTenant(tenantObj, timeOut) + chan1 <- resp + err1 <- err + }() + go func() { + for { + resp, err := p.GetApi() + f5osLogger.Info("[CreateTenantAndGetApi]", "RequestGetApi ", hclog.Fmt("%+v", string(resp))) + time.Sleep(15 * time.Second) + chan2 <- resp + err2 <- err + } + }() + if <-err1 != nil { + return <-chan1, <-err1 + } + if <-err2 == nil { + f5osLogger.Info("[CreateTenantAndGetApi]", "RequestGetApi-Out", hclog.Fmt("%+v", <-chan2)) + } + return <-chan1, <-err1 +} + func (p *F5os) CreateTenant(tenantObj *F5ReqTenants, timeOut int) ([]byte, error) { - url := uriTenant - f5osLogger.Info("[CreateTenant]", "Request path", hclog.Fmt("%+v", url)) + // url := uriTenant + f5osLogger.Info("[CreateTenant]", "Request path", hclog.Fmt("%+v", uriTenant)) byteBody, err := json.Marshal(tenantObj) if err != nil { return byteBody, err } f5osLogger.Info("[CreateTenant]", "Body", hclog.Fmt("%+v", string(byteBody))) - respData, err := p.PostRequest(uriTenant, byteBody) + // stop := p.schedule(15 * time.Second) + respData, err := p.PostTenantRequest(uriTenant, byteBody) if err != nil { + // stop <- true return respData, err } f5osLogger.Info("[CreateTenant]", "Resp: ", hclog.Fmt("%+v", string(respData))) @@ -254,27 +364,50 @@ func (p *F5os) CreateTenant(tenantObj *F5ReqTenants, timeOut int) ([]byte, error for { check, err := p.tenantWait(tenantObj.F5TenantsTenant[0].Name, tenantObj.F5TenantsTenant[0].Config.RunningState) if err != nil { + if err.Error() == "tenant status not found" { + time.Sleep(30 * time.Second) + t1 = time.Now() + continue + } + // stop <- true return []byte(""), err } t2 := time.Now() timeDiff := t2.Sub(t1) + f5osLogger.Info("[CreateTenant]", "timeDiff: ", hclog.Fmt("%+v", timeDiff)) if timeDiff.Seconds() > float64(timeOut) { - return []byte(""), fmt.Errorf("tenant deployment still in In Progress with Timeout Period, please increase timeout") + tenantMap, _ := p.getTenantDeployStatus(tenantObj.F5TenantsTenant[0].Name) + tenantResp, _ := json.Marshal(tenantMap) + tenantStatus := tenantMap["f5-tenants:state"].(map[string]interface{})["status"].(string) + errorNew := struct { + Status string `json:"status"` + Message string `json:"message"` + Details json.RawMessage `json:"details"` + }{ + Status: "200 status OK", + Message: fmt.Sprintf("tenant deployment status is still in (%+v) within in %d seconds timeout period", tenantStatus, timeOut), + Details: json.RawMessage(string(tenantResp)), + } + jsonData, _ := json.Marshal(errorNew) + // stop <- true + return []byte(""), fmt.Errorf("%+v", string(jsonData)) + //return []byte(""), fmt.Errorf("[TF-100]tenant deployment still in In Progress with in Timeout Period, please increase timeout") } if check { - time.Sleep(20 * time.Second) + time.Sleep(80 * time.Second) continue } else { time.Sleep(20 * time.Second) + // stop <- true return []byte("Tenant Deployment Success"), nil } } - return []byte("Tenant Deployment Success"), nil + // return []byte("Tenant Deployment Success"), nil } func (p *F5os) UpdateTenant(tenantObj *F5ReqTenantsPatch, timeOut int) ([]byte, error) { - url := fmt.Sprintf("%s", uriTenant) - f5osLogger.Info("[UpdateTenant]", "Request path", hclog.Fmt("%+v", url)) + // url := fmt.Sprintf("%s", uriTenant) + f5osLogger.Info("[UpdateTenant]", "Request path", hclog.Fmt("%+v", uriTenant)) byteBody, err := json.Marshal(tenantObj) if err != nil { return byteBody, err @@ -289,6 +422,11 @@ func (p *F5os) UpdateTenant(tenantObj *F5ReqTenantsPatch, timeOut int) ([]byte, for { check, err := p.tenantWait(tenantObj.F5TenantsTenants.Tenant[0].Name, tenantObj.F5TenantsTenants.Tenant[0].Config.RunningState) if err != nil { + if err.Error() == "tenant status not found" { + time.Sleep(30 * time.Second) + t1 = time.Now() + continue + } return []byte(""), err } t2 := time.Now() @@ -304,7 +442,7 @@ func (p *F5os) UpdateTenant(tenantObj *F5ReqTenantsPatch, timeOut int) ([]byte, return []byte("Tenant Deployment Success"), nil } } - return []byte("Tenant Deployment Success"), nil + // return []byte("Tenant Deployment Success"), nil } func (p *F5os) GetTenant(tenantName string) (*F5RespTenants, error) { @@ -312,26 +450,77 @@ func (p *F5os) GetTenant(tenantName string) (*F5RespTenants, error) { url := fmt.Sprintf("%s%s", uriTenant, tenantNameurl) f5osLogger.Info("[GetTenant]", "Request path", hclog.Fmt("%+v", url)) tenantStatus := &F5RespTenants{} - byteData, err := p.GetRequest(url) + byteData, err := p.GetTenantRequest(url) if err != nil { - return nil, err + errorNew := struct { + Status string `json:"status"` + Message string `json:"message"` + Details json.RawMessage `json:"details"` + }{ + Status: "404 Not Found", + Message: fmt.Sprintf("Tenant (%s) not found", tenantName), + Details: json.RawMessage(err.Error()), + } + jsonData, _ := json.Marshal(errorNew) + return nil, fmt.Errorf("%+v", string(jsonData)) + // return nil, err } f5osLogger.Info("[GetTenant]", "Tenant Info:", hclog.Fmt("%+v", string(byteData))) json.Unmarshal(byteData, tenantStatus) if len(tenantStatus.F5TenantsTenant) == 0 { - return nil, fmt.Errorf("GetTenant failed with :%+v", string(byteData)) + errorNew := struct { + Status string `json:"status"` + Message string `json:"message"` + Details json.RawMessage `json:"details"` + }{ + Status: "404 Not Found", + Message: fmt.Sprintf("Tenant (%s) not found", tenantName), + Details: json.RawMessage(string(byteData)), + } + jsonData, _ := json.Marshal(errorNew) + return nil, fmt.Errorf("%+v", string(jsonData)) + // return nil, fmt.Errorf("GetTenant failed with :%+v", string(byteData)) } - f5osLogger.Info("[GetTenant]", "Tenant Struct:", hclog.Fmt("%+v", tenantStatus)) + // f5osLogger.Info("[GetTenant]", "Instances Length:", hclog.Fmt("%+v", len(tenantStatus.F5TenantsTenant[0].State.Instances.Instance))) return tenantStatus, nil } +func (p *F5os) CheckTenantnotexist(tenantName string) bool { + tenantNameurl := fmt.Sprintf("/tenant=%s", tenantName) + url := fmt.Sprintf("%s%s", uriTenant, tenantNameurl) + f5osLogger.Info("[CheckTenantnotexist]", "Request path", hclog.Fmt("%+v", url)) + byteData, err := p.GetRequest(url) + if err != nil { + return false + } + var tenantStatus map[string]interface{} + // { + // "ietf-restconf:errors": { + // "error": [ + // { + // "error-type": "application", + // "error-tag": "invalid-value", + // "error-message": "uri keypath not found" + // } + // ] + // } + // } + json.Unmarshal(byteData, &tenantStatus) + // check error-message + f5osLogger.Info("[CheckTenantnotexist]", "Tenant", hclog.Fmt("%+v uri result :%+v", tenantName, tenantStatus["ietf-restconf:errors"].(map[string]interface{})["error"].([]interface{})[0].(map[string]interface{})["error-message"].(string))) + return tenantStatus["ietf-restconf:errors"].(map[string]interface{})["error"].([]interface{})[0].(map[string]interface{})["error-message"].(string) == "uri keypath not found" +} + func (p *F5os) DeleteTenant(tenantName string) error { url := fmt.Sprintf("%s%s%s/tenant=%s", p.Host, p.UriRoot, uriTenant, tenantName) f5osLogger.Info("[DeleteTenant]", "Request path", hclog.Fmt("%+v", url)) - _, err := p.doRequest("DELETE", url, []byte("")) + _, err := p.doTenantRequest("DELETE", url, []byte("")) if err != nil { return err } + f5osLogger.Debug("[DeleteTenant]", "wait for 50 sec", hclog.Fmt("%d", 10)) + time.Sleep(50 * time.Second) + p.CheckTenantnotexist(tenantName) return nil } func (p *F5os) tenantWait(tenantName, runningState string) (bool, error) { @@ -340,9 +529,11 @@ func (p *F5os) tenantWait(tenantName, runningState string) (bool, error) { return true, err } if tenantMap["f5-tenants:state"].(map[string]interface{})["status"] == nil { - return true, nil + return true, fmt.Errorf("tenant status not found") } tenantStatus := tenantMap["f5-tenants:state"].(map[string]interface{})["status"].(string) + f5osLogger.Info("[tenantWait]", "tenantName:", hclog.Fmt("%+v", tenantName)) + f5osLogger.Info("[tenantWait]", "f5-tenants:state", hclog.Fmt("%+v", tenantStatus)) if strings.Contains(tenantStatus, "Running") && runningState == "deployed" { return false, nil } @@ -353,8 +544,20 @@ func (p *F5os) tenantWait(tenantName, runningState string) (bool, error) { return true, nil } if strings.Contains(tenantStatus, "Pending") { + // map[instance:[map[creation-time: instance-id:2 node:2 phase:Insufficient slots to deploy tenant pod-name:test-tenant22-2 ready-time: status:Tenant deployment will be processed when the slot available in partition]]] + jsonDataold, _ := json.Marshal(tenantMap["f5-tenants:state"].(map[string]interface{})["instances"].(map[string]interface{})["instance"].([]interface{})[0]) if tenantMap["f5-tenants:state"].(map[string]interface{})["instances"] != nil { - return false, fmt.Errorf("%v", tenantMap["f5-tenants:state"].(map[string]interface{})["instances"]) + errorNew := struct { + Status string `json:"status"` + Message string `json:"message"` + Details json.RawMessage `json:"details"` + }{ + Status: "Tenant Deployment Pending", + Message: tenantMap["f5-tenants:state"].(map[string]interface{})["instances"].(map[string]interface{})["instance"].([]interface{})[0].(map[string]interface{})["phase"].(string), + Details: json.RawMessage(string(jsonDataold)), + } + jsonData, _ := json.Marshal(errorNew) + return false, fmt.Errorf("%v", string(jsonData)) } } return true, nil @@ -363,7 +566,7 @@ func (p *F5os) getTenantDeployStatus(tenantName string) (map[string]interface{}, url := fmt.Sprintf("%s/tenant=%s/state", uriTenant, tenantName) f5osLogger.Info("[getTenantDeployStatus]", "Request path", hclog.Fmt("%+v", url)) var ss map[string]interface{} - byteData, err := p.GetRequest(url) + byteData, err := p.GetTenantRequest(url) if err != nil { return nil, err } diff --git a/vendor/modules.txt b/vendor/modules.txt index 3136f17..3fbd892 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -307,7 +307,7 @@ github.com/zclconf/go-cty/cty/function/stdlib github.com/zclconf/go-cty/cty/gocty github.com/zclconf/go-cty/cty/json github.com/zclconf/go-cty/cty/set -# gitswarm.f5net.com/terraform-providers/f5osclient v1.0.5 +# gitswarm.f5net.com/terraform-providers/f5osclient v1.0.7 ## explicit; go 1.21.3 gitswarm.f5net.com/terraform-providers/f5osclient # golang.org/x/crypto v0.7.0