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

ec_extension: implement extension resource #216

Merged
merged 25 commits into from
Jan 13, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b9a0301
ec_extension: implement extension resource
snowhork Dec 25, 2020
a6bcc37
ec_extension: fix variable code style
snowhork Jan 4, 2021
0238de7
ec_extension: fix typo
snowhork Jan 4, 2021
5e66825
ec_extension: file_hash requires_with file_path
snowhork Jan 4, 2021
87dee54
ec_extension: use GetOk for key check
snowhork Jan 4, 2021
112f437
ec_extension: check hash changed on update for avoiding reupload
snowhork Jan 4, 2021
31a44fb
ec_extension: fix request wrapper to return model
snowhork Jan 4, 2021
73dfb89
ec_extension: fix upload request wrapper to use filePath variable
snowhork Jan 4, 2021
89f1147
ec_extension: fix request error handling and add success test case
snowhork Jan 5, 2021
a55feb8
ec_extension: fix extension_bundle example
snowhork Jan 5, 2021
1aa8c44
ec_extension: add download_url for request payload
snowhork Jan 7, 2021
ecb300f
ec_extension: set empty id when delete succeed
snowhork Jan 7, 2021
cf32ed1
ec_extension: set description for resource
snowhork Jan 7, 2021
dfbcd34
ec_extension: use string pointer util
snowhork Jan 7, 2021
c00675d
ec_extension: add "url", "last_modified", "size" fields
snowhork Jan 7, 2021
b4246f9
ec_extension: acc test: extension_bundle_file
snowhork Jan 9, 2021
c3891ad
ec_extension: acc_test for updating description
snowhork Jan 10, 2021
cd26327
ec_extension: add doc
snowhork Jan 10, 2021
57edd74
ec_extension: set description optional
snowhork Jan 11, 2021
4c5c135
ec_extension: fmt
snowhork Jan 11, 2021
2a3e8a5
ec_extension: fix docs
snowhork Jan 11, 2021
f121138
ec_extension: add bundle_download test
snowhork Jan 11, 2021
d340fa3
ec_extension: change extension type bundle to plugin
snowhork Jan 11, 2021
afb3299
Apply suggestions from code review
snowhork Jan 12, 2021
adbac57
ec_extension: set download_url on read
snowhork Jan 12, 2021
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
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"
snowhork marked this conversation as resolved.
Show resolved Hide resolved
"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
snowhork marked this conversation as resolved.
Show resolved Hide resolved
func createResource(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var client = meta.(*api.API)
snowhork marked this conversation as resolved.
Show resolved Hide resolved

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

d.SetId(*res.Payload.ID)

if d.Get("file_path") != nil {
snowhork marked this conversation as resolved.
Show resolved Hide resolved
_, err = uploadRequest(client, d)
if err != nil {
snowhork marked this conversation as resolved.
Show resolved Hide resolved
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) {
snowhork marked this conversation as resolved.
Show resolved Hide resolved
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"
snowhork marked this conversation as resolved.
Show resolved Hide resolved
"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)
snowhork marked this conversation as resolved.
Show resolved Hide resolved

_, err := deleteRequest(client, d)

if err != nil {
snowhork marked this conversation as resolved.
Show resolved Hide resolved
if alreadyDestroyed(err) {
d.SetId("")
return nil
}

return diag.FromErr(err)
}

snowhork marked this conversation as resolved.
Show resolved Hide resolved
return nil
}

func alreadyDestroyed(err error) bool {
// If the extension is already destroyed, API return 403.
return apierror.IsRuntimeStatusCode(err, 403)
snowhork marked this conversation as resolved.
Show resolved Hide resolved
}
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) {
snowhork marked this conversation as resolved.
Show resolved Hide resolved
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"
snowhork marked this conversation as resolved.
Show resolved Hide resolved
"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)
snowhork marked this conversation as resolved.
Show resolved Hide resolved

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)
snowhork marked this conversation as resolved.
Show resolved Hide resolved
}

func modelToState(d *schema.ResourceData, model *models.Extension) error {
snowhork marked this conversation as resolved.
Show resolved Hide resolved
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