diff --git a/.changelog/904.txt b/.changelog/904.txt new file mode 100644 index 00000000..7fa35626 --- /dev/null +++ b/.changelog/904.txt @@ -0,0 +1,7 @@ +```release-note:feature +`resource/cloudavenue_org_certificate_library` - Added new resource to manage certificate in the Cloud Avenue Organization. +``` + +```release-note:feature +`datasource/cloudavenue_org_certificate_library` - Added new datasource to get certificate information in the Cloud Avenue Organization. +``` \ No newline at end of file diff --git a/docs/data-sources/org_certificate_library.md b/docs/data-sources/org_certificate_library.md new file mode 100644 index 00000000..559f3225 --- /dev/null +++ b/docs/data-sources/org_certificate_library.md @@ -0,0 +1,31 @@ +--- +page_title: "cloudavenue_org_certificate_library Data Source - cloudavenue" +subcategory: "Organization" +description: |- + The cloudavenue_org_certificate_library data source allows you to retrieve information about an certificate in your organization's library. +--- + +# cloudavenue_org_certificate_library (Data Source) + +The `cloudavenue_org_certificate_library` data source allows you to retrieve information about an certificate in your organization's library. + +## Example Usage + +```terraform +data "cloudavenue_org_certificate_library" "example" { + name = "my-certificate-library" +} +``` + + +## Schema + +### Optional + +- `id` (String) The ID of the certificate library. Ensure that one and only one attribute from this collection is set : `name`, `id`. +- `name` (String) The name of the certificate library. Ensure that one and only one attribute from this collection is set : `name`, `id`. + +### Read-Only + +- `certificate` (String) The certificate content. It can be a PEM encoded certificate or a certificate chain. +- `description` (String) The description of the certificate library. diff --git a/docs/resources/org_certificate_library.md b/docs/resources/org_certificate_library.md new file mode 100644 index 00000000..73cb7427 --- /dev/null +++ b/docs/resources/org_certificate_library.md @@ -0,0 +1,46 @@ +--- +page_title: "cloudavenue_org_certificate_library Resource - cloudavenue" +subcategory: "Organization" +description: |- + The cloudavenue_org_certificate_library resource allows you to manage certificate in your organization's library. +--- + +# cloudavenue_org_certificate_library (Resource) + +The `cloudavenue_org_certificate_library` resource allows you to manage certificate in your organization's library. + +## Example Usage + +```terraform +resource "cloudavenue_org_certificate_library" "example" { + name = "company-certificate" + description = "dev environment certificate" + certificate = chomp(file("/my/certificate/path/cert.pem")) + private_key = chomp(file("/my/certificate/path/key.pem")) +} +``` + + +## Schema + +### Required + +- `certificate` (String) (ForceNew) The certificate content. It can be a PEM encoded certificate or a certificate chain. Contains all strings including the BEGIN CERTIFICATE and END CERTIFICATE lines. No empty lines are allowed. +- `name` (String) The name of the certificate library. + +### Optional + +- `description` (String) The description of the certificate library. +- `passphrase` (String, Sensitive) (ForceNew) The passphrase of the private key. +- `private_key` (String, Sensitive) (ForceNew) The private key of the certificate in PEM format. + +### Read-Only + +- `id` (String) The ID of the certificate library. + +## Import + +Import is supported using the following syntax: +```shell +terraform import cloudavenue_org_certificate_library.example nameOrID +``` \ No newline at end of file diff --git a/examples/data-sources/cloudavenue_org_certificate_library/data-source.tf b/examples/data-sources/cloudavenue_org_certificate_library/data-source.tf new file mode 100644 index 00000000..34643547 --- /dev/null +++ b/examples/data-sources/cloudavenue_org_certificate_library/data-source.tf @@ -0,0 +1,3 @@ +data "cloudavenue_org_certificate_library" "example" { + name = "my-certificate-library" +} diff --git a/examples/resources/cloudavenue_org_certificate_library/import.sh b/examples/resources/cloudavenue_org_certificate_library/import.sh new file mode 100644 index 00000000..2d31d129 --- /dev/null +++ b/examples/resources/cloudavenue_org_certificate_library/import.sh @@ -0,0 +1 @@ +terraform import cloudavenue_org_certificate_library.example nameOrID \ No newline at end of file diff --git a/examples/resources/cloudavenue_org_certificate_library/resource.tf b/examples/resources/cloudavenue_org_certificate_library/resource.tf new file mode 100644 index 00000000..2ee74b95 --- /dev/null +++ b/examples/resources/cloudavenue_org_certificate_library/resource.tf @@ -0,0 +1,6 @@ +resource "cloudavenue_org_certificate_library" "example" { + name = "company-certificate" + description = "dev environment certificate" + certificate = chomp(file("/my/certificate/path/cert.pem")) + private_key = chomp(file("/my/certificate/path/key.pem")) +} diff --git a/go.mod b/go.mod index 7bdca2b9..8e13cd7b 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,6 @@ toolchain go1.23.3 require ( github.com/FrangipaneTeam/terraform-analytic-tool v0.0.12 - github.com/FrangipaneTeam/terraform-plugin-framework-superschema v1.8.1 - github.com/FrangipaneTeam/terraform-plugin-framework-supertypes v0.4.0 github.com/aws/aws-sdk-go v1.55.6 github.com/drhodes/golorem v0.0.0-20220328165741-da82e5b29246 github.com/google/uuid v1.6.0 @@ -21,7 +19,8 @@ require ( github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0 github.com/iancoleman/strcase v0.3.0 - github.com/orange-cloudavenue/cloudavenue-sdk-go v0.20.1 + github.com/madflojo/testcerts v1.4.0 + github.com/orange-cloudavenue/cloudavenue-sdk-go v0.21.1 github.com/orange-cloudavenue/common-go/print v0.0.0-20250109171729-2be550d5d3ac github.com/orange-cloudavenue/common-go/utils v0.0.0-20240119163616-66b473d92339 github.com/orange-cloudavenue/terraform-plugin-framework-planmodifiers v1.4.0 @@ -65,7 +64,7 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.24.0 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect - github.com/go-resty/resty/v2 v2.16.3 // indirect + github.com/go-resty/resty/v2 v2.16.5 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/hashicorp/cli v1.1.6 // indirect diff --git a/go.sum b/go.sum index ed724c61..6a3c2a45 100644 --- a/go.sum +++ b/go.sum @@ -4,10 +4,6 @@ github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/FrangipaneTeam/terraform-analytic-tool v0.0.12 h1:rbh0EtyILnuyu07RuOhrEVXXXRcrxSvKSVtOO14h5ok= github.com/FrangipaneTeam/terraform-analytic-tool v0.0.12/go.mod h1:j3TxedNm9WrKKseOSBKxnNtquuXa0FQChO/QdcvPKtg= -github.com/FrangipaneTeam/terraform-plugin-framework-superschema v1.8.1 h1:ov6LOLLANE9nZVQ1DrpMLuITkejMzTbZLE54xtxZ14A= -github.com/FrangipaneTeam/terraform-plugin-framework-superschema v1.8.1/go.mod h1:AkcBw7L/PhgCm1A4P4adGrbEjE7i2maeCn/Jeh5t5Lo= -github.com/FrangipaneTeam/terraform-plugin-framework-supertypes v0.4.0 h1:5lFfjKOhBxBQNwQ63PZWBc5Unqgi5ppYq9RDoN05N+k= -github.com/FrangipaneTeam/terraform-plugin-framework-supertypes v0.4.0/go.mod h1:klzXBi/0nMGXBh4bzRjP2wef+HE6rfCMia81Glc2+eY= github.com/Kunde21/markdownfmt/v3 v3.1.0 h1:KiZu9LKs+wFFBQKhrZJrFZwtLnCCWJahL+S+E/3VnM0= github.com/Kunde21/markdownfmt/v3 v3.1.0/go.mod h1:tPXN1RTyOzJwhfHoon9wUr4HGYmWgVxSQN6VBJDkrVc= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -103,8 +99,8 @@ github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= -github.com/go-resty/resty/v2 v2.16.3 h1:zacNT7lt4b8M/io2Ahj6yPypL7bqx9n1iprfQuodV+E= -github.com/go-resty/resty/v2 v2.16.3/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= +github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM= +github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -221,6 +217,8 @@ github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4F github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/madflojo/testcerts v1.4.0 h1:I09gN0C1ly9IgeVNcAqKk8RAKIJTe3QnFrrPBDyvzN4= +github.com/madflojo/testcerts v1.4.0/go.mod h1:MW8sh39gLnkKh4K0Nc55AyHEDl9l/FBLDUsQhpmkuo0= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= @@ -262,8 +260,8 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/orange-cloudavenue/cloudavenue-sdk-go v0.20.1 h1:5oJ/xg5q+USbwKDkDGpIAyB4hyYiNBECHJyrtVY8wAQ= -github.com/orange-cloudavenue/cloudavenue-sdk-go v0.20.1/go.mod h1:flkZyfFFO60w78vhTackWb1FxoEm5EVA8yakrrJRN1I= +github.com/orange-cloudavenue/cloudavenue-sdk-go v0.21.1 h1:Uy/AkLQM/KQzDMFBCVR7vh4BppgROa/GK5UNfXbP7e0= +github.com/orange-cloudavenue/cloudavenue-sdk-go v0.21.1/go.mod h1:1jc0W7Me1Oq0kSPoJNYcH6emJ5HruIIsh1//Wp26AJQ= github.com/orange-cloudavenue/common-go/print v0.0.0-20250109171729-2be550d5d3ac h1:f1Fd70+PMDTK6FE4gHdNfoHSQHLn5pfJMTjZPzOWZtc= github.com/orange-cloudavenue/common-go/print v0.0.0-20250109171729-2be550d5d3ac/go.mod h1:IYtCusqpEGS0dhC6F8X9GHrrt1gp1zHaNhSKGYV59Xg= github.com/orange-cloudavenue/common-go/utils v0.0.0-20240119163616-66b473d92339 h1:DEKcWLGbEhu/I6kn9NAXhVCFrbPhR+Ef7oLmpLVnnPM= diff --git a/internal/provider/alb/service_engine_group_schema.go b/internal/provider/alb/service_engine_group_schema.go index 816b0b2e..ee92e31a 100644 --- a/internal/provider/alb/service_engine_group_schema.go +++ b/internal/provider/alb/service_engine_group_schema.go @@ -3,14 +3,14 @@ package alb import ( "context" + superschema "github.com/orange-cloudavenue/terraform-plugin-framework-superschema" + "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/schema/validator" schemaD "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" - - superschema "github.com/FrangipaneTeam/terraform-plugin-framework-superschema" ) func serviceEngineGroupSchema(_ context.Context) superschema.Schema { diff --git a/internal/provider/alb/service_engine_group_types.go b/internal/provider/alb/service_engine_group_types.go index 82a00f51..32e9c2ab 100644 --- a/internal/provider/alb/service_engine_group_types.go +++ b/internal/provider/alb/service_engine_group_types.go @@ -1,7 +1,7 @@ package alb import ( - supertypes "github.com/FrangipaneTeam/terraform-plugin-framework-supertypes" + supertypes "github.com/orange-cloudavenue/terraform-plugin-framework-supertypes" ) type serviceEngineGroupModel struct { diff --git a/internal/provider/alb/service_engine_groups_schema.go b/internal/provider/alb/service_engine_groups_schema.go index 3cabe928..0491de7c 100644 --- a/internal/provider/alb/service_engine_groups_schema.go +++ b/internal/provider/alb/service_engine_groups_schema.go @@ -3,14 +3,14 @@ package alb import ( "context" + superschema "github.com/orange-cloudavenue/terraform-plugin-framework-superschema" + "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/schema/validator" schemaD "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" - - superschema "github.com/FrangipaneTeam/terraform-plugin-framework-superschema" ) func serviceEngineGroupsSchema(ctx context.Context) superschema.Schema { diff --git a/internal/provider/alb/service_engine_groups_types.go b/internal/provider/alb/service_engine_groups_types.go index 5055b111..42b2eef4 100644 --- a/internal/provider/alb/service_engine_groups_types.go +++ b/internal/provider/alb/service_engine_groups_types.go @@ -1,6 +1,6 @@ package alb -import supertypes "github.com/FrangipaneTeam/terraform-plugin-framework-supertypes" +import supertypes "github.com/orange-cloudavenue/terraform-plugin-framework-supertypes" type serviceEngineGroupsModel struct { ID supertypes.StringValue `tfsdk:"id"` diff --git a/internal/provider/org/certificate_library_datasource.go b/internal/provider/org/certificate_library_datasource.go index 74528b5b..83bdf803 100644 --- a/internal/provider/org/certificate_library_datasource.go +++ b/internal/provider/org/certificate_library_datasource.go @@ -9,9 +9,10 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/orange-cloudavenue/cloudavenue-sdk-go/v1/org" + "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/client" "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/metrics" - "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/provider/common/org" ) var ( @@ -24,18 +25,21 @@ func NewCertificateLibraryDatasource() datasource.DataSource { } type CertificateLibraryDatasource struct { - client *client.CloudAvenue - org org.Org + client *client.CloudAvenue + orgClient *org.Client } // Init Initializes the data source. -func (d *CertificateLibraryDatasource) Init(ctx context.Context, dm *CertificateLibraryDatasourcesGoModel) (diags diag.Diagnostics) { - // Uncomment the following lines if you need to access to the Org - d.org, diags = org.Init(d.client) - if diags.HasError() { - return +func (d *CertificateLibraryDatasource) Init(ctx context.Context, dm *CertificateLibraryDatasourceModel) (diags diag.Diagnostics) { + var err error + + org, err := d.client.CAVSDK.V1.Org() + if err != nil { + diags.AddError("Error initializing ORG client", err.Error()) } + d.orgClient = org.Client + return } @@ -44,7 +48,7 @@ func (d *CertificateLibraryDatasource) Metadata(ctx context.Context, req datasou } func (d *CertificateLibraryDatasource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { - resp.Schema = certificateLibraryDatasourceSchema(ctx).GetDataSource(ctx) + resp.Schema = certificateLibrarySchema(ctx).GetDataSource(ctx) } func (d *CertificateLibraryDatasource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { @@ -67,10 +71,7 @@ func (d *CertificateLibraryDatasource) Configure(ctx context.Context, req dataso func (d *CertificateLibraryDatasource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { defer metrics.New("data.cloudavenue_org_certificate_library", d.client.GetOrgName(), metrics.Read)() - config := &CertificateLibraryDatasourcesGoModel{} - - // If the data source don't have same schema/structure as the resource, you can use the following code: - // config := &CertificateLibraryDatasourceModel{} + config := &CertificateLibraryDatasourceModel{} // Read Terraform configuration data into the model resp.Diagnostics.Append(req.Config.Get(ctx, config)...) @@ -88,23 +89,32 @@ func (d *CertificateLibraryDatasource) Read(ctx context.Context, req datasource. Implement the data source read logic here. */ - // If read function is identical to the resource, you can use the following code: - /* - s := &CertificateLibraryDatasourcesGoResource{ - client: d.client, - // org: d.org, - // vdc: d.vdc, - // vapp: d.vapp, - } - - // Read data from the API - data, _, diags := s.read(ctx, config) - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { - return - } - - // Save data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) - */ + s := &CertificateLibraryResource{ + client: d.client, + orgClient: d.orgClient, + } + + configResource := &CertificateLibraryModel{ + ID: config.ID, + Name: config.Name, + } + + // Read data from the API + data, found, diags := s.read(ctx, configResource) + if !found { + resp.Diagnostics.AddError("Resource not found", fmt.Sprintf("The Certificate %s(%s) was not found", config.Name.Get(), config.ID.Get())) + return + } + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + config.ID.Set(data.ID.Get()) + config.Name.Set(data.Name.Get()) + config.Description.Set(data.Description.Get()) + config.Certificate.Set(data.Certificate.Get()) + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &config)...) } diff --git a/internal/provider/org/certificate_library_resource.go b/internal/provider/org/certificate_library_resource.go new file mode 100644 index 00000000..cfe52119 --- /dev/null +++ b/internal/provider/org/certificate_library_resource.go @@ -0,0 +1,307 @@ +package org + +import ( + "context" + "fmt" + + "github.com/vmware/go-vcloud-director/v2/govcd" + + "github.com/hashicorp/terraform-plugin-framework/diag" + + "github.com/hashicorp/terraform-plugin-framework/resource" + + "github.com/orange-cloudavenue/cloudavenue-sdk-go/pkg/urn" + "github.com/orange-cloudavenue/cloudavenue-sdk-go/v1/org" + "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/client" + "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/metrics" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ resource.Resource = &CertificateLibraryResource{} + _ resource.ResourceWithConfigure = &CertificateLibraryResource{} + _ resource.ResourceWithImportState = &CertificateLibraryResource{} +) + +// NewCertificateLibraryResource is a helper function to simplify the provider implementation. +func NewCertificateLibraryResource() resource.Resource { + return &CertificateLibraryResource{} +} + +// CertificateLibraryResource is the resource implementation. +type CertificateLibraryResource struct { + client *client.CloudAvenue + orgClient *org.Client +} + +// Init Initializes the resource. +func (r *CertificateLibraryResource) Init(ctx context.Context, rm *CertificateLibraryModel) (diags diag.Diagnostics) { + var err error + + org, err := r.client.CAVSDK.V1.Org() + if err != nil { + diags.AddError("Error initializing ORG client", err.Error()) + } + + r.orgClient = org.Client + + return +} + +// Metadata returns the resource type name. +func (r *CertificateLibraryResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_" + categoryName + "_certificate_library" +} + +// Schema defines the schema for the resource. +func (r *CertificateLibraryResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = certificateLibrarySchema(ctx).GetResource(ctx) +} + +func (r *CertificateLibraryResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*client.CloudAvenue) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *client.CloudAvenue, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + r.client = client +} + +// Create creates the resource and sets the initial Terraform state. +func (r *CertificateLibraryResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + defer metrics.New("cloudavenue_org_certificate_library", r.client.GetOrgName(), metrics.Create)() + + plan := &CertificateLibraryModel{} + + // Retrieve values from plan + resp.Diagnostics.Append(req.Plan.Get(ctx, plan)...) + if resp.Diagnostics.HasError() { + return + } + + // Init the resource + resp.Diagnostics.Append(r.Init(ctx, plan)...) + if resp.Diagnostics.HasError() { + return + } + + /* + Implement the resource creation logic here. + */ + + // Create the certificate library + newCertificate, err := r.orgClient.CreateCertificateInLibrary(plan.ToSDKCertificateLibraryModel()) + if err != nil { + resp.Diagnostics.AddError("error while creating certificate %s in library", err.Error()) + return + } + + plan.ID.Set(newCertificate.Certificate.ID) + + // Use generic read function to refresh the state + state, found, d := r.read(ctx, plan) + if !found { + resp.Diagnostics.AddError("Resource not found", fmt.Sprintf("The certificate '%s' was not found after creation.", plan.Name.Get())) + return + } + if d.HasError() { + resp.Diagnostics.Append(d...) + return + } + + // Set state to fully populated data + resp.Diagnostics.Append(resp.State.Set(ctx, state)...) +} + +// Read refreshes the Terraform state with the latest data. +func (r *CertificateLibraryResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + defer metrics.New("cloudavenue_org_certificate_library", r.client.GetOrgName(), metrics.Read)() + + state := &CertificateLibraryModel{} + + // Get current state + resp.Diagnostics.Append(req.State.Get(ctx, state)...) + if resp.Diagnostics.HasError() { + return + } + + // Init the resource + resp.Diagnostics.Append(r.Init(ctx, state)...) + if resp.Diagnostics.HasError() { + return + } + + // Refresh the state + stateRefreshed, found, d := r.read(ctx, state) + if !found { + resp.State.RemoveResource(ctx) + return + } + if d.HasError() { + resp.Diagnostics.Append(d...) + return + } + + // Set refreshed state + resp.Diagnostics.Append(resp.State.Set(ctx, stateRefreshed)...) +} + +// Update updates the resource and sets the updated Terraform state on success. +func (r *CertificateLibraryResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + defer metrics.New("cloudavenue_org_certificate_library", r.client.GetOrgName(), metrics.Update)() + + var ( + plan = &CertificateLibraryModel{} + state = &CertificateLibraryModel{} + ) + + // Get current plan and state + resp.Diagnostics.Append(req.Plan.Get(ctx, plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, state)...) + if resp.Diagnostics.HasError() { + return + } + + // Init the resource + resp.Diagnostics.Append(r.Init(ctx, state)...) + if resp.Diagnostics.HasError() { + return + } + + /* + Implement the resource update here + */ + + certificate, err := r.orgClient.GetCertificateFromLibrary(state.ID.Get()) + if err != nil { + resp.Diagnostics.AddError("error while fetching certificate : %s", err.Error()) + return + } + + certificate.Certificate = plan.ToSDKCertificateLibraryModel() + + // Update the certificate library + if err := certificate.Update(); err != nil { + resp.Diagnostics.AddError("error while updating certificate %s", err.Error()) + return + } + + // Use generic read function to refresh the state + stateRefreshed, _, d := r.read(ctx, plan) + if d.HasError() { + resp.Diagnostics.Append(d...) + return + } + + // Set state to fully populated data + resp.Diagnostics.Append(resp.State.Set(ctx, stateRefreshed)...) +} + +// Delete deletes the resource and removes the Terraform state on success. +func (r *CertificateLibraryResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + defer metrics.New("cloudavenue_org_certificate_library", r.client.GetOrgName(), metrics.Delete)() + + state := &CertificateLibraryModel{} + + // Get current state + resp.Diagnostics.Append(req.State.Get(ctx, state)...) + if resp.Diagnostics.HasError() { + return + } + + // Init the resource + resp.Diagnostics.Append(r.Init(ctx, state)...) + if resp.Diagnostics.HasError() { + return + } + + /* + Implement the resource deletion here + */ + + certificate, err := r.orgClient.GetCertificateFromLibrary(state.ID.Get()) + if err != nil { + resp.Diagnostics.AddError("error while fetching certificate : %s", err.Error()) + return + } + + if err := certificate.Delete(); err != nil { + resp.Diagnostics.AddError("error while deleting certificate : %s", err.Error()) + return + } +} + +func (r *CertificateLibraryResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + defer metrics.New("cloudavenue_org_certificate_library", r.client.GetOrgName(), metrics.Import)() + + // * ID format is CertificateIdOrName + + config := &CertificateLibraryModel{} + + // Init the resource + resp.Diagnostics.Append(r.Init(ctx, config)...) + if resp.Diagnostics.HasError() { + return + } + + if urn.IsCertificateLibraryItem(req.ID) { + config.ID.Set(req.ID) + } else { + config.Name.Set(req.ID) + } + + // Use generic read function to refresh the state + stateRefreshed, found, d := r.read(ctx, config) + if !found { + resp.Diagnostics.AddError("Resource not found", fmt.Sprintf("The certificate '%s' was not found after import.", req.ID)) + return + } + if d.HasError() { + resp.Diagnostics.Append(d...) + return + } + + // Set state to fully populated data + resp.Diagnostics.Append(resp.State.Set(ctx, stateRefreshed)...) +} + +// * CustomFuncs + +// read is a generic read function that can be used by the resource Create, Read and Update functions. +func (r *CertificateLibraryResource) read(_ context.Context, planOrState *CertificateLibraryModel) (stateRefreshed *CertificateLibraryModel, found bool, diags diag.Diagnostics) { + stateRefreshed = planOrState.Copy() + + var ( + certificate *org.CertificateClient + err error + ) + + if planOrState.ID.IsKnown() { + certificate, err = r.orgClient.GetCertificateFromLibrary(planOrState.ID.Get()) + } else { + certificate, err = r.orgClient.GetCertificateFromLibrary(planOrState.Name.Get()) + } + if err != nil { + if govcd.IsNotFound(err) { + return nil, false, diags + } + diags.AddError("error while fetching certificate library: %s", err.Error()) + return nil, false, diags + } + + // Set the refreshed state + stateRefreshed.ID.Set(certificate.Certificate.ID) + stateRefreshed.Name.Set(certificate.Certificate.Name) + stateRefreshed.Description.Set(certificate.Certificate.Description) + stateRefreshed.Certificate.Set(certificate.Certificate.Certificate) + + return stateRefreshed, true, nil +} diff --git a/internal/provider/org/certificate_library_schema.go b/internal/provider/org/certificate_library_schema.go index bc9ce099..cb4c33c3 100644 --- a/internal/provider/org/certificate_library_schema.go +++ b/internal/provider/org/certificate_library_schema.go @@ -3,102 +3,106 @@ package org import ( "context" - schemaD "github.com/hashicorp/terraform-plugin-framework/datasource/schema" - schemaR "github.com/hashicorp/terraform-plugin-framework/resource/schema" - - superschema "github.com/FrangipaneTeam/terraform-plugin-framework-superschema" -) + superschema "github.com/orange-cloudavenue/terraform-plugin-framework-superschema" -// TODO : Remove unused imports. -// ! This is outside import block because golangci-lint remove commented import. -// * Hashicorp Validators -// "github.com/Hashicorp/terraform-plugin-framework-validators/stringvalidator" -// "github.com/Hashicorp/terraform-plugin-framework-validators/boolvalidator" -// "github.com/Hashicorp/terraform-plugin-framework-validators/int64validator" -// "github.com/Hashicorp/terraform-plugin-framework-validators/float64validator" -// "github.com/Hashicorp/terraform-plugin-framework-validators/listvalidator" -// "github.com/Hashicorp/terraform-plugin-framework-validators/mapvalidator" -// "github.com/Hashicorp/terraform-plugin-framework-validators/setvalidator" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" -// * Hashicorp Plan Modifiers Resource -// "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" -// "github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier" -// "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" -// "github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier" -// "github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier" -// "github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier" - -// * Hashicorp Plan Modifiers DataSource -// "github.com/hashicorp/terraform-plugin-framework/datasource/schema/stringplanmodifier" -// "github.com/hashicorp/terraform-plugin-framework/datasource/schema/boolplanmodifier" -// "github.com/hashicorp/terraform-plugin-framework/datasource/schema/int64planmodifier" -// "github.com/hashicorp/terraform-plugin-framework/datasource/schema/listplanmodifier" -// "github.com/hashicorp/terraform-plugin-framework/datasource/schema/mapplanmodifier" -// "github.com/hashicorp/terraform-plugin-framework/datasource/schema/setplanmodifier" - -// * Hashicorp Default Values -// "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" -// "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" -// "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + schemaD "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + schemaR "github.com/hashicorp/terraform-plugin-framework/resource/schema" -// * FrangipaneTeam Custom Validators -// fstringvalidator "github.com/FrangipaneTeam/terraform-plugin-framework-validators/stringvalidator" -// fboolvalidator "github.com/FrangipaneTeam/terraform-plugin-framework-validators/boolvalidator" -// fint64validator "github.com/FrangipaneTeam/terraform-plugin-framework-validators/int64validator" -// flistvalidator "github.com/FrangipaneTeam/terraform-plugin-framework-validators/listvalidator" -// fmapvalidator "github.com/FrangipaneTeam/terraform-plugin-framework-validators/mapvalidator" -// fsetvalidator "github.com/FrangipaneTeam/terraform-plugin-framework-validators/setvalidator" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" -// * FrangipaneTeam Custom Plan Modifiers -// fstringplanmodifier "github.com/FrangipaneTeam/terraform-plugin-framework-planmodifiers/stringplanmodifier" -// fboolplanmodifier "github.com/FrangipaneTeam/terraform-plugin-framework-planmodifiers/boolplanmodifier" -// fint64planmodifier "github.com/FrangipaneTeam/terraform-plugin-framework-planmodifiers/int64planmodifier" -// flistplanmodifier "github.com/FrangipaneTeam/terraform-plugin-framework-planmodifiers/listplanmodifier" -// fmapplanmodifier "github.com/FrangipaneTeam/terraform-plugin-framework-planmodifiers/mapplanmodifier" -// fsetplanmodifier "github.com/FrangipaneTeam/terraform-plugin-framework-planmodifiers/setplanmodifier" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" +) -// How to use types generator: -// 1. Define the schema in the file internal/provider/org/certificate_library_datasources_go_schema.go -// 2. Add the resource or data source to the file internal/provider/provider_resources.go or internal/provider/provider_data_sources.go respectively -// 3. Launch the following command to generate golang structs for the schema: -// go run ./cmd/types-generator/*.go -file internal/provider/org/certificate_library_datasources_go_schema.go -resource cloudavenue_org_certificate_library_datasources_go -is-resource. -func certificateLibraryDatasourceSchema(_ context.Context) superschema.Schema { +func certificateLibrarySchema(_ context.Context) superschema.Schema { return superschema.Schema{ Resource: superschema.SchemaDetails{ - MarkdownDescription: "The `cloudavenue_org_certificate_library_datasources_go` resource allows you to manage ...", + MarkdownDescription: "The `cloudavenue_org_certificate_library` resource allows you to manage certificate in your organization's library.", }, DataSource: superschema.SchemaDetails{ - MarkdownDescription: "The `cloudavenue_org_certificate_library_datasources_go` data source allows you to retrieve information about an ...", + MarkdownDescription: "The `cloudavenue_org_certificate_library` data source allows you to retrieve information about an certificate in your organization's library.", }, Attributes: map[string]superschema.Attribute{ "id": superschema.SuperStringAttribute{ Common: &schemaR.StringAttribute{ Computed: true, - MarkdownDescription: "The ID of the certificate_library_datasources_go.", + MarkdownDescription: "The ID of the certificate library.", + }, + Resource: &schemaR.StringAttribute{ + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + DataSource: &schemaD.StringAttribute{ + Optional: true, + Validators: []validator.String{ + stringvalidator.ExactlyOneOf(path.MatchRoot("name"), path.MatchRoot("id")), + }, }, }, "name": superschema.SuperStringAttribute{ Common: &schemaR.StringAttribute{ - MarkdownDescription: "The name of the certificate_library_datasources_go.", + MarkdownDescription: "The name of the certificate library.", }, Resource: &schemaR.StringAttribute{ Required: true, }, DataSource: &schemaD.StringAttribute{ Computed: true, + Optional: true, + Validators: []validator.String{ + stringvalidator.ExactlyOneOf(path.MatchRoot("name"), path.MatchRoot("id")), + }, }, }, - "single": superschema.SuperSingleNestedAttributeOf[struct{}]{ - Common: &schemaR.SingleNestedAttribute{ - MarkdownDescription: "The name of the index document.", + "description": superschema.SuperStringAttribute{ + Common: &schemaR.StringAttribute{ + MarkdownDescription: "The description of the certificate library.", }, - Resource: &schemaR.SingleNestedAttribute{ + Resource: &schemaR.StringAttribute{ Optional: true, }, - DataSource: &schemaD.SingleNestedAttribute{ + DataSource: &schemaD.StringAttribute{ + Computed: true, + }, + }, + "certificate": superschema.SuperStringAttribute{ + Common: &schemaR.StringAttribute{ + MarkdownDescription: "The certificate content. It can be a PEM encoded certificate or a certificate chain.", + }, + Resource: &schemaR.StringAttribute{ + Required: true, + MarkdownDescription: "Contains all strings including the BEGIN CERTIFICATE and END CERTIFICATE lines. No empty lines are allowed.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + DataSource: &schemaD.StringAttribute{ Computed: true, }, - Attributes: superschema.Attributes{}, + }, + "private_key": superschema.SuperStringAttribute{ + Resource: &schemaR.StringAttribute{ + MarkdownDescription: "The private key of the certificate in PEM format.", + Optional: true, + Sensitive: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + }, + "passphrase": superschema.SuperStringAttribute{ + Resource: &schemaR.StringAttribute{ + MarkdownDescription: "The passphrase of the private key.", + Optional: true, + Sensitive: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, }, }, } diff --git a/internal/provider/org/certificate_library_schema_test.go b/internal/provider/org/certificate_library_schema_test.go index 878dab0b..1a0515b9 100644 --- a/internal/provider/org/certificate_library_schema_test.go +++ b/internal/provider/org/certificate_library_schema_test.go @@ -5,33 +5,34 @@ import ( "testing" fwdatasource "github.com/hashicorp/terraform-plugin-framework/datasource" -) + fwresource "github.com/hashicorp/terraform-plugin-framework/resource" -// TODO : Comment or uncomment the following imports if you are using resources or/and datasources + "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/provider/org" +) -// Unit test for the schema of the resource cloudavenue_org_CertificateLibraryDatasourcesGo -// func TestCertificateLibraryDatasourcesGoResourceSchema(t *testing.T) { -// t.Parallel() +// Unit test for the schema of the resource cloudavenue_org_certificate_library. +func TestCertificateLibraryResourceSchema(t *testing.T) { + t.Parallel() -// ctx := context.Background() -// schemaResponse := &fwresource.SchemaResponse{} + ctx := context.Background() + schemaResponse := &fwresource.SchemaResponse{} -// // Instantiate the resource.Resource and call its Schema method -// org.NewCertificateLibraryDatasource().Schema(ctx, fwresource.SchemaRequest{}, schemaResponse) + // Instantiate the resource.Resource and call its Schema method + org.NewCertificateLibraryResource().Schema(ctx, fwresource.SchemaRequest{}, schemaResponse) -// if schemaResponse.Diagnostics.HasError() { -// t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics) -// } + if schemaResponse.Diagnostics.HasError() { + t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics) + } -// // Validate the schema -// diagnostics := schemaResponse.Schema.ValidateImplementation(ctx) + // Validate the schema + diagnostics := schemaResponse.Schema.ValidateImplementation(ctx) -// if diagnostics.HasError() { -// t.Fatalf("Schema validation diagnostics: %+v", diagnostics) -// } -// } + if diagnostics.HasError() { + t.Fatalf("Schema validation diagnostics: %+v", diagnostics) + } +} -// Unit test for the schema of the datasource cloudavenue_org_CertificateLibraryDatasourcesGo +// Unit test for the schema of the datasource cloudavenue_org_certificate_library func TestCertificateLibraryDatasourceSchema(t *testing.T) { t.Parallel() @@ -40,8 +41,7 @@ func TestCertificateLibraryDatasourceSchema(t *testing.T) { schemaResponse := &fwdatasource.SchemaResponse{} // Instantiate the datasource.Datasource and call its Schema method - - // org.NewCertificateLibraryDatasource().Schema(ctx, fwdatasource.SchemaRequest{}, schemaResponse) + org.NewCertificateLibraryDatasource().Schema(ctx, fwdatasource.SchemaRequest{}, schemaResponse) if schemaResponse.Diagnostics.HasError() { t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics) diff --git a/internal/provider/org/certificate_library_types.go b/internal/provider/org/certificate_library_types.go index 98c604a8..c291e670 100644 --- a/internal/provider/org/certificate_library_types.go +++ b/internal/provider/org/certificate_library_types.go @@ -1,9 +1,43 @@ package org import ( - supertypes "github.com/FrangipaneTeam/terraform-plugin-framework-supertypes" + supertypes "github.com/orange-cloudavenue/terraform-plugin-framework-supertypes" + + "github.com/orange-cloudavenue/cloudavenue-sdk-go/v1/org" + "github.com/orange-cloudavenue/terraform-provider-cloudavenue/pkg/utils" ) -type CertificateLibraryDatasourcesGoModel struct { - ID supertypes.StringValue `tfsdk:"id"` +type CertificateLibraryModel struct { + ID supertypes.StringValue `tfsdk:"id"` + Name supertypes.StringValue `tfsdk:"name"` + Description supertypes.StringValue `tfsdk:"description"` + Certificate supertypes.StringValue `tfsdk:"certificate"` + PrivateKey supertypes.StringValue `tfsdk:"private_key"` + Passphrase supertypes.StringValue `tfsdk:"passphrase"` +} + +type CertificateLibraryDatasourceModel struct { + ID supertypes.StringValue `tfsdk:"id"` + Name supertypes.StringValue `tfsdk:"name"` + Description supertypes.StringValue `tfsdk:"description"` + Certificate supertypes.StringValue `tfsdk:"certificate"` +} + +// ToSDKCertificateLibraryModel converts the data Terraform to the SDK model. +func (rm *CertificateLibraryModel) ToSDKCertificateLibraryModel() org.CertificateModel { + return org.CertificateModel{ + ID: rm.ID.Get(), + Name: rm.Name.Get(), + Description: rm.Description.Get(), + Certificate: rm.Certificate.Get(), + PrivateKey: rm.PrivateKey.Get(), + Passphrase: rm.Passphrase.Get(), + } +} + +// Copy returns a copy of the CertificateLibraryModel. +func (rm *CertificateLibraryModel) Copy() *CertificateLibraryModel { + x := &CertificateLibraryModel{} + utils.ModelCopy(rm, x) + return x } diff --git a/internal/provider/provider_resources.go b/internal/provider/provider_resources.go index c2827f68..6be3649d 100644 --- a/internal/provider/provider_resources.go +++ b/internal/provider/provider_resources.go @@ -20,6 +20,7 @@ import ( "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/provider/edgegw" "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/provider/iam" "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/provider/network" + "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/provider/org" "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/provider/publicip" "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/provider/s3" "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/provider/vapp" @@ -110,5 +111,8 @@ func (p *cloudavenueProvider) Resources(_ context.Context) []func() resource.Res s3.NewBucketACLResource, s3.NewCredentialResource, s3.NewBucketPolicyResource, + + // * ORG + org.NewCertificateLibraryResource, } } diff --git a/internal/testsacc/acctest_datasources_test.go b/internal/testsacc/acctest_datasources_test.go index aed5aae1..75380328 100644 --- a/internal/testsacc/acctest_datasources_test.go +++ b/internal/testsacc/acctest_datasources_test.go @@ -73,5 +73,8 @@ func GetDataSourceConfig() map[testsacc.ResourceName]func() *testsacc.ResourceCo // * VApp VAppDatasourceName: testsacc.NewResourceConfig(NewVAppDatasourceTest()), VAppIsolatedNetworkDataSourceName: testsacc.NewResourceConfig(NewVAppIsolatedNetworkDataSourceTest()), + + // * Org + OrgCertificateLibraryDatasourceName: testsacc.NewResourceConfig(NewOrgCertificateLibraryDatasourceTest()), } } diff --git a/internal/testsacc/acctest_resources_test.go b/internal/testsacc/acctest_resources_test.go index 9f466e22..9099d04a 100644 --- a/internal/testsacc/acctest_resources_test.go +++ b/internal/testsacc/acctest_resources_test.go @@ -74,5 +74,8 @@ func GetResourceConfig() map[testsacc.ResourceName]func() *testsacc.ResourceConf // * IAM IAMUserResourceName: testsacc.NewResourceConfig(NewIAMUserResourceTest()), IAMUserSAMLResourceName: testsacc.NewResourceConfig(NewIAMUserSAMLResourceTest()), + + // * ORG + ORGCertificateLibraryResourceName: testsacc.NewResourceConfig(NewORGCertificateLibraryResourceTest()), } } diff --git a/internal/testsacc/org_certificate_library_datasource_test.go b/internal/testsacc/org_certificate_library_datasource_test.go index c98d9e1f..8d08186d 100644 --- a/internal/testsacc/org_certificate_library_datasource_test.go +++ b/internal/testsacc/org_certificate_library_datasource_test.go @@ -6,13 +6,14 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/orange-cloudavenue/cloudavenue-sdk-go/pkg/urn" "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/helpers/testsacc" ) var _ testsacc.TestACC = &OrgCertificateLibraryDatasource{} const ( - OrgCertificateLibraryDatasourceName = testsacc.ResourceName("data.cloudavenue_org_certificate_library_datasources_go") + OrgCertificateLibraryDatasourceName = testsacc.ResourceName("data.cloudavenue_org_certificate_library") ) type OrgCertificateLibraryDatasource struct{} @@ -27,25 +28,42 @@ func (r *OrgCertificateLibraryDatasource) GetResourceName() string { } func (r *OrgCertificateLibraryDatasource) DependenciesConfig() (resp testsacc.DependenciesConfigResponse) { - // Add dependencies config to the resource - // resp.Append(GetResourceConfig()[OrgCertificateLibraryDatasourcesGoResourceName]().GetDefaultConfig), + resp.Append(GetResourceConfig()[ORGCertificateLibraryResourceName]().GetDefaultConfig) return } func (r *OrgCertificateLibraryDatasource) Tests(ctx context.Context) map[testsacc.TestName]func(ctx context.Context, resourceName string) testsacc.Test { return map[testsacc.TestName]func(ctx context.Context, resourceName string) testsacc.Test{ // * Test One (example) - "example": func(_ context.Context, _ string) testsacc.Test { + "example": func(_ context.Context, resourceName string) testsacc.Test { return testsacc.Test{ // ! Create testing Create: testsacc.TFConfig{ TFConfig: ` - data "cloudavenue_org_certificate_library_datasources_go" "example" { - foo_id = cloudavenue_foo_bar.example.id + data "cloudavenue_org_certificate_library" "example" { + name = cloudavenue_org_certificate_library.example.name }`, - // Here use resource config test to test the data source - // the field example is the name of the test - // Checks: GetResourceConfig()[org_CertificateLibraryDatasourcesGoResourceName]().GetDefaultChecks() + Checks: []resource.TestCheckFunc{ + resource.TestCheckResourceAttrWith(resourceName, "id", urn.TestIsType(urn.CertificateLibraryItem)), + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttrSet(resourceName, "certificate"), + }, + }, + } + }, + "example_id": func(_ context.Context, resourceName string) testsacc.Test { + return testsacc.Test{ + // ! Create testing + Create: testsacc.TFConfig{ + TFConfig: ` + data "cloudavenue_org_certificate_library" "example_id" { + id = cloudavenue_org_certificate_library.example.id + }`, + Checks: []resource.TestCheckFunc{ + resource.TestCheckResourceAttrWith(resourceName, "id", urn.TestIsType(urn.CertificateLibraryItem)), + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttrSet(resourceName, "certificate"), + }, }, } }, @@ -53,6 +71,9 @@ func (r *OrgCertificateLibraryDatasource) Tests(ctx context.Context) map[testsac } func TestAccOrgCertificateLibraryDatasource(t *testing.T) { + cleanup := orgCertificateLibraryResourcePreCheck() + defer cleanup() + resource.Test(t, resource.TestCase{ PreCheck: func() { TestAccPreCheck(t) }, ProtoV6ProviderFactories: TestAccProtoV6ProviderFactories, diff --git a/internal/testsacc/org_certificate_library_resource_test.go b/internal/testsacc/org_certificate_library_resource_test.go new file mode 100644 index 00000000..d9599843 --- /dev/null +++ b/internal/testsacc/org_certificate_library_resource_test.go @@ -0,0 +1,142 @@ +package testsacc + +import ( + "context" + "os" + "testing" + + "github.com/madflojo/testcerts" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/orange-cloudavenue/cloudavenue-sdk-go/pkg/urn" + "github.com/orange-cloudavenue/terraform-provider-cloudavenue/internal/helpers/testsacc" +) + +var _ testsacc.TestACC = &ORGCertificateLibraryResource{} + +const ( + ORGCertificateLibraryResourceName = testsacc.ResourceName("cloudavenue_org_certificate_library") +) + +type ORGCertificateLibraryResource struct{} + +func NewORGCertificateLibraryResourceTest() testsacc.TestACC { + return &ORGCertificateLibraryResource{} +} + +// GetResourceName returns the name of the resource. +func (r *ORGCertificateLibraryResource) GetResourceName() string { + return ORGCertificateLibraryResourceName.String() +} + +func (r *ORGCertificateLibraryResource) DependenciesConfig() (resp testsacc.DependenciesConfigResponse) { + return +} + +func (r *ORGCertificateLibraryResource) Tests(ctx context.Context) map[testsacc.TestName]func(ctx context.Context, resourceName string) testsacc.Test { + return map[testsacc.TestName]func(ctx context.Context, resourceName string) testsacc.Test{ + // * First test named "example" + "example": func(_ context.Context, resourceName string) testsacc.Test { + return testsacc.Test{ + CommonChecks: []resource.TestCheckFunc{ + resource.TestCheckResourceAttrWith(resourceName, "id", urn.TestIsType(urn.CertificateLibraryItem)), + resource.TestCheckResourceAttrSet(resourceName, "certificate"), + resource.TestCheckResourceAttrSet(resourceName, "private_key"), + }, + // ! Create testing + Create: testsacc.TFConfig{ + TFConfig: testsacc.GenerateFromTemplate(resourceName, ` + resource "cloudavenue_org_certificate_library" "example" { + name = {{ generate . "name" }} + description = {{ generate . "description" }} + certificate = chomp(file("/tmp/cert.pem")) + private_key = chomp(file("/tmp/key.pem")) + }`), + Checks: []resource.TestCheckFunc{ + resource.TestCheckResourceAttr(resourceName, "name", testsacc.GetValueFromTemplate(resourceName, "name")), + resource.TestCheckResourceAttr(resourceName, "description", testsacc.GetValueFromTemplate(resourceName, "description")), + resource.TestCheckNoResourceAttr(resourceName, "passphrase"), + }, + }, + // ! Updates testing + Updates: []testsacc.TFConfig{ + { + TFConfig: testsacc.GenerateFromTemplate(resourceName, ` + resource "cloudavenue_org_certificate_library" "example" { + name = {{ generate . "name" }} + description = {{ get . "description" }} + certificate = chomp(file("/tmp/cert.pem")) + private_key = chomp(file("/tmp/key.pem")) + }`), + Checks: []resource.TestCheckFunc{ + resource.TestCheckResourceAttr(resourceName, "name", testsacc.GetValueFromTemplate(resourceName, "name")), + resource.TestCheckResourceAttr(resourceName, "description", testsacc.GetValueFromTemplate(resourceName, "description")), + resource.TestCheckNoResourceAttr(resourceName, "passphrase"), + }, + }, + { + TFConfig: testsacc.GenerateFromTemplate(resourceName, ` + resource "cloudavenue_org_certificate_library" "example" { + name = {{ generate . "name" }} + description = {{ generate . "description" }} + certificate = chomp(file("/tmp/cert.pem")) + private_key = chomp(file("/tmp/key.pem")) + passphrase = "password" + }`), + Checks: []resource.TestCheckFunc{ + resource.TestCheckResourceAttr(resourceName, "name", testsacc.GetValueFromTemplate(resourceName, "name")), + resource.TestCheckResourceAttr(resourceName, "description", testsacc.GetValueFromTemplate(resourceName, "description")), + resource.TestCheckResourceAttrSet(resourceName, "passphrase"), + }, + }, + }, + // ! Imports testing + Imports: []testsacc.TFImport{ + { + ImportStateIDBuilder: []string{"id"}, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"passphrase", "private_key"}, + }, + { + ImportStateIDBuilder: []string{"name"}, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"passphrase", "private_key"}, + }, + }, + } + }, + } +} + +const ( + orgCertificateLibraryCertFile = "/tmp/cert.pem" + orgCertificateLibraryKeyFile = "/tmp/key.pem" +) + +func orgCertificateLibraryResourcePreCheck() (cleanup func()) { + if err := testcerts.GenerateCertsToFile( + orgCertificateLibraryCertFile, + orgCertificateLibraryKeyFile, + ); err != nil { + panic(err) + } + + return func() { + os.Remove(orgCertificateLibraryCertFile) + os.Remove(orgCertificateLibraryKeyFile) + } +} + +func TestAccORGCertificateLibraryResource(t *testing.T) { + cleanup := orgCertificateLibraryResourcePreCheck() + defer cleanup() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { TestAccPreCheck(t) }, + ProtoV6ProviderFactories: TestAccProtoV6ProviderFactories, + Steps: testsacc.GenerateTests(&ORGCertificateLibraryResource{}), + }) +} diff --git a/templates/data-sources/org_certificate_library.md.tmpl b/templates/data-sources/org_certificate_library.md.tmpl new file mode 100644 index 00000000..179a4b55 --- /dev/null +++ b/templates/data-sources/org_certificate_library.md.tmpl @@ -0,0 +1,18 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "Organization" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +{{ if .HasExample -}} +## Example Usage + +{{ tffile .ExampleFile }} +{{- end }} + +{{ .SchemaMarkdown | trimspace }} diff --git a/templates/resources/org_certificate_library.md.tmpl b/templates/resources/org_certificate_library.md.tmpl new file mode 100644 index 00000000..cec68c1d --- /dev/null +++ b/templates/resources/org_certificate_library.md.tmpl @@ -0,0 +1,25 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "Organization" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +{{ if .HasExample -}} +## Example Usage + +{{ tffile .ExampleFile }} +{{- end }} + +{{ .SchemaMarkdown | trimspace }} + +{{ if .HasImport -}} +## Import + +Import is supported using the following syntax: +{{ codefile "shell" .ImportFile }} +{{- end }} \ No newline at end of file