Skip to content

Commit

Permalink
ec_extension: implement extension resource
Browse files Browse the repository at this point in the history
implement ec_extension resource and make example

Closes elastic#102
  • Loading branch information
snowhork committed Dec 25, 2020
1 parent d16ca16 commit b9a0301
Show file tree
Hide file tree
Showing 18 changed files with 928 additions and 0 deletions.
46 changes: 46 additions & 0 deletions ec/ecresource/extensionresource/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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 extensionresource

import (
"context"
"github.com/elastic/cloud-sdk-go/pkg/api"
"github.com/elastic/cloud-sdk-go/pkg/multierror"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// Create will createResource a new deployment traffic filter ruleset
func createResource(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var client = meta.(*api.API)

res, err := createRequest(client, d)
if err != nil {
return diag.FromErr(err)
}

d.SetId(*res.Payload.ID)

if d.Get("file_path") != nil {
_, err = uploadRequest(client, d)
if err != nil {
return diag.FromErr(multierror.NewPrefixed("failed to upload file", err))
}
}
return readResource(ctx, d, meta)
}
92 changes: 92 additions & 0 deletions ec/ecresource/extensionresource/create_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// 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 extensionresource

import (
"context"
"testing"

"github.com/elastic/cloud-sdk-go/pkg/api"
"github.com/elastic/cloud-sdk-go/pkg/api/mock"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/stretchr/testify/assert"

"github.com/elastic/terraform-provider-ec/ec/internal/util"
)

func Test_createResource(t *testing.T) {
tc500Err := util.NewResourceData(t, util.ResDataParams{
ID: "12345678",
State: newExtension(),
Schema: newSchema(),
})
wantTC500 := util.NewResourceData(t, util.ResDataParams{
ID: "12345678",
State: newExtension(),
Schema: newSchema(),
})

type args struct {
ctx context.Context
d *schema.ResourceData
meta interface{}
}
tests := []struct {
name string
args args
want diag.Diagnostics
wantRD *schema.ResourceData
}{
{
name: "returns an error when it receives a 500",
args: args{
d: tc500Err,
meta: api.NewMock(mock.NewErrorResponse(500, mock.APIError{
Code: "some", Message: "message",
})),
},
want: diag.Diagnostics{
{
Severity: diag.Error,
Summary: "api error: 1 error occurred:\n\t* some: message\n\n",
},
},
wantRD: wantTC500,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := createResource(tt.args.ctx, tt.args.d, tt.args.meta)
assert.Equal(t, tt.want, got)
var want interface{}
if tt.wantRD != nil {
if s := tt.wantRD.State(); s != nil {
want = s.Attributes
}
}

var gotState interface{}
if s := tt.args.d.State(); s != nil {
gotState = s.Attributes
}

assert.Equal(t, want, gotState)
})
}
}
48 changes: 48 additions & 0 deletions ec/ecresource/extensionresource/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// 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 extensionresource

import (
"context"
"github.com/elastic/cloud-sdk-go/pkg/api"
"github.com/elastic/cloud-sdk-go/pkg/api/apierror"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func deleteResource(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var client = meta.(*api.API)

_, err := deleteRequest(client, d)

if err != nil {
if alreadyDestroyed(err) {
d.SetId("")
return nil
}

return diag.FromErr(err)
}

return nil
}

func alreadyDestroyed(err error) bool {
// If the extension is already destroyed, API return 403.
return apierror.IsRuntimeStatusCode(err, 403)
}
115 changes: 115 additions & 0 deletions ec/ecresource/extensionresource/delete_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// 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 extensionresource

import (
"context"
"testing"

"github.com/elastic/cloud-sdk-go/pkg/api"
"github.com/elastic/cloud-sdk-go/pkg/api/mock"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/stretchr/testify/assert"

"github.com/elastic/terraform-provider-ec/ec/internal/util"
)

func Test_deleteResource(t *testing.T) {
tc500Err := util.NewResourceData(t, util.ResDataParams{
ID: "12345678",
State: newExtension(),
Schema: newSchema(),
})
wantTC500 := util.NewResourceData(t, util.ResDataParams{
ID: "12345678",
State: newExtension(),
Schema: newSchema(),
})

tc403Err := util.NewResourceData(t, util.ResDataParams{
ID: "12345678",
State: newExtension(),
Schema: newSchema(),
})
wantTC403 := util.NewResourceData(t, util.ResDataParams{
ID: "12345678",
State: newExtension(),
Schema: newSchema(),
})
wantTC403.SetId("")

type args struct {
ctx context.Context
d *schema.ResourceData
meta interface{}
}
tests := []struct {
name string
args args
want diag.Diagnostics
wantRD *schema.ResourceData
}{
{
name: "returns an error when it receives a 500",
args: args{
d: tc500Err,
meta: api.NewMock(mock.NewErrorResponse(500, mock.APIError{
Code: "some", Message: "message",
})),
},
want: diag.Diagnostics{
{
Severity: diag.Error,
Summary: "api error: 1 error occurred:\n\t* some: message\n\n",
},
},
wantRD: wantTC500,
},
{
name: "returns nil and unsets the state when the error is known",
args: args{
d: tc403Err,
meta: api.NewMock(mock.NewErrorResponse(403, mock.APIError{
Code: "some", Message: "message",
})),
},
want: nil,
wantRD: wantTC403,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := deleteResource(tt.args.ctx, tt.args.d, tt.args.meta)
assert.Equal(t, tt.want, got)
var want interface{}
if tt.wantRD != nil {
if s := tt.wantRD.State(); s != nil {
want = s.Attributes
}
}

var gotState interface{}
if s := tt.args.d.State(); s != nil {
gotState = s.Attributes
}

assert.Equal(t, want, gotState)
})
}
}
83 changes: 83 additions & 0 deletions ec/ecresource/extensionresource/read.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// 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 extensionresource

import (
"context"
"errors"
"github.com/elastic/cloud-sdk-go/pkg/api"
"github.com/elastic/cloud-sdk-go/pkg/api/apierror"
"github.com/elastic/cloud-sdk-go/pkg/client/extensions"
"github.com/elastic/cloud-sdk-go/pkg/models"
"github.com/elastic/cloud-sdk-go/pkg/multierror"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func readResource(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var client = meta.(*api.API)

res, err := readRequest(d, client)

if err != nil {
if extensionNotFound(err) {
d.SetId("")
return nil
}

return diag.FromErr(multierror.NewPrefixed("failed reading extension", err))
}

if err := modelToState(d, res.Payload); err != nil {
return diag.FromErr(err)
}

return nil
}

func extensionNotFound(err error) bool {
// We're using the As() call since we do not care about the error value
// but do care about the error's contents type since it's an implicit 404.
var extensionNotFound *extensions.GetExtensionNotFound
if errors.As(err, &extensionNotFound) {
return true
}

// We also check for the case where a 403 is thrown for ESS.
return apierror.IsRuntimeStatusCode(err, 403)
}

func modelToState(d *schema.ResourceData, model *models.Extension) error {
if err := d.Set("name", model.Name); err != nil {
return err
}

if err := d.Set("version", model.Version); err != nil {
return err
}

if err := d.Set("extension_type", model.ExtensionType); err != nil {
return err
}

if err := d.Set("description", model.Description); err != nil {
return err
}

return nil
}
Loading

0 comments on commit b9a0301

Please sign in to comment.