Skip to content

Commit

Permalink
WIP: ec_deployment resource
Browse files Browse the repository at this point in the history
  • Loading branch information
dimuon committed Sep 7, 2022
1 parent cf373db commit 566bce8
Show file tree
Hide file tree
Showing 11 changed files with 721 additions and 18 deletions.
3 changes: 1 addition & 2 deletions ec/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"github.com/elastic/terraform-provider-ec/ec/ecdatasource/deploymentdatasource"
"github.com/elastic/terraform-provider-ec/ec/ecdatasource/deploymentsdatasource"
"github.com/elastic/terraform-provider-ec/ec/ecdatasource/stackdatasource"
"github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource"
"github.com/elastic/terraform-provider-ec/ec/ecresource/elasticsearchkeystoreresource"
"github.com/elastic/terraform-provider-ec/ec/ecresource/extensionresource"
"github.com/elastic/terraform-provider-ec/ec/ecresource/trafficfilterassocresource"
Expand Down Expand Up @@ -70,7 +69,7 @@ func Provider() *schema.Provider {
"ec_stack": stackdatasource.DataSource(),
},
ResourcesMap: map[string]*schema.Resource{
"ec_deployment": deploymentresource.Resource(),
// "ec_deployment": deploymentresource.Resource(),
"ec_deployment_elasticsearch_keystore": elasticsearchkeystoreresource.Resource(),
"ec_deployment_traffic_filter": trafficfilterresource.Resource(),
"ec_deployment_traffic_filter_association": trafficfilterassocresource.Resource(),
Expand Down
2 changes: 1 addition & 1 deletion ec/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@
package ec

// Version contains the current terraform provider version.
const Version = "0.4.0-dev"
const Version = "0.5.0-dev"
260 changes: 260 additions & 0 deletions ectpf/deployment_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package ectpf

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/diag"
tpfprovider "github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"

"github.com/elastic/terraform-provider-ec/ectpf/ecresource/deploymentresource"
)

// Ensure provider defined types fully satisfy framework interfaces
var _ tpfprovider.ResourceType = deploymentResourceType{}
var _ resource.Resource = deploymentResource{}

// var _ resource.ResourceWithImportState = deploymentResource{}

type deploymentResourceType struct{}

func (t deploymentResourceType) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) {
return tfsdk.Schema{
// This description is used by the documentation generator and the language server.
MarkdownDescription: "Elastic Cloud Deployment resource",

Attributes: map[string]tfsdk.Attribute{
"version": {
Type: types.StringType,
Description: "Required Elastic Stack version to use for all of the deployment resources",
Required: true,
},
"region": {
Type: types.StringType,
Description: `Required ESS region where to create the deployment, for ECE environments "ece-region" must be set`,
Required: true,
},
"deployment_template_id": {
Type: types.StringType,
Description: "Required Deployment Template identifier to create the deployment from",
Required: true,
},
"name": {
Type: types.StringType,
Description: "Optional name for the deployment",
Optional: true,
},
},

Blocks: map[string]tfsdk.Block{
"elasticsearch": {
NestingMode: tfsdk.BlockNestingModeList,
MaxItems: 1,
Attributes: map[string]tfsdk.Attribute{
"autoscale": {
Type: types.StringType,
Description: `Enable or disable autoscaling. Defaults to the setting coming from the deployment template. Accepted values are "true" or "false".`,
Computed: true,
Optional: true,
// ValidateFunc: func(i interface{}, s string) ([]string, []error) {
// if _, err := strconv.ParseBool(i.(string)); err != nil {
// return nil, []error{
// fmt.Errorf("failed parsing autoscale value: %w", err),
// }
// }
// return nil, nil
// },
},

"resource_id": {
Type: types.StringType,
Description: "The Elasticsearch resource unique identifier",
Computed: true,
},
"region": {
Type: types.StringType,
Description: "The Elasticsearch resource region",
Computed: true,
},
"https_endpoint": {
Type: types.StringType,
Description: "The Elasticsearch resource HTTPs endpoint",
Computed: true,
},
},

Blocks: map[string]tfsdk.Block{
"topology": {
NestingMode: tfsdk.BlockNestingModeList,
MinItems: 0,
Attributes: map[string]tfsdk.Attribute{
"id": {
Type: types.StringType,
Description: `Required topology ID from the deployment template`,
Required: true,
},
},
},
},

Description: "Required Elasticsearch resource definition",
},
},
}, nil
}

func (t deploymentResourceType) NewResource(ctx context.Context, in tpfprovider.Provider) (resource.Resource, diag.Diagnostics) {
provider, diags := convertProviderType(in)

return deploymentResource{
provider: provider,
}, diags
}

type deploymentResource struct {
provider scaffoldingProvider
}

