From f4065c96f3d63f5fd0eeb8096e3a4116ca4670f8 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Wed, 3 Jan 2024 13:49:07 -0800 Subject: [PATCH 1/5] Upgrade shared module --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 10af5bc..a7de5a0 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 github.com/hashicorp/terraform-plugin-go v0.20.0 github.com/hashicorp/terraform-plugin-testing v1.6.0 - github.com/jfrog/terraform-provider-shared v1.21.1 + github.com/jfrog/terraform-provider-shared v1.21.3 github.com/samber/lo v1.39.0 ) diff --git a/go.sum b/go.sum index 9c8d001..cf42ea1 100644 --- a/go.sum +++ b/go.sum @@ -127,8 +127,8 @@ github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jfrog/terraform-provider-shared v1.21.1 h1:hBlk7087fjMVk7fdx2BkpZM3RnLIzS6fGNZEJc5HLYc= -github.com/jfrog/terraform-provider-shared v1.21.1/go.mod h1:Ioq1OBLb2h9uj4t4KzBEfA1piHbUg+Lgvn84Vbzk5uI= +github.com/jfrog/terraform-provider-shared v1.21.3 h1:zAE7mWTZ0WUjr7d7dC0WOPNU9xpwuc7mh2RB+T7XNP8= +github.com/jfrog/terraform-provider-shared v1.21.3/go.mod h1:xwhh2ugF0XwEd8wlalqC54ibJBmSlmLLhA5l04gBJsU= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= From e1d0f78e9235773806014e9f272d6d15e6ead68f Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Wed, 3 Jan 2024 13:49:33 -0800 Subject: [PATCH 2/5] Add new 'platform_license' resource --- docs/resources/license.md | 45 ++++ .../resources/platform_license/resource.tf | 8 + pkg/platform/provider.go | 5 +- pkg/platform/resource_license.go | 249 ++++++++++++++++++ pkg/platform/resource_license_test.go | 85 ++++++ pkg/platform/resource_reverse_proxy.go | 1 + 6 files changed, 391 insertions(+), 2 deletions(-) create mode 100644 docs/resources/license.md create mode 100644 examples/resources/platform_license/resource.tf create mode 100644 pkg/platform/resource_license.go create mode 100644 pkg/platform/resource_license_test.go diff --git a/docs/resources/license.md b/docs/resources/license.md new file mode 100644 index 0000000..7b7be89 --- /dev/null +++ b/docs/resources/license.md @@ -0,0 +1,45 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "platform_license Resource - terraform-provider-platform" +subcategory: "" +description: |- + Provides a JFrog license https://jfrog.com/help/r/jfrog-platform-administration-documentation/managing-licenses resource to install/update license. + ~>Only available for self-hosted instances. +--- + +# platform_license (Resource) + +Provides a JFrog [license](https://jfrog.com/help/r/jfrog-platform-administration-documentation/managing-licenses) resource to install/update license. + +~>Only available for self-hosted instances. + +## Example Usage + +```terraform +resource "platform_license" "my-ent-license" { + name = "my-enterprise-license" + key = < +## Schema + +### Required + +- `key` (String) License key. Any newline characters must be represented by escape sequence ` +` + +### Optional + +- `name` (String) Name of the license + +### Read-Only + +- `licensed_to` (String) Customer name the license belongs to. +- `type` (String) Type of the license. +- `valid_through` (String) Date of the license is valid through. diff --git a/examples/resources/platform_license/resource.tf b/examples/resources/platform_license/resource.tf new file mode 100644 index 0000000..1183365 --- /dev/null +++ b/examples/resources/platform_license/resource.tf @@ -0,0 +1,8 @@ +resource "platform_license" "my-ent-license" { + name = "my-enterprise-license" + key = <Only available for self-hosted instances.", + } +} + +type licenseResourceModel struct { + Key types.String `tfsdk:"key"` + Name types.String `tfsdk:"name"` + Type types.String `tfsdk:"type"` + ValidThrough types.String `tfsdk:"valid_through"` + LicensedTo types.String `tfsdk:"licensed_to"` +} + +func (r *licenseResourceModel) fromAPIModel(ctx context.Context, apiModel *licenseAPIGetModel) (ds diag.Diagnostics) { + r.Type = types.StringValue(apiModel.Type) + r.ValidThrough = types.StringValue(apiModel.ValidThrough) + r.LicensedTo = types.StringValue(apiModel.LicensedTo) + + return +} + +type licenseAPIPostRequestModel struct { + Key string `json:"licenseKey"` +} + +type licenseAPIPostResonseModel struct { + Status int `json:"status"` + Messages map[string]string `json:"messages"` +} + +type licenseAPIGetModel struct { + Type string `json:"type"` + ValidThrough string `json:"validThrough"` + LicensedTo string `json:"licensedTo"` +} + +func (r *licenseResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + r.ProviderData = req.ProviderData.(util.ProvderMetadata) +} + +func (r *licenseResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan licenseResourceModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + license := licenseAPIPostRequestModel{ + Key: plan.Key.ValueString(), + } + + var errorResult licenseAPIPostResonseModel + + response, err := r.ProviderData.Client.R(). + SetBody(&license). + SetError(&errorResult). + Post(licensePostEndpoint) + + if err != nil { + if !(response.StatusCode() == http.StatusBadRequest && + errorResult.Messages[license.Key] == "License already exists.") { + messages := lo.Values[string, string](errorResult.Messages) + utilfw.UnableToCreateResourceError(resp, strings.Join(messages, ",")) + return + } + } + + var licenseGet licenseAPIGetModel + + response, err = r.ProviderData.Client.R(). + SetResult(&licenseGet). + Get(licenseGetEndpoint) + + // Treat HTTP 404 Not Found status as a signal to recreate resource + // and return early + if err != nil { + utilfw.UnableToCreateResourceError(resp, response.String()) + return + } + + // Convert from the API data model to the Terraform data model + // and refresh any attribute values. + resp.Diagnostics.Append(plan.fromAPIModel(ctx, &licenseGet)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *licenseResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state licenseResourceModel + + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + var license licenseAPIGetModel + + response, err := r.ProviderData.Client.R(). + SetResult(&license). + Get(licenseGetEndpoint) + + // Treat HTTP 404 Not Found status as a signal to recreate resource + // and return early + if err != nil { + utilfw.UnableToRefreshResourceError(resp, response.String()) + return + } + + // Convert from the API data model to the Terraform data model + // and refresh any attribute values. + resp.Diagnostics.Append(state.fromAPIModel(ctx, &license)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *licenseResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan licenseResourceModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + license := licenseAPIPostRequestModel{ + Key: plan.Key.ValueString(), + } + + var errorResult licenseAPIPostResonseModel + + response, err := r.ProviderData.Client.R(). + SetBody(&license). + SetError(&errorResult). + Post(licensePostEndpoint) + + if err != nil { + if !(response.StatusCode() == http.StatusBadRequest && + errorResult.Messages[license.Key] == "License already exists.") { + messages := lo.Values[string, string](errorResult.Messages) + utilfw.UnableToUpdateResourceError(resp, strings.Join(messages, ",")) + return + } + } + + var licenseGet licenseAPIGetModel + + response, err = r.ProviderData.Client.R(). + SetResult(&licenseGet). + Get(licenseGetEndpoint) + + // Treat HTTP 404 Not Found status as a signal to recreate resource + // and return early + if err != nil { + utilfw.UnableToUpdateResourceError(resp, response.String()) + return + } + + // Convert from the API data model to the Terraform data model + // and refresh any attribute values. + resp.Diagnostics.Append(plan.fromAPIModel(ctx, &licenseGet)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *licenseResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + resp.Diagnostics.AddWarning( + "Unable to Delete Resource", + "License cannot be deleted.", + ) +} diff --git a/pkg/platform/resource_license_test.go b/pkg/platform/resource_license_test.go new file mode 100644 index 0000000..9abc16f --- /dev/null +++ b/pkg/platform/resource_license_test.go @@ -0,0 +1,85 @@ +package platform_test + +import ( + "fmt" + "os" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/jfrog/terraform-provider-shared/testutil" +) + +func readLicense(path string) (string, error) { + data, err := os.ReadFile(path) + if err != nil { + return "", err + } + return strings.TrimSuffix(string(data), "\n"), nil +} + +func TestAccLicense_full(t *testing.T) { + _, fqrn, licenseName := testutil.MkNames("test-license", "platform_license") + + temp := ` + resource "platform_license" "{{ .name }}" { + name = "{{ .name }}" + key = < Date: Wed, 3 Jan 2024 13:50:05 -0800 Subject: [PATCH 3/5] Improve Slack message in Pipeline step Update copyright year in README --- .jfrog-pipelines/pr.yaml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.jfrog-pipelines/pr.yaml b/.jfrog-pipelines/pr.yaml index 949a076..1d97170 100644 --- a/.jfrog-pipelines/pr.yaml +++ b/.jfrog-pipelines/pr.yaml @@ -211,7 +211,7 @@ pipelines: export DESCRIPTION="All tests passed successfully." git clone https://${int_partnership_github_token}@github.com/jfrog/terraform-provider-shared.git ./terraform-provider-shared/scripts/github-status.sh ${res_terraform_provider_platform_gitProvider_token} ${res_terraform_provider_platform_gitRepoFullName} ${res_terraform_provider_platform_commitSha} - send_notification partnership_slack --text "<${res_terraform_provider_platform_gitRepoRepositoryHttpsUrl}|Terraform Provider>. A new PR was submitted by *${PR_COMMITTER}* - <${PR_URL}|${PR_TITLE}>, branch *${PR_BRANCH}*. Changes tested successfully. <@U01H1SLSPA8> or <@UNDRUL1EU> please, review and merge." + send_notification partnership_slack --text "<${res_terraform_provider_platform_gitRepoRepositoryHttpsUrl}|Terraform Provider Platform>. A new PR was submitted by *${PR_COMMITTER}* - <${PR_URL}|${PR_TITLE}>, branch *${PR_BRANCH}*. Changes tested successfully. <@U01H1SLSPA8> or <@UNDRUL1EU> please, review and merge." fi onFailure: - echo "Failure, sending status to GitHub and Slack." diff --git a/README.md b/README.md index 790adcc..f01712f 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ See the [contribution guide](CONTRIBUTIONS.md). ## License -Copyright (c) 2023 JFrog. +Copyright (c) 2024 JFrog. Apache 2.0 licensed, see [LICENSE][LICENSE] file. From 67677cf7d8e527402d4931c08451b3612b9a00fb Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Wed, 3 Jan 2024 14:30:49 -0800 Subject: [PATCH 4/5] Update CHANGELOG --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a127eb2..e215e0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.2.0 (Jan 4, 2023) + +FEATURES: + +* **New Resource:** `platform_license`: PR: [#20](https://github.com/jfrog/terraform-provider-platform/pull/20) Issue: [#12](https://github.com/jfrog/terraform-provider-platform/issues/12) + ## 1.1.0 (Dec 14, 2023). Tested on Artifactory 7.71.10 with Terraform CLI v1.6.6 FEATURES: From 9e3a3ab4be53ce35b3c751700981841173b6a84a Mon Sep 17 00:00:00 2001 From: JFrog CI Date: Wed, 3 Jan 2024 22:44:32 +0000 Subject: [PATCH 5/5] JFrog Pipelines - Add Artifactory version to CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e215e0c..5470ecc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.2.0 (Jan 4, 2023) +## 1.2.0 (Jan 4, 2023). Tested on Artifactory 7.71.11 with Terraform CLI v1.6.6 FEATURES: