Skip to content

Commit

Permalink
Persist snapshot source in the read response (#788)
Browse files Browse the repository at this point in the history
* Persist snapshot source in the read response

* Unit tests

* Changelog
  • Loading branch information
tobio authored Mar 11, 2024
1 parent 8c29ee8 commit cc5eba7
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .changelog/788.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
resource/deployment: Persist the snapshot source settings during reads. This fixes a [provider crash](https://github.com/elastic/terraform-provider-ec/issues/787) when creating a deployment from a snapshot.
```
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ import (
"context"
"errors"
"fmt"
"github.com/elastic/cloud-sdk-go/pkg/client/deployments"
"slices"
"strings"

"github.com/elastic/cloud-sdk-go/pkg/client/deployments"

"github.com/blang/semver"
"github.com/elastic/cloud-sdk-go/pkg/models"
"github.com/elastic/cloud-sdk-go/pkg/util/ec"

apmv2 "github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource/apm/v2"
elasticsearchv1 "github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource/elasticsearch/v1"
elasticsearchv2 "github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource/elasticsearch/v2"
enterprisesearchv2 "github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource/enterprisesearch/v2"
integrationsserverv2 "github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource/integrationsserver/v2"
Expand All @@ -39,6 +41,7 @@ import (
"github.com/elastic/terraform-provider-ec/ec/internal/converters"
"github.com/elastic/terraform-provider-ec/ec/internal/util"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
)

Expand All @@ -65,6 +68,28 @@ type Deployment struct {
MigrateToLatestHardware *bool `tfsdk:"migrate_to_latest_hardware"`
}

func (dep *Deployment) PersistSnapshotSource(ctx context.Context, esPlan *elasticsearchv2.ElasticsearchTF) diag.Diagnostics {
if dep == nil || dep.Elasticsearch == nil {
return nil
}

if esPlan == nil || esPlan.SnapshotSource.IsNull() || esPlan.SnapshotSource.IsUnknown() {
return nil
}

var snapshotSource *elasticsearchv1.ElasticsearchSnapshotSourceTF
if diags := tfsdk.ValueAs(ctx, esPlan.SnapshotSource, &snapshotSource); diags.HasError() {
return diags
}

dep.Elasticsearch.SnapshotSource = &elasticsearchv2.ElasticsearchSnapshotSource{
SourceElasticsearchClusterId: snapshotSource.SourceElasticsearchClusterId.ValueString(),
SnapshotName: snapshotSource.SnapshotName.ValueString(),
}

return nil
}

// Nullify Elasticsearch topologies that have zero size and are not specified in plan
func (dep *Deployment) NullifyUnusedEsTopologies(ctx context.Context, esPlan *elasticsearchv2.ElasticsearchTF) {
if dep.Elasticsearch == nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,23 @@
package v2

import (
"context"
"errors"
"testing"

"github.com/elastic/cloud-sdk-go/pkg/api/mock"
"github.com/elastic/cloud-sdk-go/pkg/models"
"github.com/elastic/cloud-sdk-go/pkg/util/ec"
apmv2 "github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource/apm/v2"
elasticsearchv1 "github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource/elasticsearch/v1"
elasticsearchv2 "github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource/elasticsearch/v2"
enterprisesearchv2 "github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource/enterprisesearch/v2"
kibanav2 "github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource/kibana/v2"
observabilityv2 "github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource/observability/v2"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func Test_readDeployment(t *testing.T) {
Expand Down Expand Up @@ -1723,3 +1728,59 @@ func Test_getDeploymentTemplateID(t *testing.T) {
})
}
}

func Test_PersistSnapshotSource(t *testing.T) {
tests := []struct {
name string
deployment *Deployment
snapshotSource *elasticsearchv1.ElasticsearchSnapshotSource
expectedSourceElasticsearchClusterId string
expectedSnapshotName string
}{
{
name: "should noop if deployment is nil",
},
{
name: "should noop if the esplan snapshot source is null",
deployment: &Deployment{},
},
{
name: "should set the snapshot source cluster and snapshot name if specified in the plan",
deployment: &Deployment{
Elasticsearch: &elasticsearchv2.Elasticsearch{},
},
snapshotSource: &elasticsearchv1.ElasticsearchSnapshotSource{
SourceElasticsearchClusterId: "source-cluster-id",
SnapshotName: "snapshot-name",
},
expectedSourceElasticsearchClusterId: "source-cluster-id",
expectedSnapshotName: "snapshot-name",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var obj types.Object
if tt.snapshotSource != nil {
diags := tfsdk.ValueFrom(context.Background(), tt.snapshotSource, elasticsearchv2.ElasticsearchSnapshotSourceSchema().GetType(), &obj)
require.Nil(t, diags)
}

esPlan := elasticsearchv2.ElasticsearchTF{
SnapshotSource: obj,
}

diags := tt.deployment.PersistSnapshotSource(context.Background(), &esPlan)
require.Nil(t, diags)

var snapshotName, sourceESClusterID string
if tt.deployment != nil && tt.deployment.Elasticsearch != nil && tt.deployment.Elasticsearch.SnapshotSource != nil {
snapshotName = tt.deployment.Elasticsearch.SnapshotSource.SnapshotName
sourceESClusterID = tt.deployment.Elasticsearch.SnapshotSource.SourceElasticsearchClusterId
}

require.Equal(t, tt.expectedSnapshotName, snapshotName)
require.Equal(t, tt.expectedSourceElasticsearchClusterId, sourceESClusterID)
})
}
}
4 changes: 2 additions & 2 deletions ec/ecresource/deploymentresource/elasticsearch/v2/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func ElasticsearchSchema() schema.Attribute {

"snapshot": elasticsearchSnapshotSchema(),

"snapshot_source": elasticsearchSnapshotSourceSchema(),
"snapshot_source": ElasticsearchSnapshotSourceSchema(),

"extension": elasticsearchExtensionSchema(),

Expand Down Expand Up @@ -361,7 +361,7 @@ func elasticsearchSnapshotRepositoryReferenceSchema() schema.Attribute {
}
}

func elasticsearchSnapshotSourceSchema() schema.Attribute {
func ElasticsearchSnapshotSourceSchema() schema.Attribute {
return schema.SingleNestedAttribute{
Description: `Restores data from a snapshot of another deployment.
Expand Down
1 change: 1 addition & 0 deletions ec/ecresource/deploymentresource/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ func (r *Resource) read(ctx context.Context, id string, state *deploymentv2.Depl
deployment.ProcessSelfInObservability()

deployment.NullifyUnusedEsTopologies(ctx, baseElasticsearch)
diags.Append(deployment.PersistSnapshotSource(ctx, baseElasticsearch)...)

if !deployment.HasNodeTypes() {
// The MigrateDeploymentTemplate request can only be performed for deployments that use node roles.
Expand Down

0 comments on commit cc5eba7

Please sign in to comment.