func (r deploymentResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
if !r.provider.configured {
resp.Diagnostics.AddError(
"Provider not configured",
"The provider hasn't been configured before apply, likely because it depends on an unknown value from another resource. This leads to weird stuff happening, so we'd prefer if you didn't do that. Thanks!",
)
return
}

var cfg deploymentresource.DeploymentData
diags := req.Config.Get(ctx, &cfg)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

var plan deploymentresource.DeploymentData
diags = req.Plan.Get(ctx, &plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

deploymentResource, errors := deploymentresource.Create(ctx, r.provider.client, &cfg, &plan)

if len(errors) > 0 {
for _, err := range errors {
resp.Diagnostics.AddError(
"Cannot create deployment resource",
err.Error(),
)
}
return
}

// If applicable, this is a great opportunity to initialize any necessary
// provider client data and make a call using it.
// example, err := d.provider.client.CreateExample(...)
// if err != nil {
// resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create example, got error: %s", err))
// return
// }

// For the purposes of this example code, hardcoding a response value to
// save into the Terraform state.
// data.Id = types.String{Value: "example-id"}

// write logs using the tflog package
// see https://pkg.go.dev/github.com/hashicorp/terraform-plugin-log/tflog
// for more information
tflog.Trace(ctx, "created a resource")

diags = resp.State.Set(ctx, &deploymentResource)
resp.Diagnostics.Append(diags...)
}

func (r deploymentResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var state deploymentresource.DeploymentData

diags := req.State.Get(ctx, &state)
resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

// If applicable, this is a great opportunity to initialize any necessary
// provider client data and make a call using it.
// example, err := d.provider.client.ReadExample(...)
// if err != nil {
// resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read example, got error: %s", err))
// return
// }
// r.provider.client

diags = resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)
}

func (r deploymentResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data deploymentresource.DeploymentData

diags := req.Plan.Get(ctx, &data)
resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

// If applicable, this is a great opportunity to initialize any necessary
// provider client data and make a call using it.
// example, err := d.provider.client.UpdateExample(...)
// if err != nil {
// resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update example, got error: %s", err))
// return
// }

diags = resp.State.Set(ctx, &data)
resp.Diagnostics.Append(diags...)
}

func (r deploymentResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data deploymentresource.DeploymentData

diags := req.State.Get(ctx, &data)
resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

// If applicable, this is a great opportunity to initialize any necessary
// provider client data and make a call using it.
// example, err := d.provider.client.DeleteExample(...)
// if err != nil {
// resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete example, got error: %s", err))
// return
// }
}

// func (r deploymentResource) ImportState(ctx context.Context, req tfsdk.ImportResourceStateRequest, resp *tfsdk.ImportResourceStateResponse) {
// tfsdk.ResourceImportStatePassthroughID(ctx, tftypes.NewAttributePath().WithAttributeName("id"), req, resp)
// }
80 changes: 80 additions & 0 deletions ectpf/ecresource/deploymentresource/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package deploymentresource

import (
"context"
"fmt"

"github.com/elastic/cloud-sdk-go/pkg/api"
)

// CreateResource will createResource a new deployment from the specified settings.
func Create(ctx context.Context, client *api.API, cfg, plan *DeploymentData) (resp *DeploymentData, errors []error) {
// reqID := deploymentapi.RequestID("")

// req, err := createResourceToModel(client, cfg, plan)
// if err != nil {
// return nil, []error{err}
// }

// res, err := deploymentapi.Create(deploymentapi.CreateParams{
// API: client,
// RequestID: reqID,
// Request: req,
// Overrides: &deploymentapi.PayloadOverrides{
// Name: plan.Name.Value,
// Version: plan.Version.Value,
// Region: plan.Region.Value,
// },
// })

// if err != nil {
// merr := multierror.NewPrefixed("failed creating deployment", err)
// return nil, []error{merr.Append(newCreationError(reqID))}
// }

// if err := WaitForPlanCompletion(client, *res.ID); err != nil {
// merr := multierror.NewPrefixed("failed tracking create progress", err)
// return nil, []error{merr.Append(newCreationError(reqID))}
// }

// d.SetId(*res.ID)

// if err := handleRemoteClusters(d, client); err != nil {
// errors = append(errors, err)
// }

/* if errs := readResource(ctx, d, meta); errs != nil {
errors = append(errors, errs...)
}
if err := parseCredentials(d, res.Resources); err != nil {
errors = append(errors, err)
}
return errors
*/
return nil, nil
}

func newCreationError(reqID string) error {
return fmt.Errorf(
`set "request_id" to "%s" to recreate the deployment resources`, reqID,
)
}
Loading

0 comments on commit 566bce8

Please sign in to comment.