Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't force resource replacement when expiration is unset during SDK-PF migration #875

Merged
merged 2 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
## [Unreleased]

- Allow `elasticstack_kibana_alerting_rule` to be used without Elasticsearch being configured. ([#869](https://github.com/elastic/terraform-provider-elasticstack/pull/869))
- Add resource `elasticstack_elasticsearch_data_stream_lifecycle` ([838](https://github.com/elastic/terraform-provider-elasticstack/issues/838))
- Add resource `elasticstack_elasticsearch_data_stream_lifecycle` ([#838](https://github.com/elastic/terraform-provider-elasticstack/issues/838))
- Ensure API keys are not replaced when upgrading from 0.11.9 or earlier. ([#875](https://github.com/elastic/terraform-provider-elasticstack/pull/875))

## [0.11.10] - 2024-10-23

Expand Down
2 changes: 1 addition & 1 deletion internal/clients/elasticsearch/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ func UpdateApiKey(apiClient *clients.ApiClient, apikey models.ApiKey) fwdiag.Dia
return utils.FrameworkDiagFromError(err)
}
defer res.Body.Close()
if diags := utils.CheckError(res, "Unable to create apikey"); diags.HasError() {
if diags := utils.CheckError(res, "Unable to update apikey"); diags.HasError() {
return utils.FrameworkDiagsFromSDK(diags)
}

Expand Down
77 changes: 77 additions & 0 deletions internal/elasticsearch/security/api_key/acc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,60 @@ func SkipWhenApiKeysAreNotSupportedOrRestrictionsAreSupported(minApiKeySupported
}
}

func TestAccResourceSecurityApiKeyFromSDK(t *testing.T) {
// generate a random name
apiKeyName := sdkacctest.RandStringFromCharSet(10, sdkacctest.CharSetAlphaNum)
var initialApiKey string

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
CheckDestroy: checkResourceSecurityApiKeyDestroy,
Steps: []resource.TestStep{
{
// Create the api_key with the last provider version where the api_key resource was built on the SDK
ExternalProviders: map[string]resource.ExternalProvider{
"elasticstack": {
Source: "elastic/elasticstack",
VersionConstraint: "0.11.9",
},
},
ProtoV6ProviderFactories: acctest.Providers,
SkipFunc: versionutils.CheckIfVersionIsUnsupported(api_key.MinVersion),
Config: testAccResourceSecurityApiKeyWithoutExpiration(apiKeyName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_security_api_key.test", "name", apiKeyName),
resource.TestCheckResourceAttrSet("elasticstack_elasticsearch_security_api_key.test", "role_descriptors"),
resource.TestCheckResourceAttrSet("elasticstack_elasticsearch_security_api_key.test", "encoded"),
resource.TestCheckResourceAttrSet("elasticstack_elasticsearch_security_api_key.test", "id"),
resource.TestCheckResourceAttrWith("elasticstack_elasticsearch_security_api_key.test", "api_key", func(value string) error {
initialApiKey = value

if value == "" {
return fmt.Errorf("expected api_key to be non-empty")
}

return nil
}),
),
},
{
ProtoV6ProviderFactories: acctest.Providers,
SkipFunc: versionutils.CheckIfVersionIsUnsupported(api_key.MinVersion),
Config: testAccResourceSecurityApiKeyWithoutExpiration(apiKeyName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrWith("elasticstack_elasticsearch_security_api_key.test", "api_key", func(value string) error {
if value != initialApiKey {
return fmt.Errorf("expected api_key to be unchanged")
}

return nil
}),
),
},
},
})
}

func testAccResourceSecurityApiKeyCreate(apiKeyName string) string {
return fmt.Sprintf(`
provider "elasticstack" {
Expand Down Expand Up @@ -291,6 +345,29 @@ resource "elasticstack_elasticsearch_security_api_key" "test" {
`, apiKeyName)
}

func testAccResourceSecurityApiKeyWithoutExpiration(apiKeyName string) string {
return fmt.Sprintf(`
provider "elasticstack" {
elasticsearch {}
}

resource "elasticstack_elasticsearch_security_api_key" "test" {
name = "%s"

role_descriptors = jsonencode({
role-a = {
cluster = ["all"]
indices = [{
names = ["index-a*"]
privileges = ["read"]
allow_restricted_indices = false
}]
}
})
}
`, apiKeyName)
}

func testAccResourceSecurityApiKeyRemoteIndices(apiKeyName string) string {
return fmt.Sprintf(`
provider "elasticstack" {
Expand Down
1 change: 1 addition & 0 deletions internal/elasticsearch/security/api_key/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
// Ensure provider defined types fully satisfy framework interfaces
var _ resource.Resource = &Resource{}
var _ resource.ResourceWithConfigure = &Resource{}
var _ resource.ResourceWithUpgradeState = &Resource{}
var (
MinVersion = version.Must(version.NewVersion("8.0.0")) // Enabled in 8.0
MinVersionWithUpdate = version.Must(version.NewVersion("8.4.0"))
Expand Down
7 changes: 5 additions & 2 deletions internal/elasticsearch/security/api_key/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ import (
providerschema "github.com/elastic/terraform-provider-elasticstack/internal/schema"
)

const currentSchemaVersion int64 = 1

func (r *Resource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = r.getSchema()
resp.Schema = r.getSchema(currentSchemaVersion)
}

func (r *Resource) getSchema() schema.Schema {
func (r *Resource) getSchema(version int64) schema.Schema {
return schema.Schema{
Version: version,
Description: "Creates an API key for access without requiring basic authentication. See, https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html",
Blocks: map[string]schema.Block{
"elasticsearch_connection": providerschema.GetEsFWConnectionBlock("elasticsearch_connection", false),
Expand Down
30 changes: 30 additions & 0 deletions internal/elasticsearch/security/api_key/state_upgrade.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package api_key

import (
"context"

"github.com/elastic/terraform-provider-elasticstack/internal/utils"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
)

func (r *Resource) UpgradeState(context.Context) map[int64]resource.StateUpgrader {
return map[int64]resource.StateUpgrader{
0: {
PriorSchema: utils.Pointer(r.getSchema(0)),
StateUpgrader: func(ctx context.Context, req resource.UpgradeStateRequest, resp *resource.UpgradeStateResponse) {
var model tfModel
resp.Diagnostics.Append(req.State.Get(ctx, &model)...)
if resp.Diagnostics.HasError() {
return
}

if utils.IsKnown(model.Expiration) && model.Expiration.ValueString() == "" {
model.Expiration = basetypes.NewStringNull()
}

resp.State.Set(ctx, model)
},
},
}
}
Loading