diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8dc8402..de962c2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,20 +29,19 @@ jobs: go-version: [1.18.x] os: [ubuntu-latest] os-major-version: - - "1-opensearch" + - "2-opensearch" include: - - os-major-version: "1-opensearch" - version: 1.1.0 + - os-major-version: "2-opensearch" + version: 2 oss-image: "opensearchproject/opensearch" - OS_OPENDISTRO_IMAGE: "opensearchproject/opensearch:1.1.0" - OS_DASHBOARD_IMAGE: "opensearchproject/opensearch-dashboards:1.1.0" + OS_IMAGE: "opensearchproject/opensearch:2" + OS_DASHBOARD_IMAGE: "opensearchproject/opensearch-dashboards:2" OPENSEARCH_PREFIX: "plugins.security" - OSS_ENV_VAR: "plugins.security.disabled=true" needs: [lint] name: Test against OS ${{ matrix.os-major-version }} on ${{ matrix.go-version }}/${{ matrix.os }} runs-on: ${{ matrix.os }} env: - OS_OPENDISTRO_IMAGE: "${{matrix.OS_OPENDISTRO_IMAGE}}" + OS_IMAGE: "${{matrix.OS_IMAGE}}" OS_DASHBOARD_IMAGE: "${{matrix.OS_DASHBOARD_IMAGE}}" OPENSEARCH_PREFIX: "${{matrix.OPENSEARCH_PREFIX}}" OSS_ENV_VAR: "${{matrix.OSS_ENV_VAR}}" @@ -92,21 +91,13 @@ jobs: - name: Wait for Opensearch # ensure that OS has come up and is available run: | - ./script/wait-for-endpoint --timeout=20 http://localhost:9200 - - name: Warm up OpenDistro/Opensearch - # - OpenDistro lazily initializes its indexes, see - # https://github.com/opendistro-for-elasticsearch/alerting/issues/60 - run: | - if [ -n "$OS_OPENDISTRO_IMAGE" ]; then - ./script/wait-for-endpoint --timeout=120 http://admin:admin@localhost:9220 - curl -s -v -X POST -H 'Content-type: application/json' -d '{"name":"_warmup","type":"slack","slack":{"url": "http://www.example.com"}}' http://admin:admin@localhost:9220/_opendistro/_alerting/destinations - fi + ./script/wait-for-endpoint --timeout=20 http://admin:admin@localhost:9200 - name: Dump docker logs on failure if: failure() uses: jwalton/gh-docker-logs@v2 - name: Run the tests run: | - export OPENSEARCH_URL=http://localhost:9200 + export OPENSEARCH_URL=http://admin:admin@localhost:9200 export TF_LOG=INFO TF_ACC=1 go test ./... -v -parallel 20 -cover -short # check goreleaser config for deprecations diff --git a/README.md b/README.md index 5a5b9cf..fc57351 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,76 @@ This provider will target compatibility with major versions of Opensearch, each | Opensearch version | Supported | | ----------- | --------- | -| 1.x | :white_check_mark: | -| 2.x | :x: | +| 2.x | :white_check_mark: | +### Supported Functionalities + +Examples of resources can be found in the examples directory. + +#### OpenSearch and OpenSearch Dashboards + +- [x] [Cluster Settings](https://opensearch.org/docs/latest/api-reference/cluster-api/cluster-settings/) +- [x] [Audit Config](https://opensearch.org/docs/latest/security/audit-logs/index/) +- [x] [Component templates](https://opensearch.org/docs/latest/dashboards/im-dashboards/component-templates/) +- [x] [Index and Composable templates](https://opensearch.org/docs/latest/im-plugin/index-templates/) +- [x] [Data Streams](https://opensearch.org/docs/2.9/dashboards/im-dashboards/datastream/) +- [x] [Ingest Pipeline](https://opensearch.org/docs/2.9/api-reference/ingest-apis/create-update-ingest/) +- [x] [Security](https://opensearch.org/docs/latest/security/index/) +- [x] [Snapshot Repository](https://opensearch.org/docs/2.9/tuning-your-cluster/availability-and-recovery/snapshots/snapshot-restore/#register-repository) +- [x] [Anomaly Detection](https://opensearch.org/docs/latest/observing-your-data/ad/index/) +- [x] [Index State Management](https://opensearch.org/docs/latest/im-plugin/ism/index/) +- [x] [Dashboards Visualization](https://opensearch.org/docs/latest/dashboards/visualize/viz-index/) +- [x] [Dashboards Tenant](https://opensearch.org/docs/latest/security/multi-tenancy/tenant-index/) +- [x] [Alerting Monitors](https://opensearch.org/docs/latest/observing-your-data/alerting/monitors/) + + +### Running tests locally + +```sh +./script/install-tools +export OSS_IMAGE="opensearchproject/opensearch:2" +docker-compose up -d +docker-compose ps -a +export OPENSEARCH_URL=http://admin:admin@localhost:9200 +export TF_LOG=INFO +TF_ACC=1 go test ./... -v -parallel 20 -cover -short +``` + +#### To Run Specific Test +```sh +cd provider/ +TF_ACC=2 go test -run TestAccOpensearchOpenDistroDashboardTenant -v -cover -short +``` + +#### Fix the go-lint errors + +```sh +golangci-lint run --out-format=github-actions +``` + + +### Debugging this provider + +Build the executable, and start in debug mode: + +```console +$ go build +$ ./terraform-provider-opensearch -debuggable # or start in debug mode in your IDE +{"@level":"debug","@message":"plugin address","@timestamp":"2022-05-17T10:10:04.331668+01:00","address":"/var/folders/32/3mbbgs9x0r5bf991ltrl3p280010fs/T/plugin1346340234","network":"unix"} +Provider started, to attach Terraform set the TF_REATTACH_PROVIDERS env var: + + TF_REATTACH_PROVIDERS='{"registry.terraform.io/opensearch-project/opensearch":{"Protocol":"grpc","ProtocolVersion":5,"Pid":79075,"Test":true,"Addr":{"Network":"unix","String":"/var/folders/32/3mbbgs9x0r5bf991ltrl3p280010fs/T/plugin1346340234"}}}' +``` + +In another terminal, you can test your terraform code: + +```console +$ cd +$ export TF_REATTACH_PROVIDERS= +$ terraform apply +``` + +The local provider will be used instead, and you should see debug information printed to the terminal. ## Version and Branching As of now, this terraform-provider-opensearch repository maintains 2 branches: diff --git a/docker-compose.yml b/docker-compose.yml index 22ab8c0..1b58279 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: opensearch: - image: ${OSS_IMAGE} + image: ${OSS_IMAGE} hostname: opensearch container_name: opensearch networks: @@ -15,6 +15,7 @@ services: - network.publish_host=127.0.0.1 - logger.org.opensearch=warn - "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g" + - "plugins.security.ssl.http.enabled=false" - ${OSS_ENV_VAR:-FOO=bar} command: ${OS_COMMAND} ulimits: @@ -27,30 +28,6 @@ services: hard: -1 ports: - 9200:9200 - opendistro: - image: ${OS_OPENDISTRO_IMAGE:-rwgrim/docker-noop} - hostname: opensearch-opendistro - container_name: opensearch-opendistro - environment: - - cluster.name=opendistro - - bootstrap.memory_lock=true - - discovery.type=single-node - - path.repo=/tmp - - ${OPENSEARCH_PREFIX:-opendistro_security}.ssl.http.enabled=false - - http.port=9220 - - network.publish_host=127.0.0.1 - - logger.org.opensearch=warn - - "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g" - ulimits: - nproc: 65536 - nofile: - soft: 65536 - hard: 65536 - memlock: - soft: -1 - hard: -1 - ports: - - 9220:9220 networks: opensearch: driver: bridge diff --git a/docs/data-sources/destination.md b/docs/data-sources/destination.md deleted file mode 100644 index c28b19e..0000000 --- a/docs/data-sources/destination.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "opensearch_destination Data Source - terraform-provider-opensearch" -subcategory: "" -description: |- - opensearch_destination can be used to retrieve the destination object by name. ---- - -# opensearch_destination (Data Source) - -`opensearch_destination` can be used to retrieve the destination object by name. - -## Example Usage - -```terraform -# Example destination in other terraform plan -# resource "opensearch_destination" "test" { -# body = < -## Schema - -### Required - -- `name` (String) Name of the destrination to retrieve - -### Read-Only - -- `body` (Map of String) Map of the attributes of the destination -- `id` (String) The ID of this resource. - - diff --git a/docs/index.md b/docs/index.md index 15fa89b..765272f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -64,7 +64,7 @@ EOF - `aws_access_key` (String) The access key for use with AWS opensearch Service domains - `aws_assume_role_arn` (String) Amazon Resource Name of an IAM Role to assume prior to making AWS API calls. -- `aws_assume_role_external_id` (Optional) - External ID configured in the role to assume prior to making AWS API calls. +- `aws_assume_role_external_id` (String) External ID configured in the IAM policy of the IAM Role to assume prior to making AWS API calls. - `aws_profile` (String) The AWS profile for use with AWS opensearch Service domains - `aws_region` (String) The AWS region for use in signing of AWS opensearch requests. Must be specified in order to use AWS URL signing with AWS OpenSearch endpoint exposed on a custom DNS domain. - `aws_secret_key` (String) The secret key for use with AWS opensearch Service domains diff --git a/docs/resources/composable_index_template.md b/docs/resources/composable_index_template.md index 5d2d550..e2005e0 100644 --- a/docs/resources/composable_index_template.md +++ b/docs/resources/composable_index_template.md @@ -3,12 +3,12 @@ page_title: "opensearch_composable_index_template Resource - terraform-provider-opensearch" subcategory: "" description: |- - Provides an Composable index template resource. This resource uses the /_index_template endpoint of the API that is available since version 7.8. Use opensearch_index_template if you are using older versions or if you want to keep using legacy Index Templates in versions 7.8+. + Provides an Composable index template resource. This resource uses the /_index_template endpoint of the API that is available since version 2.0.0. Use opensearch_index_template if you are using older versions or if you want to keep using legacy Index Templates. --- # opensearch_composable_index_template (Resource) -Provides an Composable index template resource. This resource uses the `/_index_template` endpoint of the API that is available since version 7.8. Use `opensearch_index_template` if you are using older versions or if you want to keep using legacy Index Templates in versions 7.8+. +Provides an Composable index template resource. This resource uses the `/_index_template` endpoint of the API that is available since version 2.0.0. Use `opensearch_index_template` if you are using older versions or if you want to keep using legacy Index Templates. ## Example Usage diff --git a/docs/resources/dashboard_object.md b/docs/resources/dashboard_object.md index 238eb67..e05e362 100644 --- a/docs/resources/dashboard_object.md +++ b/docs/resources/dashboard_object.md @@ -3,15 +3,12 @@ page_title: "opensearch_dashboard_object Resource - terraform-provider-opensearch" subcategory: "" description: |- - Provides an OpenSearch Dashboards object resource. This resource interacts directly with the underlying OpenSearch index backing Dashboards, so the format must match what Dashboards the version of Dashboards is expecting. Dashboards v5 and v6 will export all objects in Dashboards v5 format, so the exported objects cannot be used as a source for body in this resource - directly pulling the JSON from a Dashboards index of the same version of OpenSearch targeted by the provider is a workaround. - With the removal of mapping types in OpenSearch, the Dashboards index changed from v5 to >= v6, previously the document mapping type had the Dashboards object type, however, the _type going forward is doc and the type is within the document, see below. Using v5 doc types in v6 and above will result in errors from OpenSearch after one or more document types are used. + Provides an OpenSearch Dashboards object resource. This resource interacts directly with the underlying OpenSearch index backing Dashboards, so the format must match what Dashboards the version of Dashboards is expecting. Dashboards with older versions - directly pulling the JSON from a Dashboards index of the same version of OpenSearch targeted by the provider is a workaround. --- # opensearch_dashboard_object (Resource) -Provides an OpenSearch Dashboards object resource. This resource interacts directly with the underlying OpenSearch index backing Dashboards, so the format must match what Dashboards the version of Dashboards is expecting. Dashboards v5 and v6 will export all objects in Dashboards v5 format, so the exported objects cannot be used as a source for `body` in this resource - directly pulling the JSON from a Dashboards index of the same version of OpenSearch targeted by the provider is a workaround. - -With the removal of mapping types in OpenSearch, the Dashboards index changed from v5 to >= v6, previously the document mapping type had the Dashboards object type, however, the `_type` going forward is `doc` and the type is within the document, see below. Using v5 doc types in v6 and above will result in errors from OpenSearch after one or more document types are used. +Provides an OpenSearch Dashboards object resource. This resource interacts directly with the underlying OpenSearch index backing Dashboards, so the format must match what Dashboards the version of Dashboards is expecting. Dashboards with older versions - directly pulling the JSON from a Dashboards index of the same version of OpenSearch targeted by the provider is a workaround. ## Example Usage diff --git a/docs/resources/destination.md b/docs/resources/destination.md deleted file mode 100644 index 707d20c..0000000 --- a/docs/resources/destination.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "opensearch_destination Resource - terraform-provider-opensearch" -subcategory: "" -description: |- - Provides an OpenSearch destination, a reusable communication channel for an action, such as email, Slack, or a webhook URL. Please refer to the OpenSearch destination documentation for details. ---- - -# opensearch_destination (Resource) - -Provides an OpenSearch destination, a reusable communication channel for an action, such as email, Slack, or a webhook URL. Please refer to the OpenSearch destination documentation for details. - -## Example Usage - -```terraform -resource "opensearch_destination" "test_destination" { - body = < -## Schema - -### Required - -- `body` (String) The JSON body of the destination. - -### Read-Only - -- `id` (String) The ID of this resource. - -## Import - -Import is supported using the following syntax: - -```shell -# Import by name -terraform import opensearch_destination.test_destination my-destination -``` diff --git a/provider/data_source_opensearch_destination.go b/provider/data_source_opensearch_destination.go deleted file mode 100644 index 3010605..0000000 --- a/provider/data_source_opensearch_destination.go +++ /dev/null @@ -1,186 +0,0 @@ -package provider - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "log" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - - "github.com/olivere/elastic/uritemplates" - elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" -) - -const DESTINATION_NAME_FIELD = "destination.name.keyword" - -var datasourceOpenDistroDestinationSchema = map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - Description: "Name of the destrination to retrieve", - }, - "body": { - Type: schema.TypeMap, - Computed: true, - Description: "Map of the attributes of the destination", - }, -} - -func dataSourceOpenSearchDestination() *schema.Resource { - return &schema.Resource{ - Description: "`opensearch_destination` can be used to retrieve the destination object by name.", - Read: dataSourceOpensearchOpenDistroDestinationRead, - Schema: datasourceOpenDistroDestinationSchema, - } -} - -func dataSourceOpensearchOpenDistroDestinationRead(d *schema.ResourceData, m interface{}) error { - destinationName := d.Get("name").(string) - - var id string - var destination map[string]interface{} - var err error - esClient, err := getClient(m.(*ProviderConf)) - if err != nil { - return err - } - switch client := esClient.(type) { - case *elastic7.Client: - // See https://github.com/opendistro-for-elasticsearch/alerting/issues/70, - // no tags or API endpoint for searching destination. In ODFE >= 1.11.0, - // the index has become a "system index", so it cannot be searched: - // https://opendistro.github.io/for-elasticsearch-docs/docs/alerting/settings/#alerting-indices - // instead we paginate through all destinations to find the first name match :| - id, destination, err = destinationOpenSearch7GetAll(client, destinationName) - if err != nil { - id, destination, err = destinationOpenSearch7Search(client, DESTINATION_INDEX, destinationName) - } - case *elastic6.Client: - id, destination, err = destinationOpenSearch6Search(client, DESTINATION_INDEX, destinationName) - default: - err = errors.New("destination resource not implemented prior to v6") - } - - if err != nil { - return err - } else if id == "" { - // short circuit - return nil - } - - d.SetId(id) - - // we get a non-uniform map[string]interface{} back for the body, terraform - // only accepts a mapping of string to primitive values. We want to save - // this as a map so that attributes are accessible - simplifiedBody := map[string]string{} - for key, value := range destination { - if stringified, ok := value.(string); ok { - simplifiedBody[key] = stringified - } else { - log.Printf("[INFO] couldn't simplify: %+v", value) - } - } - err = d.Set("body", simplifiedBody) - return err -} - -func destinationOpenSearch7Search(client *elastic7.Client, index string, name string) (string, map[string]interface{}, error) { - termQuery := elastic7.NewTermQuery(DESTINATION_NAME_FIELD, name) - result, err := client.Search(). - Index(index). - Query(termQuery). - Do(context.TODO()) - - destination := make(map[string]interface{}) - if err != nil { - return "", destination, err - } - if result.TotalHits() == 1 { - if err := json.Unmarshal(result.Hits.Hits[0].Source, &destination); err != nil { - return "", destination, fmt.Errorf("error unmarshalling destination body: %+v", err) - } - - return result.Hits.Hits[0].Id, destination["destination"].(map[string]interface{}), nil - } else if result.TotalHits() < 1 { - return "", destination, err - } else { - return "", destination, fmt.Errorf("1 result expected, found %d.", result.TotalHits()) - } -} - -func destinationOpenSearch6Search(client *elastic6.Client, index string, name string) (string, map[string]interface{}, error) { - termQuery := elastic6.NewTermQuery(DESTINATION_NAME_FIELD, name) - result, err := client.Search(). - Index(index). - Query(termQuery). - Do(context.TODO()) - - destination := make(map[string]interface{}) - if err != nil { - return "", destination, err - } - if result.TotalHits() == 1 { - if err := json.Unmarshal(*result.Hits.Hits[0].Source, &destination); err != nil { - return "", destination, fmt.Errorf("error unmarshalling destination body: %+v", err) - } - - return result.Hits.Hits[0].Id, destination["destination"].(map[string]interface{}), nil - } else if result.TotalHits() < 1 { - return "", destination, err - } else { - return "", destination, fmt.Errorf("1 result expected, found %d.", result.TotalHits()) - } -} - -func destinationOpenSearch7GetAll(client *elastic7.Client, name string) (string, map[string]interface{}, error) { - offset := 0 - pageSize := 1000 - destination := make(map[string]interface{}) - for { - path, err := uritemplates.Expand("/_opendistro/_alerting/destinations?startIndex={startIndex}&size={size}", map[string]string{ - "startIndex": fmt.Sprint(offset), - "size": fmt.Sprint(pageSize), - }) - if err != nil { - return "", destination, fmt.Errorf("error building URL path for destination: %+v", err) - } - - httpResponse, err := client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "GET", - Path: path, - }) - if err != nil { - return "", destination, err - } - - var drg destinationResponseGet - if err := json.Unmarshal(httpResponse.Body, &drg); err != nil { - return "", destination, fmt.Errorf("error unmarshalling destination body: %+v", err) - } - - for _, d := range drg.Destinations { - if d.Name == name { - j, err := json.Marshal(d) - if err != nil { - return "", destination, fmt.Errorf("error marshalling destination: %+v", err) - } - if err := json.Unmarshal(j, &destination); err != nil { - return "", destination, fmt.Errorf("error unmarshalling destination body: %+v", err) - } - return d.ID, destination, nil - } - } - - if drg.Total > offset { - offset += pageSize - } else { - break - } - } - - return "", destination, fmt.Errorf("destination not found") -} diff --git a/provider/data_source_opensearch_destination_test.go b/provider/data_source_opensearch_destination_test.go deleted file mode 100644 index 0659322..0000000 --- a/provider/data_source_opensearch_destination_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package provider - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" -) - -func TestAccOpensearchDataSourceDestination_basic(t *testing.T) { - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, - Providers: testAccOpendistroProviders, - Steps: []resource.TestStep{ - { - Config: testAccOpensearchDataSourceDestination, - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet("data.opensearch_destination.test", "id"), - resource.TestCheckResourceAttrSet("data.opensearch_destination.test", "body.type"), - ), - }, - }, - }) -} - -var testAccOpensearchDataSourceDestination = ` -resource "opensearch_destination" "test" { - body = < 0 { - url = urls.Index(0).String() - } - case *elastic6.Client: - urls := reflect.ValueOf(client).Elem().FieldByName("urls") - if urls.Len() > 0 { - url = urls.Index(0).String() - } - default: - return errors.New("this version of OpenSearch is not supported") + urls := reflect.ValueOf(osClient).Elem().FieldByName("urls") + if urls.Len() > 0 { + url = urls.Index(0).String() } d.SetId(url) err = d.Set("url", url) diff --git a/provider/diff_suppress_funcs.go b/provider/diff_suppress_funcs.go index 33489e7..0795953 100644 --- a/provider/diff_suppress_funcs.go +++ b/provider/diff_suppress_funcs.go @@ -71,26 +71,6 @@ func diffSuppressComponentTemplate(k, old, new string, d *schema.ResourceData) b return reflect.DeepEqual(oo, no) } -func diffSuppressDestination(k, old, new string, d *schema.ResourceData) bool { - var oo, no interface{} - if err := json.Unmarshal([]byte(old), &oo); err != nil { - return false - } - if err := json.Unmarshal([]byte(new), &no); err != nil { - return false - } - - if om, ok := oo.(map[string]interface{}); ok { - normalizeDestination(om) - } - - if nm, ok := no.(map[string]interface{}); ok { - normalizeDestination(nm) - } - - return reflect.DeepEqual(oo, no) -} - func diffSuppressMonitor(k, old, new string, d *schema.ResourceData) bool { var oo, no interface{} if err := json.Unmarshal([]byte(old), &oo); err != nil { diff --git a/provider/provider.go b/provider/provider.go index 49a8189..8803ba5 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -26,7 +26,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" ) type ServerFlavor int64 @@ -35,6 +34,7 @@ type ServerFlavor int64 const ( Unknown ServerFlavor = iota OpenSearch + Default = 2 ) var awsUrlRegexp = regexp.MustCompile(`([a-z0-9-]+).es.amazonaws.com$`) @@ -226,7 +226,6 @@ func Provider() *schema.Provider { "opensearch_ingest_pipeline": resourceOpensearchIngestPipeline(), "opensearch_dashboard_object": resourceOpensearchDashboardObject(), "opensearch_audit_config": resourceOpenSearchAuditConfig(), - "opensearch_destination": resourceOpenSearchDestination(), "opensearch_ism_policy_mapping": resourceOpenSearchISMPolicyMapping(), "opensearch_ism_policy": resourceOpenSearchISMPolicy(), "opensearch_dashboard_tenant": resourceOpenSearchDashboardTenant(), @@ -239,8 +238,7 @@ func Provider() *schema.Provider { }, DataSourcesMap: map[string]*schema.Resource{ - "opensearch_host": dataSourceOpensearchHost(), - "opensearch_destination": dataSourceOpenSearchDestination(), + "opensearch_host": dataSourceOpensearchHost(), }, ConfigureContextFunc: providerConfigure, @@ -283,7 +281,7 @@ func providerConfigure(c context.Context, d *schema.ResourceData) (interface{}, }, nil } -func getClient(conf *ProviderConf) (interface{}, error) { +func getClient(conf *ProviderConf) (*elastic7.Client, error) { opts := []elastic7.ClientOptionFunc{ elastic7.SetURL(conf.rawUrl), elastic7.SetScheme(conf.parsedUrl.Scheme), @@ -352,7 +350,6 @@ func getClient(conf *ProviderConf) (interface{}, error) { opts = append(opts, elastic7.SetErrorLog(errorLogger)) } - var relevantClient interface{} client, err := elastic7.NewClient(opts...) if err != nil { if errors.Is(err, elastic7.ErrNoClient) { @@ -361,7 +358,6 @@ func getClient(conf *ProviderConf) (interface{}, error) { } return nil, err } - relevantClient = client // Use the v7 client to ping the cluster to determine the version if one was not provided if conf.osVersion == "" { @@ -387,82 +383,15 @@ func getClient(conf *ProviderConf) (interface{}, error) { log.Printf("[INFO] OS version %+v", info.Version) switch info.Version.BuildFlavor { case "default": - conf.flavor = OpenSearch - } - } - - if conf.osVersion < "7.0.0" && conf.osVersion >= "6.0.0" { - log.Printf("[INFO] Using ES 6") - opts := []elastic6.ClientOptionFunc{ - elastic6.SetURL(conf.rawUrl), - elastic6.SetScheme(conf.parsedUrl.Scheme), - elastic6.SetSniff(conf.sniffing), - elastic6.SetHealthcheck(conf.healthchecking), - } - - if conf.parsedUrl.User.Username() != "" { - p, _ := conf.parsedUrl.User.Password() - opts = append(opts, elastic6.SetBasicAuth(conf.parsedUrl.User.Username(), p)) - } - if conf.username != "" && conf.password != "" { - opts = append(opts, elastic6.SetBasicAuth(conf.username, conf.password)) - } - - if m := awsUrlRegexp.FindStringSubmatch(conf.parsedUrl.Hostname()); m != nil && conf.signAWSRequests { - log.Printf("[INFO] Using AWS: %+v", m[1]) - client, err := awsHttpClient(m[1], conf, map[string]string{}) - if err != nil { - return nil, err - } - opts = append(opts, elastic6.SetHttpClient(client), elastic6.SetSniff(false)) - } else if awsRegion := conf.awsRegion; conf.awsRegion != "" && conf.signAWSRequests { - log.Printf("[INFO] Using AWS: %+v", conf.awsRegion) - client, err := awsHttpClient(awsRegion, conf, map[string]string{}) - if err != nil { - return nil, err - } - opts = append(opts, elastic6.SetHttpClient(client), elastic6.SetSniff(false)) - } else if conf.insecure || conf.cacertFile != "" { - opts = append(opts, elastic6.SetHttpClient(tlsHttpClient(conf, map[string]string{})), elastic6.SetSniff(false)) - } else if conf.token != "" { - opts = append(opts, elastic6.SetHttpClient(tokenHttpClient(conf, map[string]string{})), elastic6.SetSniff(false)) - } else { - opts = append(opts, elastic6.SetHttpClient(defaultHttpClient(conf, map[string]string{}))) - } - - switch logProviderLevel { - case "TRACE": - traceLogger := esLogger.StandardLogger(&hclog.StandardLoggerOptions{ - ForceLevel: hclog.LevelFromString("TRACE"), - }) - opts = append(opts, elastic6.SetTraceLog(traceLogger)) - fallthrough - case "INFO": - infoLogger := esLogger.StandardLogger(&hclog.StandardLoggerOptions{ - ForceLevel: hclog.LevelFromString("INFO"), - }) - opts = append(opts, elastic6.SetInfoLog(infoLogger)) - fallthrough + conf.flavor = Unknown default: - errorLogger := esLogger.StandardLogger(&hclog.StandardLoggerOptions{ - ForceLevel: hclog.LevelFromString("ERROR"), - }) - opts = append(opts, elastic6.SetErrorLog(errorLogger)) - } - - relevantClient, err = elastic6.NewClient(opts...) - if err != nil { - return nil, err + conf.flavor = OpenSearch } - } else if conf.flavor == Unknown && conf.osVersion < "2.0.0" && conf.osVersion >= "1.0.0" { - // Version 1.x of OpenSearch very likely. Nothing to do since it's API - // compatible with 7.x of ES. If elastic client library supports detecting - // flavor, update to Opensearch. - } else if conf.osVersion < "6.0.0" { - return nil, fmt.Errorf("opensearch version %s is older than 6.0.0 and is not supported, flavor: %v.", conf.osVersion, conf.flavor) + } else if conf.flavor == Unknown || conf.osVersion < "1.0.0" { + return nil, fmt.Errorf("opensearch version %s is older than 1.0.0 and is not supported, flavor: %v.", conf.osVersion, conf.flavor) } - return relevantClient, nil + return client, nil } func assumeRoleCredentials(region, roleARN, roleExternalID, profile string) *awscredentials.Credentials { diff --git a/provider/provider_test.go b/provider/provider_test.go index 26b4856..dae0016 100644 --- a/provider/provider_test.go +++ b/provider/provider_test.go @@ -42,7 +42,7 @@ func init() { opendistroOriginalConfigureFunc := testAccOpendistroProvider.ConfigureContextFunc testAccOpendistroProvider.ConfigureContextFunc = func(c context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { - err := d.Set("url", "http://admin:admin@127.0.0.1:9220") + err := d.Set("url", "http://admin:admin@127.0.0.1:9200") if err != nil { return nil, diag.FromErr(err) } diff --git a/provider/resource_opensearch_audit_config.go b/provider/resource_opensearch_audit_config.go index 5f7e1c1..17dffd5 100644 --- a/provider/resource_opensearch_audit_config.go +++ b/provider/resource_opensearch_audit_config.go @@ -3,7 +3,6 @@ package provider import ( "context" "encoding/json" - "errors" "fmt" "log" "net/http" @@ -321,24 +320,19 @@ func resourceOpensearchGetAuditConfig(m interface{}) (getAuditConfigResponse, er audit := new(getAuditConfigResponse) var body json.RawMessage - esClient, err := getClient(m.(*ProviderConf)) + osClient, err := getClient(m.(*ProviderConf)) if err != nil { return *audit, err } - switch client := esClient.(type) { - case *elastic7.Client: - var res *elastic7.Response - res, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "GET", - Path: "/_plugins/_security/api/audit", - }) - if err != nil { - return *audit, err - } - body = res.Body - default: - return *audit, errors.New("audit config resource not implemented prior to OpenSearch v1") + var res *elastic7.Response + res, err = osClient.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ + Method: "GET", + Path: "/_plugins/_security/api/audit", + }) + if err != nil { + return *audit, err } + body = res.Body if err := json.Unmarshal(body, &audit); err != nil { return *audit, fmt.Errorf("Error unmarshalling user body: %+v: %+v", err, body) @@ -431,38 +425,33 @@ func resourceOpensearchPutAuditConfig(d *schema.ResourceData, m interface{}) (*p } var body json.RawMessage - esClient, err := getClient(m.(*ProviderConf)) + osClient, err := getClient(m.(*ProviderConf)) if err != nil { return nil, err } - switch client := esClient.(type) { - case *elastic7.Client: - var res *elastic7.Response - log.Printf("[INFO] put audit config: %+v", auditConfig) - res, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "PUT", - Path: "/_plugins/_security/api/audit/config", - Body: string(auditConfigJSON), - RetryStatusCodes: []int{http.StatusInternalServerError}, - Retrier: elastic7.NewBackoffRetrier( - elastic7.NewExponentialBackoff(100*time.Millisecond, 30*time.Second), - ), - }) - if err != nil { - e, ok := err.(*elastic7.Error) - if !ok { - log.Printf("[ERROR] expected error to be of type *elastic.Error") - } else { - log.Printf("[ERROR] error creating audit config: %v %v %v", res, res.Body, e) - } - return response, err + var res *elastic7.Response + log.Printf("[INFO] put audit config: %+v", auditConfig) + res, err = osClient.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ + Method: "PUT", + Path: "/_plugins/_security/api/audit/config", + Body: string(auditConfigJSON), + RetryStatusCodes: []int{http.StatusInternalServerError}, + Retrier: elastic7.NewBackoffRetrier( + elastic7.NewExponentialBackoff(100*time.Millisecond, 30*time.Second), + ), + }) + if err != nil { + e, ok := err.(*elastic7.Error) + if !ok { + log.Printf("[ERROR] expected error to be of type *elastic.Error") + } else { + log.Printf("[ERROR] error creating audit config: %v %v %v", res, res.Body, e) } - - body = res.Body - default: - return response, errors.New("audit config resource not implemented prior to OpenSearch v1") + return response, err } + body = res.Body + if err := json.Unmarshal(body, response); err != nil { return response, fmt.Errorf("failed to unmarshal audit config body: %+v: %+v", err, body) } diff --git a/provider/resource_opensearch_audit_config_test.go b/provider/resource_opensearch_audit_config_test.go index 6cac203..170f0fa 100644 --- a/provider/resource_opensearch_audit_config_test.go +++ b/provider/resource_opensearch_audit_config_test.go @@ -7,7 +7,6 @@ import ( "testing" elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" "github.com/hashicorp/go-version" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -22,21 +21,12 @@ func TestAccOpensearchOpenSearchSecurityAuditConfig(t *testing.T) { } meta := provider.Meta() providerConf := meta.(*ProviderConf) - esClient, err := getClient(providerConf) + var allowed bool + version, err := version.NewVersion(providerConf.osVersion) if err != nil { t.Skipf("err: %s", err) } - var allowed bool - switch esClient.(type) { - case *elastic6.Client: - allowed = false - default: - version, err := version.NewVersion(providerConf.osVersion) - if err != nil { - t.Skipf("err: %s", err) - } - allowed = version.Segments()[0] == 1 - } + allowed = version.Segments()[0] == 1 resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { @@ -160,15 +150,10 @@ func testCheckOpensearchSecurityAuditConfigExists(name string) resource.TestChec meta := testAccOpendistroProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch esClient.(type) { - case *elastic7.Client: - _, err = resourceOpensearchGetAuditConfig(meta.(*ProviderConf)) - default: - } + _, err = resourceOpensearchGetAuditConfig(meta.(*ProviderConf)) if err != nil { return err @@ -190,23 +175,18 @@ func testCheckOpensearchSecurityAuditConfigConnects(name string) resource.TestCh username := rs.Primary.Attributes["username"] password := rs.Primary.Attributes["password"] - meta := testAccOpendistroProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch esClient.(type) { - case *elastic7.Client: - var client *elastic7.Client - client, err = elastic7.NewClient( - elastic7.SetURL(os.Getenv("OPENSEARCH_URL")), - elastic7.SetBasicAuth(username, password)) - - if err == nil { - _, err = client.ClusterHealth().Do(context.TODO()) - } + var client *elastic7.Client + client, err = elastic7.NewClient( + elastic7.SetURL(os.Getenv("OPENSEARCH_URL")), + elastic7.SetBasicAuth(username, password)) + + if err == nil { + _, err = client.ClusterHealth().Do(context.TODO()) } if err != nil { diff --git a/provider/resource_opensearch_cluster_settings.go b/provider/resource_opensearch_cluster_settings.go index e8d68d2..2f016ce 100644 --- a/provider/resource_opensearch_cluster_settings.go +++ b/provider/resource_opensearch_cluster_settings.go @@ -3,7 +3,6 @@ package provider import ( "context" "encoding/json" - "errors" "fmt" "log" "reflect" @@ -15,7 +14,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" ) var ( @@ -292,7 +290,7 @@ func resourceOpensearchClusterSettingsCreate(d *schema.ResourceData, meta interf func resourceOpensearchPutClusterSettings(d *schema.ResourceData, meta interface{}) error { var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } @@ -304,28 +302,14 @@ func resourceOpensearchPutClusterSettings(d *schema.ResourceData, meta interface return err } - switch client := esClient.(type) { - case *elastic7.Client: - // client doesn't support PUTing settings: https://github.com/olivere/elastic/issues/1274 - _, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "PUT", - Path: "/_cluster/settings", - Body: string(body), - }) - if err != nil { - return err - } - case *elastic6.Client: - _, err = client.PerformRequest(context.TODO(), elastic6.PerformRequestOptions{ - Method: "PUT", - Path: "/_cluster/settings", - Body: string(body), - }) - if err != nil { - return err - } - default: - return errors.New("opensearch version not supported") + // client doesn't support PUTing settings: https://github.com/olivere/elastic/issues/1274 + _, err = osClient.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ + Method: "PUT", + Path: "/_cluster/settings", + Body: string(body), + }) + if err != nil { + return err } return err @@ -359,37 +343,19 @@ func resourceOpensearchClusterSettingsGet(meta interface{}) (map[string]interfac var settings map[string]interface{} var response *json.RawMessage - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return settings, err } - - switch client := esClient.(type) { - case *elastic7.Client: - var res *elastic7.Response - - res, err := client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "GET", - Path: "/_cluster/settings?flat_settings=true", - }) - if err != nil { - return settings, err - } - response = &res.Body - case *elastic6.Client: - var res *elastic6.Response - - res, err := client.PerformRequest(context.TODO(), elastic6.PerformRequestOptions{ - Method: "GET", - Path: "/_cluster/settings?flat_settings=true", - }) - if err != nil { - return settings, err - } - response = &res.Body - default: - return settings, errors.New("opensearch version not supported") + var res *elastic7.Response + res, err = osClient.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ + Method: "GET", + Path: "/_cluster/settings?flat_settings=true", + }) + if err != nil { + return settings, err } + response = &res.Body err = json.Unmarshal(*response, &settings) if err != nil { @@ -402,7 +368,7 @@ func resourceOpensearchClusterSettingsGet(meta interface{}) (map[string]interfac func clearAllSettings(meta interface{}) error { var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } @@ -413,31 +379,18 @@ func clearAllSettings(meta interface{}) error { "action.*": null, "script.*": null, "network.*": null, - "search.*": null + "search.*": null, + "plugins.*": null } }` - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "PUT", - Path: "/_cluster/settings", - Body: body, - }) - if err != nil { - return err - } - case *elastic6.Client: - _, err = client.PerformRequest(context.TODO(), elastic6.PerformRequestOptions{ - Method: "PUT", - Path: "/_cluster/settings", - Body: body, - }) - if err != nil { - return err - } - default: - return errors.New("opensearch version not supported") + _, err = osClient.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ + Method: "PUT", + Path: "/_cluster/settings", + Body: body, + }) + if err != nil { + return err } return err diff --git a/provider/resource_opensearch_component_template.go b/provider/resource_opensearch_component_template.go index 4bdabe2..7a29e13 100644 --- a/provider/resource_opensearch_component_template.go +++ b/provider/resource_opensearch_component_template.go @@ -12,7 +12,7 @@ import ( elastic7 "github.com/olivere/elastic/v7" ) -var esComponentTemplateMinimalVersion, _ = version.NewVersion("7.8.0") +var osComponentTemplateMinimalVersion, _ = version.NewVersion("2.0.0") func resourceOpensearchComponentTemplate() *schema.Resource { return &schema.Resource{ @@ -58,23 +58,18 @@ func resourceOpensearchComponentTemplateRead(d *schema.ResourceData, meta interf var openSearchVersion *version.Version providerConf := meta.(*ProviderConf) - esClient, err := getClient(providerConf) + osClient, err := getClient(providerConf) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - openSearchVersion, err = version.NewVersion(providerConf.osVersion) - if err == nil { - if resourceOpensearchComponentTemplateAvailable(openSearchVersion, providerConf) { - result, err = elastic7GetComponentTemplate(client, id) - } else { - err = fmt.Errorf("component_template endpoint only available from server version >= 7.8, got version %s", openSearchVersion.String()) - } + openSearchVersion, err = version.NewVersion(providerConf.osVersion) + if err == nil { + if resourceOpensearchComponentTemplateAvailable(openSearchVersion, providerConf) { + result, err = elastic7GetComponentTemplate(osClient, id) + } else { + err = fmt.Errorf("component_template endpoint only available from server version >= 2.0.0, got version %s", openSearchVersion.String()) } - default: - err = fmt.Errorf("component_template endpoint only available from server version >= 7.8, got version < 7.0.0") } if err != nil { if elastic7.IsNotFound(err) { @@ -118,23 +113,18 @@ func resourceOpensearchComponentTemplateDelete(d *schema.ResourceData, meta inte var openSearchVersion *version.Version providerConf := meta.(*ProviderConf) - esClient, err := getClient(providerConf) + osClient, err := getClient(providerConf) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - openSearchVersion, err = version.NewVersion(providerConf.osVersion) - if err == nil { - if resourceOpensearchComponentTemplateAvailable(openSearchVersion, providerConf) { - err = elastic7DeleteComponentTemplate(client, id) - } else { - err = fmt.Errorf("component_template endpoint only available from server version >= 7.8, got version %s", openSearchVersion.String()) - } + openSearchVersion, err = version.NewVersion(providerConf.osVersion) + if err == nil { + if resourceOpensearchComponentTemplateAvailable(openSearchVersion, providerConf) { + err = elastic7DeleteComponentTemplate(osClient, id) + } else { + err = fmt.Errorf("component_template endpoint only available from server version >= 2.0.0, got version %s", openSearchVersion.String()) } - default: - err = fmt.Errorf("component_template endpoint only available from server version >= 7.8, got version < 7.0.0") } if err != nil { @@ -145,7 +135,7 @@ func resourceOpensearchComponentTemplateDelete(d *schema.ResourceData, meta inte } func resourceOpensearchComponentTemplateAvailable(v *version.Version, c *ProviderConf) bool { - return v.GreaterThanOrEqual(esComponentTemplateMinimalVersion) || c.flavor == Unknown + return v.GreaterThanOrEqual(osComponentTemplateMinimalVersion) || c.flavor == Unknown } func elastic7DeleteComponentTemplate(client *elastic7.Client, id string) error { @@ -160,23 +150,18 @@ func resourceOpensearchPutComponentTemplate(d *schema.ResourceData, meta interfa var openSearchVersion *version.Version providerConf := meta.(*ProviderConf) - esClient, err := getClient(providerConf) + osClient, err := getClient(providerConf) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - openSearchVersion, err = version.NewVersion(providerConf.osVersion) - if err == nil { - if resourceOpensearchComponentTemplateAvailable(openSearchVersion, providerConf) { - err = elastic7PutComponentTemplate(client, name, body, create) - } else { - err = fmt.Errorf("component_template endpoint only available from server version >= 7.8, got version %s", openSearchVersion.String()) - } + openSearchVersion, err = version.NewVersion(providerConf.osVersion) + if err == nil { + if resourceOpensearchComponentTemplateAvailable(openSearchVersion, providerConf) { + err = elastic7PutComponentTemplate(osClient, name, body, create) + } else { + err = fmt.Errorf("component_template endpoint only available from server version >= 2.0.0, got version %s", openSearchVersion.String()) } - default: - err = fmt.Errorf("component_template endpoint only available from server version >= 7.8, got version < 7.0.0") } return err diff --git a/provider/resource_opensearch_component_template_test.go b/provider/resource_opensearch_component_template_test.go index d995664..0bb93d7 100644 --- a/provider/resource_opensearch_component_template_test.go +++ b/provider/resource_opensearch_component_template_test.go @@ -2,12 +2,9 @@ package provider import ( "context" - "errors" "fmt" "testing" - elastic7 "github.com/olivere/elastic/v7" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) @@ -18,25 +15,12 @@ func TestAccOpensearchComponentTemplate(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - - var allowed bool - switch esClient.(type) { - case *elastic7.Client: - allowed = true - default: - allowed = false - } + var allowed bool = true resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) if !allowed { - t.Skip("/_component_template endpoint only supported on ES >= 7.8") + t.Skip("/_component_template endpoint only supported on OS >= 2.0.0") } }, Providers: testAccProviders, @@ -58,25 +42,12 @@ func TestAccOpensearchComponentTemplate_importBasic(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - - var allowed bool - switch esClient.(type) { - case *elastic7.Client: - allowed = true - default: - allowed = false - } + var allowed bool = true resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) if !allowed { - t.Skip("/_component_template endpoint only supported on ES >= 7.8") + t.Skip("/_component_template endpoint only supported on OS >= 2.0.0") } }, Providers: testAccProviders, @@ -106,17 +77,12 @@ func testCheckOpensearchComponentTemplateExists(name string) resource.TestCheckF meta := testAccProvider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.IndexGetComponentTemplate(rs.Primary.ID).Do(context.TODO()) - default: - err = errors.New("/_component_template endpoint only supported on ES >= 7.8") - } + _, err = osClient.IndexGetComponentTemplate(rs.Primary.ID).Do(context.TODO()) if err != nil { return err @@ -134,17 +100,12 @@ func testCheckOpensearchComponentTemplateDestroy(s *terraform.State) error { meta := testAccProvider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.IndexGetComponentTemplate(rs.Primary.ID).Do(context.TODO()) - default: - err = errors.New("/_component_template endpoint only supported on ES >= 7.8") - } + _, err = osClient.IndexGetComponentTemplate(rs.Primary.ID).Do(context.TODO()) if err != nil { return nil // should be not found error diff --git a/provider/resource_opensearch_composable_index_template.go b/provider/resource_opensearch_composable_index_template.go index 6c2ae10..3eac492 100644 --- a/provider/resource_opensearch_composable_index_template.go +++ b/provider/resource_opensearch_composable_index_template.go @@ -12,7 +12,7 @@ import ( elastic7 "github.com/olivere/elastic/v7" ) -var minimalESComposableTemplateVersion, _ = version.NewVersion("7.8.0") +var minimalOSComposableTemplateVersion, _ = version.NewVersion("2.0.0") func resourceOpensearchComposableIndexTemplate() *schema.Resource { return &schema.Resource{ @@ -38,7 +38,7 @@ func resourceOpensearchComposableIndexTemplate() *schema.Resource { Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, - Description: "Provides an Composable index template resource. This resource uses the `/_index_template` endpoint of the API that is available since version 7.8. Use `opensearch_index_template` if you are using older versions or if you want to keep using legacy Index Templates in versions 7.8+.", + Description: "Provides an Composable index template resource. This resource uses the `/_index_template` endpoint of the API that is available since version 2.0.0. Use `opensearch_index_template` if you are using older versions or if you want to keep using legacy Index Templates.", } } @@ -52,7 +52,7 @@ func resourceOpensearchComposableIndexTemplateCreate(d *schema.ResourceData, met } func resourceOpensearchComposableIndexTemplateAvailable(v *version.Version, c *ProviderConf) bool { - return v.GreaterThanOrEqual(minimalESComposableTemplateVersion) || c.flavor == Unknown + return v.GreaterThanOrEqual(minimalOSComposableTemplateVersion) || c.flavor == Unknown } func resourceOpensearchComposableIndexTemplateRead(d *schema.ResourceData, meta interface{}) error { @@ -62,23 +62,18 @@ func resourceOpensearchComposableIndexTemplateRead(d *schema.ResourceData, meta var openSearchVersion *version.Version providerConf := meta.(*ProviderConf) - esClient, err := getClient(providerConf) + osClient, err := getClient(providerConf) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - openSearchVersion, err = version.NewVersion(providerConf.osVersion) - if err == nil { - if resourceOpensearchComposableIndexTemplateAvailable(openSearchVersion, providerConf) { - result, err = elastic7GetIndexTemplate(client, id) - } else { - err = fmt.Errorf("index_template endpoint only available from server version >= 7.8, got version %s", openSearchVersion.String()) - } + openSearchVersion, err = version.NewVersion(providerConf.osVersion) + if err == nil { + if resourceOpensearchComposableIndexTemplateAvailable(openSearchVersion, providerConf) { + result, err = elastic7GetIndexTemplate(osClient, id) + } else { + err = fmt.Errorf("index_template endpoint only available from server version >= 2.0.0, got version %s", openSearchVersion.String()) } - default: - err = fmt.Errorf("index_template endpoint only available from server version >= 7.8, got version < 7.0.0") } if err != nil { if elastic7.IsNotFound(err) { @@ -123,23 +118,18 @@ func resourceOpensearchComposableIndexTemplateDelete(d *schema.ResourceData, met var openSearchVersion *version.Version providerConf := meta.(*ProviderConf) - esClient, err := getClient(providerConf) + osClient, err := getClient(providerConf) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - openSearchVersion, err = version.NewVersion(providerConf.osVersion) - if err == nil { - if resourceOpensearchComposableIndexTemplateAvailable(openSearchVersion, providerConf) { - err = elastic7DeleteIndexTemplate(client, id) - } else { - err = fmt.Errorf("index_template endpoint only available from server version >= 7.8, got version %s", openSearchVersion.String()) - } + openSearchVersion, err = version.NewVersion(providerConf.osVersion) + if err == nil { + if resourceOpensearchComposableIndexTemplateAvailable(openSearchVersion, providerConf) { + err = elastic7DeleteIndexTemplate(osClient, id) + } else { + err = fmt.Errorf("index_template endpoint only available from server version >= 2.0.0, got version %s", openSearchVersion.String()) } - default: - err = fmt.Errorf("index_template endpoint only available from server version >= 7.8, got version < 7.0.0") } if err != nil { @@ -161,23 +151,18 @@ func resourceOpensearchPutComposableIndexTemplate(d *schema.ResourceData, meta i var openSearchVersion *version.Version providerConf := meta.(*ProviderConf) - esClient, err := getClient(providerConf) + osClient, err := getClient(providerConf) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - openSearchVersion, err = version.NewVersion(providerConf.osVersion) - if err == nil { - if resourceOpensearchComposableIndexTemplateAvailable(openSearchVersion, providerConf) { - err = elastic7PutIndexTemplate(client, name, body, create) - } else { - err = fmt.Errorf("index_template endpoint only available from server version >= 7.8, got version %s", openSearchVersion.String()) - } + openSearchVersion, err = version.NewVersion(providerConf.osVersion) + if err == nil { + if resourceOpensearchComposableIndexTemplateAvailable(openSearchVersion, providerConf) { + err = elastic7PutIndexTemplate(osClient, name, body, create) + } else { + err = fmt.Errorf("index_template endpoint only available from server version >= 2.0.0, got version %s", openSearchVersion.String()) } - default: - err = fmt.Errorf("index_template endpoint only available from server version >= 7.8, got version < 7.0.0") } return err diff --git a/provider/resource_opensearch_composable_index_template_test.go b/provider/resource_opensearch_composable_index_template_test.go index 1cdcdd9..dcdf339 100644 --- a/provider/resource_opensearch_composable_index_template_test.go +++ b/provider/resource_opensearch_composable_index_template_test.go @@ -2,12 +2,9 @@ package provider import ( "context" - "errors" "fmt" "testing" - elastic7 "github.com/olivere/elastic/v7" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) @@ -18,25 +15,13 @@ func TestAccOpensearchComposableIndexTemplate(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - var allowed bool - switch esClient.(type) { - case *elastic7.Client: - allowed = true - default: - allowed = false - } + var allowed bool = true resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) if !allowed { - t.Skip("/_index_template endpoint only supported on ES >= 7.8") + t.Skip("/_index_template endpoint only supported on OS >= 2.0.0") } }, Providers: testAccProviders, @@ -58,25 +43,13 @@ func TestAccOpensearchComposableIndexTemplate_importBasic(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - - var allowed bool - switch esClient.(type) { - case *elastic7.Client: - allowed = true - default: - allowed = false - } + var allowed bool = true resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) if !allowed { - t.Skip("/_index_template endpoint only supported on ES >= 7.8") + t.Skip("/_index_template endpoint only supported on OS >= 2.0.0") } }, Providers: testAccProviders, @@ -106,17 +79,12 @@ func testCheckOpensearchComposableIndexTemplateExists(name string) resource.Test meta := testAccProvider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.IndexGetIndexTemplate(rs.Primary.ID).Do(context.TODO()) - default: - err = errors.New("/_index_template endpoint only supported on ES >= 7.8") - } + _, err = osClient.IndexGetIndexTemplate(rs.Primary.ID).Do(context.TODO()) if err != nil { return err @@ -134,17 +102,12 @@ func testCheckOpensearchComposableIndexTemplateDestroy(s *terraform.State) error meta := testAccProvider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.IndexGetIndexTemplate(rs.Primary.ID).Do(context.TODO()) - default: - err = errors.New("/_index_template endpoint only supported on ES >= 7.8") - } + _, err = osClient.IndexGetIndexTemplate(rs.Primary.ID).Do(context.TODO()) if err != nil { return nil // should be not found error diff --git a/provider/resource_opensearch_dashboard_object.go b/provider/resource_opensearch_dashboard_object.go index 7d35f5d..cc2425a 100644 --- a/provider/resource_opensearch_dashboard_object.go +++ b/provider/resource_opensearch_dashboard_object.go @@ -3,7 +3,6 @@ package provider import ( "context" "encoding/json" - "errors" "fmt" "log" @@ -11,12 +10,11 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" ) func resourceOpensearchDashboardObject() *schema.Resource { return &schema.Resource{ - Description: "Provides an OpenSearch Dashboards object resource. This resource interacts directly with the underlying OpenSearch index backing Dashboards, so the format must match what Dashboards the version of Dashboards is expecting. Dashboards v5 and v6 will export all objects in Dashboards v5 format, so the exported objects cannot be used as a source for `body` in this resource - directly pulling the JSON from a Dashboards index of the same version of OpenSearch targeted by the provider is a workaround.\n\nWith the removal of mapping types in OpenSearch, the Dashboards index changed from v5 to >= v6, previously the document mapping type had the Dashboards object type, however, the `_type` going forward is `doc` and the type is within the document, see below. Using v5 doc types in v6 and above will result in errors from OpenSearch after one or more document types are used.", + Description: "Provides an OpenSearch Dashboards object resource. This resource interacts directly with the underlying OpenSearch index backing Dashboards, so the format must match what Dashboards the version of Dashboards is expecting. Dashboards with older versions - directly pulling the JSON from a Dashboards index of the same version of OpenSearch targeted by the provider is a workaround.", Create: resourceOpensearchDashboardObjectCreate, Read: resourceOpensearchDashboardObjectRead, Update: resourceOpensearchDashboardObjectUpdate, @@ -83,26 +81,17 @@ const ( INDEX_CREATION_FAILED ) -const deprecatedDocType = "doc" - func resourceOpensearchDashboardObjectCreate(d *schema.ResourceData, meta interface{}) error { index := d.Get("index").(string) mapping_index := d.Get("index").(string) var success int var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - success, err = elastic7CreateIndexIfNotExists(client, index, mapping_index) - case *elastic6.Client: - success, err = elastic6CreateIndexIfNotExists(client, index, mapping_index) - default: - return errors.New("opensearch version not supported") - } + success, err = elastic7CreateIndexIfNotExists(osClient, index, mapping_index) if err != nil { log.Printf("[INFO] Failed to create new Dashboard index: %+v", err) @@ -147,26 +136,6 @@ func elastic7CreateIndexIfNotExists(client *elastic7.Client, index string, mappi return INDEX_EXISTS, nil } -func elastic6CreateIndexIfNotExists(client *elastic6.Client, index string, mapping_index string) (int, error) { - log.Printf("[INFO] elastic6CreateIndexIfNotExists") - - // Use the IndexExists service to check if a specified index exists. - exists, err := client.IndexExists(index).Do(context.TODO()) - if err != nil { - return INDEX_CREATION_FAILED, err - } - if !exists { - createIndex, err := client.CreateIndex(mapping_index).Body(`{"mappings":{}}`).Do(context.TODO()) - if createIndex.Acknowledged { - return INDEX_CREATED, err - } else { - return INDEX_CREATION_FAILED, err - } - } - - return INDEX_EXISTS, nil -} - func resourceOpensearchDashboardObjectRead(d *schema.ResourceData, meta interface{}) error { bodyString := d.Get("body").(string) var body []interface{} @@ -179,34 +148,22 @@ func resourceOpensearchDashboardObjectRead(d *schema.ResourceData, meta interfac return fmt.Errorf("expected %v to be an object", body[0]) } id := dashboardObject["_id"].(string) - objectType := objectTypeOrDefault(dashboardObject) index := d.Get("index").(string) var resultJSON []byte var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - var result *elastic7.GetResult - result, err = elastic7GetObject(client, index, id) - if err == nil { - resultJSON, err = json.Marshal(result) - } - case *elastic6.Client: - var result *elastic6.GetResult - result, err = elastic6GetObject(client, objectType, index, id) - if err == nil { - resultJSON, err = json.Marshal(result) - } - default: - return errors.New("opensearch version not supported") + var result *elastic7.GetResult + result, err = elastic7GetObject(osClient, index, id) + if err == nil { + resultJSON, err = json.Marshal(result) } if err != nil { - if elastic7.IsNotFound(err) || elastic6.IsNotFound(err) { + if elastic7.IsNotFound(err) { log.Printf("[WARN] Dashboard Object (%s) not found, removing from state", id) d.SetId("") return nil @@ -229,15 +186,15 @@ func resourceOpensearchDashboardObjectRead(d *schema.ResourceData, meta interfac originalKeys = append(originalKeys, k) } - result := make(map[string]interface{}) - if err := json.Unmarshal(resultJSON, &result); err != nil { + res := make(map[string]interface{}) + if err := json.Unmarshal(resultJSON, &res); err != nil { log.Printf("[WARN] Failed to unmarshal: %+v", resultJSON) return err } stateObject := []map[string]interface{}{make(map[string]interface{})} for _, k := range originalKeys { - stateObject[0][k] = result[k] + stateObject[0][k] = res[k] } state, err := json.Marshal(stateObject) if err != nil { @@ -265,22 +222,14 @@ func resourceOpensearchDashboardObjectDelete(d *schema.ResourceData, meta interf return fmt.Errorf("expected %v to be an object", body[0]) } id := object["_id"].(string) - objectType := objectTypeOrDefault(object) index := d.Get("index").(string) var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - err = elastic7DeleteIndex(client, index, id) - case *elastic6.Client: - err = elastic6DeleteIndex(client, objectType, index, id) - default: - return errors.New("opensearch version not supported") - } + err = elastic7DeleteIndex(osClient, index, id) if err != nil { return err @@ -299,17 +248,6 @@ func elastic7DeleteIndex(client *elastic7.Client, index string, id string) error return err } -func elastic6DeleteIndex(client *elastic6.Client, objectType string, index string, id string) error { - _, err := client.Delete(). - Index(index). - Type(objectType). - Id(id). - Do(context.TODO()) - - // we'll get an error if it's not found: https://github.com/olivere/elastic/blob/v6.1.26/delete.go#L207-L210 - return err -} - func resourceOpensearchPutDashboardObject(d *schema.ResourceData, meta interface{}) (string, error) { bodyString := d.Get("body").(string) var body []interface{} @@ -322,23 +260,15 @@ func resourceOpensearchPutDashboardObject(d *schema.ResourceData, meta interface return "", fmt.Errorf("expected %v to be an object", body[0]) } id := object["_id"].(string) - objectType := objectTypeOrDefault(object) data := object["_source"] index := d.Get("index").(string) var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return "", err } - switch client := esClient.(type) { - case *elastic7.Client: - err = elastic7PutIndex(client, index, id, data) - case *elastic6.Client: - err = elastic6PutIndex(client, objectType, index, id, data) - default: - err = errors.New("opensearch version not supported") - } + err = elastic7PutIndex(osClient, index, id, data) if err != nil { return "", err @@ -357,26 +287,6 @@ func elastic7PutIndex(client *elastic7.Client, index string, id string, data int return err } -func elastic6PutIndex(client *elastic6.Client, objectType string, index string, id string, data interface{}) error { - _, err := client.Index(). - Index(index). - Type(objectType). - Id(id). - BodyJson(&data). - Do(context.TODO()) - - return err -} - -// objectType is deprecated -func objectTypeOrDefault(document map[string]interface{}) string { - if document["_type"] != nil { - return document["_type"].(string) - } - - return deprecatedDocType -} - func requiredDashboardObjectKeys() []string { return []string{"_source", "_id"} } diff --git a/provider/resource_opensearch_dashboard_object_test.go b/provider/resource_opensearch_dashboard_object_test.go index ecebb8d..e933e92 100644 --- a/provider/resource_opensearch_dashboard_object_test.go +++ b/provider/resource_opensearch_dashboard_object_test.go @@ -2,7 +2,6 @@ package provider import ( "context" - "errors" "fmt" "log" "regexp" @@ -24,22 +23,8 @@ func TestAccOpensearchDashboardObject(t *testing.T) { var visualizationConfig string var indexPatternConfig string - meta := provider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - switch esClient.(type) { - case *elastic7.Client: - visualizationConfig = testAccOpensearch7DashboardVisualization - indexPatternConfig = testAccOpensearch7DashboardIndexPattern - case *elastic6.Client: - visualizationConfig = testAccOpensearch6DashboardVisualization - indexPatternConfig = testAccOpensearch6DashboardIndexPattern - default: - visualizationConfig = testAccOpensearchDashboardVisualization - indexPatternConfig = testAccOpensearchDashboardIndexPattern - } + visualizationConfig = testAccOpensearch7DashboardVisualization + indexPatternConfig = testAccOpensearch7DashboardIndexPattern resource.Test(t, resource.TestCase{ Providers: testAccProviders, @@ -86,25 +71,13 @@ func TestAccOpensearchDashboardObject_Rejected(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - var allowed bool - - switch esClient.(type) { - case *elastic6.Client: - allowed = true - default: - allowed = false - } + var allowed bool = false resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) if !allowed { - t.Skip("Only >= ES 6 has index type restrictions") + t.Skip("Only >= OS 2.0.0 has index type restrictions") } }, Providers: testAccProviders, @@ -131,18 +104,11 @@ func testCheckOpensearchDashboardObjectExists(name string, objectType string, id meta := testAccProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.Get().Index(".kibana").Id(id).Do(context.TODO()) - case *elastic6.Client: - _, err = client.Get().Index(".kibana").Type(deprecatedDocType).Id(id).Do(context.TODO()) - default: - return errors.New("opensearch version not supported") - } + _, err = osClient.Get().Index(".kibana").Id(id).Do(context.TODO()) if err != nil { log.Printf("[INFO] testCheckOpensearchDashboardObjectExists: %+v", err) @@ -162,18 +128,11 @@ func testCheckOpensearchDashboardObjectDestroy(s *terraform.State) error { meta := testAccProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.Get().Index(".kibana").Id("response-time-percentile").Do(context.TODO()) - case *elastic6.Client: - _, err = client.Get().Index(".kibana").Type("visualization").Id("response-time-percentile").Do(context.TODO()) - default: - return errors.New("opensearch version not supported") - } + _, err = osClient.Get().Index(".kibana").Id("response-time-percentile").Do(context.TODO()) if err != nil { if elastic7.IsNotFound(err) || elastic6.IsNotFound(err) { @@ -190,55 +149,6 @@ func testCheckOpensearchDashboardObjectDestroy(s *terraform.State) error { return nil } -var testAccOpensearchDashboardVisualization = ` -resource "opensearch_dashboard_object" "test_visualization" { - body = <= 7.9, got version %s", openSearchVersion.String()) - } + openSearchVersion, err = version.NewVersion(providerConf.osVersion) + if err == nil { + if resourceOpensearchDataStreamAvailable(openSearchVersion, providerConf) { + err = elastic7GetDataStream(osClient, id) + } else { + err = fmt.Errorf("_data_stream endpoint only available from server version >= 2.0.0, got version %s", openSearchVersion.String()) } - default: - err = fmt.Errorf("_data_stream endpoint only available from server version >= 7.9, got version < 7.0.0") } if err != nil { if elastic7.IsNotFound(err) { @@ -93,23 +88,18 @@ func resourceOpensearchDataStreamDelete(d *schema.ResourceData, meta interface{} var openSearchVersion *version.Version providerConf := meta.(*ProviderConf) - esClient, err := getClient(providerConf) + osClient, err := getClient(providerConf) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - openSearchVersion, err = version.NewVersion(providerConf.osVersion) - if err == nil { - if resourceOpensearchDataStreamAvailable(openSearchVersion, providerConf) { - err = elastic7DeleteDataStream(client, id) - } else { - err = fmt.Errorf("_data_stream endpoint only available from server version >= 7.9, got version %s", openSearchVersion.String()) - } + openSearchVersion, err = version.NewVersion(providerConf.osVersion) + if err == nil { + if resourceOpensearchDataStreamAvailable(openSearchVersion, providerConf) { + err = elastic7DeleteDataStream(osClient, id) + } else { + err = fmt.Errorf("_data_stream endpoint only available from server version >= 2.0.0, got version %s", openSearchVersion.String()) } - default: - err = fmt.Errorf("_data_stream endpoint only available from server version >= 7.9, got version < 7.0.0") } if err != nil { @@ -125,23 +115,18 @@ func resourceOpensearchPutDataStream(d *schema.ResourceData, meta interface{}) e var openSearchVersion *version.Version providerConf := meta.(*ProviderConf) - esClient, err := getClient(providerConf) + osClient, err := getClient(providerConf) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - openSearchVersion, err = version.NewVersion(providerConf.osVersion) - if err == nil { - if resourceOpensearchDataStreamAvailable(openSearchVersion, providerConf) { - err = elastic7PutDataStream(client, name) - } else { - err = fmt.Errorf("_data_stream endpoint only available from server version >= 7.9, got version %s", openSearchVersion.String()) - } + openSearchVersion, err = version.NewVersion(providerConf.osVersion) + if err == nil { + if resourceOpensearchDataStreamAvailable(openSearchVersion, providerConf) { + err = elastic7PutDataStream(osClient, name) + } else { + err = fmt.Errorf("_data_stream endpoint only available from server version >= 2.0.0, got version %s", openSearchVersion.String()) } - default: - err = fmt.Errorf("_data_stream endpoint only available from server version >= 7.9, got version < 7.0.0") } return err diff --git a/provider/resource_opensearch_data_stream_test.go b/provider/resource_opensearch_data_stream_test.go index 8bf9402..dff9c24 100644 --- a/provider/resource_opensearch_data_stream_test.go +++ b/provider/resource_opensearch_data_stream_test.go @@ -2,12 +2,9 @@ package provider import ( "context" - "errors" "fmt" "testing" - elastic7 "github.com/olivere/elastic/v7" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) @@ -18,27 +15,13 @@ func TestAccOpensearchDataStream(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - - var allowed bool - switch esClient.(type) { - case *elastic7.Client: - allowed = true - default: - allowed = false - } - + var allowed bool = true resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) if !allowed { - t.Skip("/_data_stream endpoint only supported on ES >= 7.9") + t.Skip("/_data_stream endpoint only supported on OS >= 2.0.0") } }, Providers: testAccProviders, @@ -67,16 +50,11 @@ func testCheckOpensearchDataStreamExists(name string) resource.TestCheckFunc { meta := testAccProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - err = elastic7GetDataStream(client, rs.Primary.ID) - default: - return errors.New("opensearch version not supported") - } + err = elastic7GetDataStream(osClient, rs.Primary.ID) if err != nil { return err @@ -95,16 +73,11 @@ func testCheckOpensearchDataStreamDestroy(s *terraform.State) error { meta := testAccProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - err = elastic7GetDataStream(client, rs.Primary.ID) - default: - return errors.New("opensearch version not supported") - } + err = elastic7GetDataStream(osClient, rs.Primary.ID) if err != nil { return nil // should be not found error diff --git a/provider/resource_opensearch_destination.go b/provider/resource_opensearch_destination.go deleted file mode 100644 index caa21bd..0000000 --- a/provider/resource_opensearch_destination.go +++ /dev/null @@ -1,327 +0,0 @@ -package provider - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "log" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - "github.com/olivere/elastic/uritemplates" - - elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" -) - -const DESTINATION_TYPE = "_doc" -const DESTINATION_INDEX = ".opendistro-alerting-config" - -var openDistroDestinationSchema = map[string]*schema.Schema{ - "body": { - Type: schema.TypeString, - Required: true, - DiffSuppressFunc: diffSuppressDestination, - ValidateFunc: validation.StringIsJSON, - StateFunc: func(v interface{}) string { - json, _ := structure.NormalizeJsonString(v) - return json - }, - Description: "The JSON body of the destination.", - }, -} - -func resourceOpenSearchDestination() *schema.Resource { - return &schema.Resource{ - Description: "Provides an OpenSearch destination, a reusable communication channel for an action, such as email, Slack, or a webhook URL. Please refer to the OpenSearch destination documentation for details.", - Create: resourceOpensearchOpenDistroDestinationCreate, - Read: resourceOpensearchOpenDistroDestinationRead, - Update: resourceOpensearchOpenDistroDestinationUpdate, - Delete: resourceOpensearchOpenDistroDestinationDelete, - Schema: openDistroDestinationSchema, - Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - }, - } -} - -func resourceOpensearchOpenDistroDestinationCreate(d *schema.ResourceData, m interface{}) error { - res, err := resourceOpensearchOpenDistroPostDestination(d, m) - - if err != nil { - log.Printf("[INFO] Failed to put destination: %+v", err) - return err - } - - d.SetId(res.ID) - destination, err := json.Marshal(res.Destination) - if err != nil { - return err - } - err = d.Set("body", string(destination)) - return err -} - -func resourceOpensearchOpenDistroDestinationRead(d *schema.ResourceData, m interface{}) error { - destination, err := resourceOpensearchOpenDistroQueryOrGetDestination(d.Id(), m) - - if elastic6.IsNotFound(err) || elastic7.IsNotFound(err) { - log.Printf("[WARN] Destination (%s) not found, removing from state", d.Id()) - d.SetId("") - return nil - } - - if err != nil { - return err - } - - body, err := json.Marshal(destination) - if err != nil { - return err - } - - err = d.Set("body", string(body)) - return err -} - -func resourceOpensearchOpenDistroDestinationUpdate(d *schema.ResourceData, m interface{}) error { - _, err := resourceOpensearchOpenDistroPutDestination(d, m) - - if err != nil { - return err - } - - return resourceOpensearchOpenDistroDestinationRead(d, m) -} - -func resourceOpensearchOpenDistroDestinationDelete(d *schema.ResourceData, m interface{}) error { - var err error - - path, err := uritemplates.Expand("/_opendistro/_alerting/destinations/{id}", map[string]string{ - "id": d.Id(), - }) - if err != nil { - return fmt.Errorf("error building URL path for destination: %+v", err) - } - - esClient, err := getClient(m.(*ProviderConf)) - if err != nil { - return err - } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "DELETE", - Path: path, - }) - case *elastic6.Client: - _, err = client.PerformRequest(context.TODO(), elastic6.PerformRequestOptions{ - Method: "DELETE", - Path: path, - }) - default: - err = errors.New("destination resource not implemented prior to v6") - } - - return err -} - -func resourceOpensearchOpenDistroGetDestination(destinationID string, esClient interface{}) (Destination, error) { - switch client := esClient.(type) { - case *elastic7.Client: - path, err := uritemplates.Expand("/_opendistro/_alerting/destinations/{id}", map[string]string{ - "id": destinationID, - }) - if err != nil { - return Destination{}, fmt.Errorf("error building URL path for destination: %+v", err) - } - - httpResponse, err := client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "GET", - Path: path, - }) - if err != nil { - return Destination{}, err - } - - var drg destinationResponseGet - if err := json.Unmarshal(httpResponse.Body, &drg); err != nil { - return Destination{}, fmt.Errorf("error unmarshalling destination body: %+v", err) - } - // The response structure from the API is the same for the index and get - // endpoints :|, and different from the other endpoints. Normalize the - // response here. - if len(drg.Destinations) > 0 { - return drg.Destinations[0], nil - } else { - return Destination{}, fmt.Errorf("endpoint returned empty set of destinations: %+v", drg) - } - default: - return Destination{}, errors.New("destination get api not implemented prior to ODFE 1.11.0") - } -} - -func resourceOpensearchOpenDistroQueryOrGetDestination(destinationID string, m interface{}) (Destination, error) { - esClient, err := getClient(m.(*ProviderConf)) - if err != nil { - return Destination{}, err - } - - var dr destinationResponse - switch client := esClient.(type) { - case *elastic7.Client: - // See https://github.com/opendistro-for-elasticsearch/alerting/issues/56, - // no API endpoint for retrieving destination prior to ODFE 1.11.0. So do - // a request, if it 404s, fall back to trying to query the index. - destination, err := resourceOpensearchOpenDistroGetDestination(destinationID, client) - if err == nil { - return destination, err - } else { - result, err := elastic7GetObject(client, DESTINATION_INDEX, destinationID) - - if err != nil { - return Destination{}, err - } - if err := json.Unmarshal(result.Source, &dr); err != nil { - return Destination{}, fmt.Errorf("error unmarshalling destination body: %+v: %+v", err, result.Source) - } - return dr.Destination, nil - } - case *elastic6.Client: - result, err := elastic6GetObject(client, DESTINATION_TYPE, DESTINATION_INDEX, destinationID) - if err != nil { - return Destination{}, err - } - if err := json.Unmarshal(*result.Source, &dr); err != nil { - return Destination{}, fmt.Errorf("error unmarshalling destination body: %+v: %+v", err, result.Source) - } - return dr.Destination, nil - default: - return Destination{}, errors.New("destination resource not implemented prior to v6") - } -} - -func resourceOpensearchOpenDistroPostDestination(d *schema.ResourceData, m interface{}) (*destinationResponse, error) { - destinationJSON := d.Get("body").(string) - - var err error - response := new(destinationResponse) - - path := "/_opendistro/_alerting/destinations/" - - var body json.RawMessage - esClient, err := getClient(m.(*ProviderConf)) - if err != nil { - return nil, err - } - switch client := esClient.(type) { - case *elastic7.Client: - var res *elastic7.Response - res, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "POST", - Path: path, - Body: destinationJSON, - }) - if err != nil { - return response, err - } - body = res.Body - case *elastic6.Client: - var res *elastic6.Response - res, err = client.PerformRequest(context.TODO(), elastic6.PerformRequestOptions{ - Method: "POST", - Path: path, - Body: destinationJSON, - }) - if err != nil { - return response, err - } - body = res.Body - default: - return response, errors.New("destination resource not implemented prior to v6") - } - - if err := json.Unmarshal(body, response); err != nil { - return response, fmt.Errorf("error unmarshalling destination body: %+v: %+v", err, body) - } - - return response, nil -} - -func resourceOpensearchOpenDistroPutDestination(d *schema.ResourceData, m interface{}) (*destinationResponse, error) { - destinationJSON := d.Get("body").(string) - - var err error - response := new(destinationResponse) - - path, err := uritemplates.Expand("/_opendistro/_alerting/destinations/{id}", map[string]string{ - "id": d.Id(), - }) - if err != nil { - return response, fmt.Errorf("error building URL path for destination: %+v", err) - } - - var body json.RawMessage - esClient, err := getClient(m.(*ProviderConf)) - if err != nil { - return nil, err - } - switch client := esClient.(type) { - case *elastic7.Client: - var res *elastic7.Response - res, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "PUT", - Path: path, - Body: destinationJSON, - }) - if err != nil { - return response, err - } - body = res.Body - case *elastic6.Client: - var res *elastic6.Response - res, err = client.PerformRequest(context.TODO(), elastic6.PerformRequestOptions{ - Method: "PUT", - Path: path, - Body: destinationJSON, - }) - if err != nil { - return response, err - } - body = res.Body - default: - return response, errors.New("destination resource not implemented prior to v6") - } - - if err := json.Unmarshal(body, response); err != nil { - return response, fmt.Errorf("error unmarshalling destination body: %+v: %+v", err, body) - } - - return response, nil -} - -type destinationResponse struct { - Version int `json:"_version"` - ID string `json:"_id"` - Destination Destination `json:"destination"` -} - -// When this api endpoint was introduced after the other endpoints, it has a -// different response structure -type destinationResponseGet struct { - Total int `json:"totalDestinations"` - Destinations []Destination `json:"destinations"` -} - -type Destination struct { - ID string `json:"id"` - Type string `json:"type"` - Name string `json:"name"` - Slack interface{} `json:"slack,omitempty"` - CustomWebhook interface{} `json:"custom_webhook,omitempty"` - Chime interface{} `json:"chime,omitempty"` - SNS interface{} `json:"sns,omitempty"` - Email interface{} `json:"email,omitempty"` -} diff --git a/provider/resource_opensearch_destination_test.go b/provider/resource_opensearch_destination_test.go deleted file mode 100644 index 81de7eb..0000000 --- a/provider/resource_opensearch_destination_test.go +++ /dev/null @@ -1,118 +0,0 @@ -package provider - -import ( - "fmt" - "testing" - - elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" -) - -func TestAccOpensearchOpenDistroDestination(t *testing.T) { - resource.Test(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, - Providers: testAccOpendistroProviders, - CheckDestroy: testCheckOpensearchDestinationDestroy, - Steps: []resource.TestStep{ - { - Config: testAccOpensearchOpenDistroDestination, - Check: resource.ComposeTestCheckFunc( - testCheckOpensearchDestinationExists("opensearch_destination.test_destination"), - ), - }, - }, - }) -} - -func TestAccOpensearchOpenDistroDestination_importBasic(t *testing.T) { - resource.Test(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, - Providers: testAccOpendistroProviders, - CheckDestroy: testCheckOpensearchDestinationDestroy, - Steps: []resource.TestStep{ - { - Config: testAccOpensearchOpenDistroDestination, - }, - { - ResourceName: "opensearch_destination.test_destination", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testCheckOpensearchDestinationExists(name string) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[name] - if !ok { - return fmt.Errorf("Not found: %s", name) - } - if rs.Primary.ID == "" { - return fmt.Errorf("No destination ID is set") - } - - meta := testAccOpendistroProvider.Meta() - - var err error - _, err = resourceOpensearchOpenDistroQueryOrGetDestination(rs.Primary.ID, meta.(*ProviderConf)) - - if err != nil { - return err - } - - return nil - } -} - -func testCheckOpensearchDestinationDestroy(s *terraform.State) error { - for _, rs := range s.RootModule().Resources { - if rs.Type != "opensearch_destination" { - continue - } - - meta := testAccOpendistroProvider.Meta() - - var err error - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - return err - } - switch esClient.(type) { - case *elastic7.Client: - _, err = resourceOpensearchOpenDistroQueryOrGetDestination(rs.Primary.ID, meta.(*ProviderConf)) - case *elastic6.Client: - _, err = resourceOpensearchOpenDistroQueryOrGetDestination(rs.Primary.ID, meta.(*ProviderConf)) - default: - } - - if err != nil { - return nil // should be not found error - } - - return fmt.Errorf("Destination %q still exists", rs.Primary.ID) - } - - return nil -} - -var testAccOpensearchOpenDistroDestination = ` -resource "opensearch_destination" "test_destination" { - body = < 0 { + return fmt.Errorf("rollover alias %q still exists", alias) + } + + return nil + } +} + func TestAccOpensearchIndexAnalysis(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -358,21 +442,7 @@ func TestAccOpensearchIndex_doctype(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - var config string - - switch esClient.(type) { - case *elastic7.Client: - config = testAccOpensearchMappingWithDocType - case *elastic6.Client: - config = testAccOpensearchMappingWithoutDocType - default: - t.Skipf("doctypes removed after v6/v7") - } + var config string = testAccOpensearchMappingWithDocType resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -389,56 +459,6 @@ func TestAccOpensearchIndex_doctype(t *testing.T) { }) } -func TestAccOpensearchIndex_rolloverAliasOpendistro(t *testing.T) { - provider := Provider() - diags := provider.Configure(context.Background(), &terraform.ResourceConfig{}) - if diags.HasError() { - t.Skipf("err: %#v", diags) - } - meta := provider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - var allowed bool - - switch esClient.(type) { - case *elastic6.Client: - allowed = false - default: - allowed = true - } - - resource.Test(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - if !allowed { - t.Skip("Opendistro index policies only supported on ES 7") - } - }, - Providers: testAccOpendistroProviders, - CheckDestroy: checkOpensearchIndexRolloverAliasDestroy(testAccOpendistroProvider, "terraform-test"), - Steps: []resource.TestStep{ - { - Config: testAccOpensearchIndexRolloverAliasOpendistro, - Check: resource.ComposeTestCheckFunc( - checkOpensearchIndexRolloverAliasExists(testAccOpendistroProvider, "terraform-test"), - ), - }, - { - ResourceName: "opensearch_index.test", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "aliases", // not handled by this provider - "force_destroy", // not returned from the API - }, - ImportStateCheck: checkOpensearchIndexRolloverAliasState("terraform-test"), - }, - }, - }) -} - func checkOpensearchIndexExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[name] @@ -452,18 +472,11 @@ func checkOpensearchIndexExists(name string) resource.TestCheckFunc { meta := testAccProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.IndexGetSettings(rs.Primary.ID).Do(context.TODO()) - case *elastic6.Client: - _, err = client.IndexGetSettings(rs.Primary.ID).Do(context.TODO()) - default: - return errors.New("opensearch version not supported") - } + _, err = osClient.IndexGetSettings(rs.Primary.ID).Do(context.TODO()) return err } @@ -483,28 +496,15 @@ func checkOpensearchIndexUpdated(name string) resource.TestCheckFunc { var settings map[string]interface{} var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - resp, err := client.IndexGetSettings(rs.Primary.ID).Do(context.TODO()) - if err != nil { - return err - } - settings = resp[rs.Primary.ID].Settings["index"].(map[string]interface{}) - - case *elastic6.Client: - resp, err := client.IndexGetSettings(rs.Primary.ID).Do(context.TODO()) - if err != nil { - return err - } - settings = resp[rs.Primary.ID].Settings["index"].(map[string]interface{}) - - default: - return errors.New("opensearch version not supported") + resp, err := osClient.IndexGetSettings(rs.Primary.ID).Do(context.TODO()) + if err != nil { + return err } + settings = resp[rs.Primary.ID].Settings["index"].(map[string]interface{}) r, ok := settings["number_of_replicas"] if ok { @@ -527,18 +527,11 @@ func checkOpensearchIndexDestroy(s *terraform.State) error { meta := testAccProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.IndexGetSettings(rs.Primary.ID).Do(context.TODO()) - case *elastic6.Client: - _, err = client.IndexGetSettings(rs.Primary.ID).Do(context.TODO()) - default: - return errors.New("opensearch version not supported") - } + _, err = osClient.IndexGetSettings(rs.Primary.ID).Do(context.TODO()) if err != nil { return nil // should be not found error @@ -549,85 +542,3 @@ func checkOpensearchIndexDestroy(s *terraform.State) error { return nil } - -func checkOpensearchIndexRolloverAliasExists(provider *schema.Provider, alias string) resource.TestCheckFunc { - return func(s *terraform.State) error { - meta := provider.Meta() - - var count int - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - return err - } - switch client := esClient.(type) { - case *elastic7.Client: - r, err := client.CatAliases().Alias(alias).Do(context.TODO()) - if err != nil { - return err - } - count = len(r) - case *elastic6.Client: - r, err := client.CatAliases().Alias(alias).Do(context.TODO()) - if err != nil { - return err - } - count = len(r) - default: - return errors.New("opensearch version not supported") - } - - if count == 0 { - return fmt.Errorf("rollover alias %q not found", alias) - } - - return nil - } -} - -func checkOpensearchIndexRolloverAliasState(alias string) resource.ImportStateCheckFunc { - return func(s []*terraform.InstanceState) error { - if len(s) != 1 { - return fmt.Errorf("expected 1 state: %+v", s) - } - rs := s[0] - if rs.Attributes["rollover_alias"] != alias { - return fmt.Errorf("expected rollover alias %q got %q", alias, rs.Attributes["rollover_alias"]) - } - - return nil - } -} - -func checkOpensearchIndexRolloverAliasDestroy(provider *schema.Provider, alias string) resource.TestCheckFunc { - return func(s *terraform.State) error { - meta := provider.Meta() - - var count int - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - return err - } - switch client := esClient.(type) { - case *elastic7.Client: - r, err := client.CatAliases().Alias(alias).Do(context.TODO()) - if err != nil { - return err - } - count = len(r) - case *elastic6.Client: - r, err := client.CatAliases().Alias(alias).Do(context.TODO()) - if err != nil { - return err - } - count = len(r) - default: - return errors.New("opensearch version not supported") - } - - if count > 0 { - return fmt.Errorf("rollover alias %q still exists", alias) - } - - return nil - } -} diff --git a/provider/resource_opensearch_ingest_pipeline.go b/provider/resource_opensearch_ingest_pipeline.go index 80de767..65ae897 100644 --- a/provider/resource_opensearch_ingest_pipeline.go +++ b/provider/resource_opensearch_ingest_pipeline.go @@ -3,12 +3,10 @@ package provider import ( "context" "encoding/json" - "errors" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" ) func resourceOpensearchIngestPipeline() *schema.Resource { @@ -54,18 +52,11 @@ func resourceOpensearchIngestPipelineRead(d *schema.ResourceData, meta interface var result string var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - result, err = elastic7IngestGetPipeline(client, id) - case *elastic6.Client: - result, err = elastic6IngestGetPipeline(client, id) - default: - return errors.New("opensearch version not supported") - } + result, err = elastic7IngestGetPipeline(osClient, id) if err != nil { return err } @@ -93,20 +84,6 @@ func elastic7IngestGetPipeline(client *elastic7.Client, id string) (string, erro return string(tj), nil } -func elastic6IngestGetPipeline(client *elastic6.Client, id string) (string, error) { - res, err := client.IngestGetPipeline(id).Do(context.TODO()) - if err != nil { - return "", err - } - - t := res[id] - tj, err := json.Marshal(t) - if err != nil { - return "", err - } - return string(tj), nil -} - func resourceOpensearchIngestPipelineUpdate(d *schema.ResourceData, meta interface{}) error { return resourceOpensearchPutIngestPipeline(d, meta) } @@ -115,18 +92,11 @@ func resourceOpensearchIngestPipelineDelete(d *schema.ResourceData, meta interfa id := d.Id() var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.IngestDeletePipeline(id).Do(context.TODO()) - case *elastic6.Client: - _, err = client.IngestDeletePipeline(id).Do(context.TODO()) - default: - return errors.New("opensearch version not supported") - } + _, err = osClient.IngestDeletePipeline(id).Do(context.TODO()) if err != nil { return err @@ -140,18 +110,11 @@ func resourceOpensearchPutIngestPipeline(d *schema.ResourceData, meta interface{ body := d.Get("body").(string) var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.IngestPutPipeline(name).BodyString(body).Do(context.TODO()) - case *elastic6.Client: - _, err = client.IngestPutPipeline(name).BodyString(body).Do(context.TODO()) - default: - return errors.New("opensearch version not supported") - } + _, err = osClient.IngestPutPipeline(name).BodyString(body).Do(context.TODO()) return err } diff --git a/provider/resource_opensearch_ingest_pipeline_test.go b/provider/resource_opensearch_ingest_pipeline_test.go index 5cbea6a..fa47a83 100644 --- a/provider/resource_opensearch_ingest_pipeline_test.go +++ b/provider/resource_opensearch_ingest_pipeline_test.go @@ -2,13 +2,9 @@ package provider import ( "context" - "errors" "fmt" "testing" - elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) @@ -19,21 +15,8 @@ func TestAccOpensearchIngestPipeline(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - var config string - - switch esClient.(type) { - case *elastic7.Client: - config = testAccOpensearchIngestPipelineV7 - case *elastic6.Client: - config = testAccOpensearchIngestPipelineV6 - default: - config = testAccOpensearchIngestPipelineV5 - } + config := testAccOpensearchIngestPipelineV7 + resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) @@ -57,20 +40,8 @@ func TestAccOpensearchIngestPipeline_importBasic(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - var config string - switch esClient.(type) { - case *elastic7.Client: - config = testAccOpensearchIngestPipelineV7 - case *elastic6.Client: - config = testAccOpensearchIngestPipelineV6 - default: - config = testAccOpensearchIngestPipelineV5 - } + + config := testAccOpensearchIngestPipelineV7 resource.Test(t, resource.TestCase{ PreCheck: func() { @@ -104,18 +75,11 @@ func testCheckOpensearchIngestPipelineExists(name string) resource.TestCheckFunc meta := testAccProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) + client, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.IngestGetPipeline(rs.Primary.ID).Do(context.TODO()) - case *elastic6.Client: - _, err = client.IngestGetPipeline(rs.Primary.ID).Do(context.TODO()) - default: - return errors.New("opensearch version not supported") - } + _, err = client.IngestGetPipeline(rs.Primary.ID).Do(context.TODO()) if err != nil { return err @@ -134,18 +98,11 @@ func testCheckOpensearchIngestPipelineDestroy(s *terraform.State) error { meta := testAccProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) + client, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.IngestGetPipeline(rs.Primary.ID).Do(context.TODO()) - case *elastic6.Client: - _, err = client.IngestGetPipeline(rs.Primary.ID).Do(context.TODO()) - default: - return errors.New("opensearch version not supported") - } + _, err = client.IngestGetPipeline(rs.Primary.ID).Do(context.TODO()) if err != nil { return nil // should be not found error @@ -157,45 +114,6 @@ func testCheckOpensearchIngestPipelineDestroy(s *terraform.State) error { return nil } -var testAccOpensearchIngestPipelineV5 = ` -resource "opensearch_ingest_pipeline" "test" { - name = "terraform-test" - body = <= 7") - } }, Providers: testAccOpendistroProviders, CheckDestroy: testAccCheckOpensearchRoleDestroy, @@ -125,27 +107,12 @@ func TestAccOpensearchOpenDistroRole_importBasic(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - var allowed bool - switch esClient.(type) { - case *elastic6.Client: - allowed = false - default: - allowed = true - } randomName := "test" + acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) - if !allowed { - t.Skip("Roles only supported on ES >= 7") - } }, Providers: testAccOpendistroProviders, CheckDestroy: testAccCheckOpensearchRoleDestroy, @@ -171,15 +138,10 @@ func testAccCheckOpensearchRoleDestroy(s *terraform.State) error { meta := testAccOpendistroProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch esClient.(type) { - case *elastic7.Client: - _, err = resourceOpensearchGetOpenDistroRole(rs.Primary.ID, meta.(*ProviderConf)) - default: - } + _, err = resourceOpensearchGetOpenDistroRole(rs.Primary.ID, meta.(*ProviderConf)) if err != nil { return nil // should be not found error @@ -200,15 +162,10 @@ func testCheckOpensearchRoleExists(name string) resource.TestCheckFunc { meta := testAccOpendistroProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch esClient.(type) { - case *elastic7.Client: - _, err = resourceOpensearchGetOpenDistroRole(rs.Primary.ID, meta.(*ProviderConf)) - default: - } + _, err = resourceOpensearchGetOpenDistroRole(rs.Primary.ID, meta.(*ProviderConf)) if err != nil { return err diff --git a/provider/resource_opensearch_roles_mapping.go b/provider/resource_opensearch_roles_mapping.go index 12e8e02..8753419 100644 --- a/provider/resource_opensearch_roles_mapping.go +++ b/provider/resource_opensearch_roles_mapping.go @@ -3,7 +3,6 @@ package provider import ( "context" "encoding/json" - "errors" "fmt" "log" "net/http" @@ -121,30 +120,25 @@ func resourceOpensearchOpenDistroRolesMappingUpdate(d *schema.ResourceData, m in } func resourceOpensearchOpenDistroRolesMappingDelete(d *schema.ResourceData, m interface{}) error { - path, err := uritemplates.Expand("/_opendistro/_security/api/rolesmapping/{name}", map[string]string{ + path, err := uritemplates.Expand("/_plugins/_security/api/rolesmapping/{name}", map[string]string{ "name": d.Get("role_name").(string), }) if err != nil { return fmt.Errorf("error building URL path for role mapping: %+v", err) } - esClient, err := getClient(m.(*ProviderConf)) + osClient, err := getClient(m.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "DELETE", - Path: path, - RetryStatusCodes: []int{http.StatusConflict, http.StatusInternalServerError}, - Retrier: elastic7.NewBackoffRetrier( - elastic7.NewExponentialBackoff(100*time.Millisecond, 30*time.Second), - ), - }) - default: - err = errors.New("role mapping resource not implemented prior to v7") - } + _, err = osClient.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ + Method: "DELETE", + Path: path, + RetryStatusCodes: []int{http.StatusConflict, http.StatusInternalServerError}, + Retrier: elastic7.NewBackoffRetrier( + elastic7.NewExponentialBackoff(100*time.Millisecond, 30*time.Second), + ), + }) return err } @@ -153,7 +147,7 @@ func resourceOpensearchGetOpenDistroRolesMapping(roleID string, m interface{}) ( var err error var roleMapping = new(RolesMapping) - path, err := uritemplates.Expand("/_opendistro/_security/api/rolesmapping/{name}", map[string]string{ + path, err := uritemplates.Expand("/_plugins/_security/api/rolesmapping/{name}", map[string]string{ "name": roleID, }) @@ -161,24 +155,19 @@ func resourceOpensearchGetOpenDistroRolesMapping(roleID string, m interface{}) ( return *roleMapping, fmt.Errorf("error building URL path for role mapping: %+v", err) } var body json.RawMessage - esClient, err := getClient(m.(*ProviderConf)) + osClient, err := getClient(m.(*ProviderConf)) if err != nil { return *roleMapping, err } - switch client := esClient.(type) { - case *elastic7.Client: - var res *elastic7.Response - res, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "GET", - Path: path, - }) - if err != nil { - return *roleMapping, err - } - body = res.Body - default: - err = errors.New("role mapping resource not implemented prior to v7") + var res *elastic7.Response + res, err = osClient.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ + Method: "GET", + Path: path, + }) + if err != nil { + return *roleMapping, err } + body = res.Body if err != nil { return *roleMapping, err @@ -211,7 +200,7 @@ func resourceOpensearchPutOpenDistroRolesMapping(d *schema.ResourceData, m inter return response, fmt.Errorf("Body Error : %s", roleJSON) } - path, err := uritemplates.Expand("/_opendistro/_security/api/rolesmapping/{name}", map[string]string{ + path, err := uritemplates.Expand("/_plugins/_security/api/rolesmapping/{name}", map[string]string{ "name": d.Get("role_name").(string), }) @@ -220,34 +209,29 @@ func resourceOpensearchPutOpenDistroRolesMapping(d *schema.ResourceData, m inter } var body json.RawMessage - esClient, err := getClient(m.(*ProviderConf)) + osClient, err := getClient(m.(*ProviderConf)) if err != nil { return nil, err } - switch client := esClient.(type) { - case *elastic7.Client: - var res *elastic7.Response - res, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "PUT", - Path: path, - Body: string(roleJSON), - // see https://github.com/opendistro-for- - // elasticsearch/security/issues/1095, this should return a 409, but - // retry on the 500 as well. We can't parse the message to only retry on - // the conlict exception becaues the client doesn't directly - // expose the error response body - RetryStatusCodes: []int{http.StatusConflict, http.StatusInternalServerError}, - Retrier: elastic7.NewBackoffRetrier( - elastic7.NewExponentialBackoff(100*time.Millisecond, 30*time.Second), - ), - }) - if err != nil { - return response, err - } - body = res.Body - default: - return response, errors.New("role mapping resource not implemented prior to v7") + var res *elastic7.Response + res, err = osClient.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ + Method: "PUT", + Path: path, + Body: string(roleJSON), + // see https://github.com/opendistro-for- + // elasticsearch/security/issues/1095, this should return a 409, but + // retry on the 500 as well. We can't parse the message to only retry on + // the conlict exception becaues the client doesn't directly + // expose the error response body + RetryStatusCodes: []int{http.StatusConflict, http.StatusInternalServerError}, + Retrier: elastic7.NewBackoffRetrier( + elastic7.NewExponentialBackoff(100*time.Millisecond, 30*time.Second), + ), + }) + if err != nil { + return response, err } + body = res.Body if err := json.Unmarshal(body, response); err != nil { return response, fmt.Errorf("error unmarshalling role mapping body: %+v: %+v", err, body) diff --git a/provider/resource_opensearch_roles_mapping_test.go b/provider/resource_opensearch_roles_mapping_test.go index 977504f..06aa464 100644 --- a/provider/resource_opensearch_roles_mapping_test.go +++ b/provider/resource_opensearch_roles_mapping_test.go @@ -5,9 +5,6 @@ import ( "fmt" "testing" - elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" @@ -19,27 +16,12 @@ func TestAccOpensearchOpenDistroRolesMapping(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - var allowed bool - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - switch esClient.(type) { - case *elastic6.Client: - allowed = false - default: - allowed = true - } randomName := "test" + acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) - if !allowed { - t.Skip("Roles only supported on ES >= 7") - } }, Providers: testAccOpendistroProviders, CheckDestroy: testAccCheckOpensearchRolesMappingDestroy, @@ -89,16 +71,7 @@ func testAccCheckOpensearchRolesMappingDestroy(s *terraform.State) error { meta := testAccOpendistroProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - return err - } - switch esClient.(type) { - case *elastic7.Client: - _, err = resourceOpensearchGetOpenDistroRolesMapping(rs.Primary.ID, meta.(*ProviderConf)) - default: - } - + _, err = resourceOpensearchGetOpenDistroRolesMapping(rs.Primary.ID, meta.(*ProviderConf)) if err != nil { return nil // should be not found error } @@ -116,18 +89,8 @@ func testCheckOpensearchRolesMappingExists(name string) resource.TestCheckFunc { } meta := testAccOpendistroProvider.Meta() - var err error - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - return err - } - switch esClient.(type) { - case *elastic7.Client: - _, err = resourceOpensearchGetOpenDistroRolesMapping(rs.Primary.ID, meta.(*ProviderConf)) - default: - } - + _, err = resourceOpensearchGetOpenDistroRolesMapping(rs.Primary.ID, meta.(*ProviderConf)) if err != nil { return err } diff --git a/provider/resource_opensearch_script.go b/provider/resource_opensearch_script.go index 1ac54ad..e0159e6 100644 --- a/provider/resource_opensearch_script.go +++ b/provider/resource_opensearch_script.go @@ -3,14 +3,12 @@ package provider import ( "context" "encoding/json" - "errors" "fmt" "log" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" ) var scriptSchema = map[string]*schema.Schema{ @@ -74,7 +72,7 @@ func resourceOpensearchScriptCreate(d *schema.ResourceData, m interface{}) error if err == nil { log.Printf("[INFO] script exists: %+v", err) return fmt.Errorf("script already exists with ID: %v", scriptID) - } else if err != nil && !elastic6.IsNotFound(err) && !elastic7.IsNotFound(err) { + } else if err != nil && !elastic7.IsNotFound(err) { return err } @@ -94,7 +92,7 @@ func resourceOpensearchScriptCreate(d *schema.ResourceData, m interface{}) error func resourceOpensearchScriptRead(d *schema.ResourceData, m interface{}) error { scriptBody, err := resourceOpensearchGetScript(d.Id(), m) - if elastic6.IsNotFound(err) || elastic7.IsNotFound(err) { + if elastic7.IsNotFound(err) { log.Printf("[WARN] Script (%s) not found, removing from state", d.Id()) d.SetId("") return nil @@ -124,18 +122,11 @@ func resourceOpensearchScriptUpdate(d *schema.ResourceData, m interface{}) error func resourceOpensearchScriptDelete(d *schema.ResourceData, m interface{}) error { var err error - esClient, err := getClient(m.(*ProviderConf)) + osClient, err := getClient(m.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.DeleteScript().Id(d.Id()).Do(context.TODO()) - case *elastic6.Client: - _, err = client.DeleteScript().Id(d.Id()).Do(context.TODO()) - default: - err = errors.New("script resource not implemented prior to Elastic v6") - } + _, err = osClient.DeleteScript().Id(d.Id()).Do(context.TODO()) return err } @@ -143,28 +134,16 @@ func resourceOpensearchScriptDelete(d *schema.ResourceData, m interface{}) error func resourceOpensearchGetScript(scriptID string, m interface{}) (ScriptBody, error) { var scriptBody json.RawMessage var err error - esClient, err := getClient(m.(*ProviderConf)) + osClient, err := getClient(m.(*ProviderConf)) if err != nil { return ScriptBody{}, err } - switch client := esClient.(type) { - case *elastic7.Client: - var res *elastic7.GetScriptResponse - res, err = client.GetScript().Id(scriptID).Do(context.TODO()) - if err != nil { - return ScriptBody{}, err - } - scriptBody = res.Script - case *elastic6.Client: - var res *elastic6.GetScriptResponse - res, err = client.GetScript().Id(scriptID).Do(context.TODO()) - if err != nil { - return ScriptBody{}, err - } - scriptBody = res.Script - default: - err = errors.New("script resource not implemented prior to v6") + var res *elastic7.GetScriptResponse + res, err = osClient.GetScript().Id(scriptID).Do(context.TODO()) + if err != nil { + return ScriptBody{}, err } + scriptBody = res.Script var script ScriptBody @@ -184,24 +163,14 @@ func resourceOpensearchPutScript(d *schema.ResourceData, m interface{}) (string, return "", err } - esClient, err := getClient(m.(*ProviderConf)) + osClient, err := getClient(m.(*ProviderConf)) if err != nil { return "", err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.PutScript(). - Id(scriptID). - BodyJson(scriptBody). - Do(context.TODO()) - case *elastic6.Client: - _, err = client.PutScript(). - Id(scriptID). - BodyJson(scriptBody). - Do(context.TODO()) - default: - err = errors.New("script resource not implemented prior to v6") - } + _, err = osClient.PutScript(). + Id(scriptID). + BodyJson(scriptBody). + Do(context.TODO()) if err != nil { return "", err diff --git a/provider/resource_opensearch_script_test.go b/provider/resource_opensearch_script_test.go index 99e89bb..f62d767 100644 --- a/provider/resource_opensearch_script_test.go +++ b/provider/resource_opensearch_script_test.go @@ -5,9 +5,6 @@ import ( "fmt" "testing" - elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) @@ -43,17 +40,11 @@ func testCheckOpensearchScriptExists(name string) resource.TestCheckFunc { meta := testAccProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) + client, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.GetScript().Id("my_script").Do(context.TODO()) - case *elastic6.Client: - _, err = client.GetScript().Id("my_script").Do(context.TODO()) - default: - } + _, err = client.GetScript().Id("my_script").Do(context.TODO()) if err != nil { return err @@ -72,17 +63,11 @@ func testCheckOpensearchScriptDestroy(s *terraform.State) error { meta := testAccProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) + client, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.GetScript().Id("my_script").Do(context.TODO()) - case *elastic6.Client: - _, err = client.GetScript().Id("my_script").Do(context.TODO()) - default: - } + _, err = client.GetScript().Id("my_script").Do(context.TODO()) if err != nil { return nil // should be not found error diff --git a/provider/resource_opensearch_snapshot_repository.go b/provider/resource_opensearch_snapshot_repository.go index 7ee76d7..80dc7ea 100644 --- a/provider/resource_opensearch_snapshot_repository.go +++ b/provider/resource_opensearch_snapshot_repository.go @@ -2,11 +2,9 @@ package provider import ( "context" - "errors" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" ) func resourceOpensearchSnapshotRepository() *schema.Resource { @@ -55,18 +53,11 @@ func resourceOpensearchSnapshotRepositoryRead(d *schema.ResourceData, meta inter var repositoryType string var settings map[string]interface{} var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - repositoryType, settings, err = elastic7SnapshotGetRepository(client, id) - case *elastic6.Client: - repositoryType, settings, err = elastic6SnapshotGetRepository(client, id) - default: - return errors.New("opensearch version not supported") - } + repositoryType, settings, err = elastic7SnapshotGetRepository(osClient, id) if err != nil { return err @@ -88,15 +79,6 @@ func elastic7SnapshotGetRepository(client *elastic7.Client, id string) (string, return repos[id].Type, repos[id].Settings, nil } -func elastic6SnapshotGetRepository(client *elastic6.Client, id string) (string, map[string]interface{}, error) { - repos, err := client.SnapshotGetRepository(id).Do(context.TODO()) - if err != nil { - return "", make(map[string]interface{}), err - } - - return repos[id].Type, repos[id].Settings, nil -} - func resourceOpensearchSnapshotRepositoryUpdate(d *schema.ResourceData, meta interface{}) error { repositoryType := d.Get("type").(string) name := d.Get("name").(string) @@ -108,23 +90,16 @@ func resourceOpensearchSnapshotRepositoryUpdate(d *schema.ResourceData, meta int } var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - err = elastic7SnapshotCreateRepository(client, name, repositoryType, settings) - case *elastic6.Client: - err = elastic6SnapshotCreateRepository(client, name, repositoryType, settings) - default: - return errors.New("opensearch version not supported") - } + err = os7SnapshotCreateRepository(osClient, name, repositoryType, settings) return err } -func elastic7SnapshotCreateRepository(client *elastic7.Client, name string, repositoryType string, settings map[string]interface{}) error { +func os7SnapshotCreateRepository(client *elastic7.Client, name string, repositoryType string, settings map[string]interface{}) error { repo := elastic7.SnapshotRepositoryMetaData{ Type: repositoryType, Settings: settings, @@ -134,32 +109,15 @@ func elastic7SnapshotCreateRepository(client *elastic7.Client, name string, repo return err } -func elastic6SnapshotCreateRepository(client *elastic6.Client, name string, repositoryType string, settings map[string]interface{}) error { - repo := elastic6.SnapshotRepositoryMetaData{ - Type: repositoryType, - Settings: settings, - } - - _, err := client.SnapshotCreateRepository(name).BodyJson(&repo).Do(context.TODO()) - return err -} - func resourceOpensearchSnapshotRepositoryDelete(d *schema.ResourceData, meta interface{}) error { id := d.Id() var err error - esClient, err := getClient(meta.(*ProviderConf)) + osClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - err = elastic7SnapshotDeleteRepository(client, id) - case *elastic6.Client: - err = elastic6SnapshotDeleteRepository(client, id) - default: - return errors.New("opensearch version not supported") - } + err = os7SnapshotDeleteRepository(osClient, id) if err != nil { return err @@ -168,12 +126,7 @@ func resourceOpensearchSnapshotRepositoryDelete(d *schema.ResourceData, meta int return nil } -func elastic7SnapshotDeleteRepository(client *elastic7.Client, id string) error { - _, err := client.SnapshotDeleteRepository(id).Do(context.TODO()) - return err -} - -func elastic6SnapshotDeleteRepository(client *elastic6.Client, id string) error { +func os7SnapshotDeleteRepository(client *elastic7.Client, id string) error { _, err := client.SnapshotDeleteRepository(id).Do(context.TODO()) return err } diff --git a/provider/resource_opensearch_snapshot_repository_test.go b/provider/resource_opensearch_snapshot_repository_test.go index e149b71..fe99d06 100644 --- a/provider/resource_opensearch_snapshot_repository_test.go +++ b/provider/resource_opensearch_snapshot_repository_test.go @@ -2,13 +2,9 @@ package provider import ( "context" - "errors" "fmt" "testing" - elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) @@ -60,18 +56,11 @@ func testCheckOpensearchSnapshotRepositoryExists(name string) resource.TestCheck meta := testAccProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) + client, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.SnapshotGetRepository(rs.Primary.ID).Do(context.TODO()) - case *elastic6.Client: - _, err = client.SnapshotGetRepository(rs.Primary.ID).Do(context.TODO()) - default: - return errors.New("opensearch version not supported") - } + _, err = client.SnapshotGetRepository(rs.Primary.ID).Do(context.TODO()) if err != nil { return err @@ -90,18 +79,11 @@ func testCheckOpensearchSnapshotRepositoryDestroy(s *terraform.State) error { meta := testAccProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) + client, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.SnapshotGetRepository(rs.Primary.ID).Do(context.TODO()) - case *elastic6.Client: - _, err = client.SnapshotGetRepository(rs.Primary.ID).Do(context.TODO()) - default: - return errors.New("opensearch version not supported") - } + _, err = client.SnapshotGetRepository(rs.Primary.ID).Do(context.TODO()) if err != nil { return nil // should be not found error diff --git a/provider/resource_opensearch_user.go b/provider/resource_opensearch_user.go index 7714159..b6a4aeb 100644 --- a/provider/resource_opensearch_user.go +++ b/provider/resource_opensearch_user.go @@ -3,7 +3,6 @@ package provider import ( "context" "encoding/json" - "errors" "fmt" "log" "net/http" @@ -112,30 +111,25 @@ func resourceOpensearchOpenDistroUserUpdate(d *schema.ResourceData, m interface{ func resourceOpensearchOpenDistroUserDelete(d *schema.ResourceData, m interface{}) error { var err error - path, err := uritemplates.Expand("/_opendistro/_security/api/internalusers/{name}", map[string]string{ + path, err := uritemplates.Expand("/_plugins/_security/api/internalusers/{name}", map[string]string{ "name": d.Get("username").(string), }) if err != nil { return fmt.Errorf("Error building URL path for user: %+v", err) } - esClient, err := getClient(m.(*ProviderConf)) + osClient, err := getClient(m.(*ProviderConf)) if err != nil { return err } - switch client := esClient.(type) { - case *elastic7.Client: - _, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "DELETE", - Path: path, - RetryStatusCodes: []int{http.StatusConflict, http.StatusInternalServerError}, - Retrier: elastic7.NewBackoffRetrier( - elastic7.NewExponentialBackoff(100*time.Millisecond, 30*time.Second), - ), - }) - default: - err = errors.New("Role resource not implemented prior to v7") - } + _, err = osClient.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ + Method: "DELETE", + Path: path, + RetryStatusCodes: []int{http.StatusConflict, http.StatusInternalServerError}, + Retrier: elastic7.NewBackoffRetrier( + elastic7.NewExponentialBackoff(100*time.Millisecond, 30*time.Second), + ), + }) return err } @@ -143,34 +137,30 @@ func resourceOpensearchOpenDistroUserDelete(d *schema.ResourceData, m interface{ func resourceOpensearchGetOpenDistroUser(userID string, m interface{}) (UserBody, error) { var err error user := new(UserBody) - - path, err := uritemplates.Expand("/_opendistro/_security/api/internalusers/{name}", map[string]string{ + path, err := uritemplates.Expand("/_plugins/_security/api/internalusers/{name}", map[string]string{ "name": userID, }) - + log.Printf("The resourceOpensearchGetOpenDistroUser path is " + string(path)) if err != nil { return *user, fmt.Errorf("Error building URL path for user: %+v", err) } var body json.RawMessage - esClient, err := getClient(m.(*ProviderConf)) + osClient, err := getClient(m.(*ProviderConf)) if err != nil { return *user, err } - switch client := esClient.(type) { - case *elastic7.Client: - var res *elastic7.Response - res, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "GET", - Path: path, - }) - if err != nil { - return *user, err - } - body = res.Body - default: - return *user, errors.New("Role resource not implemented prior to v7") + var res *elastic7.Response + res, err = osClient.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ + Method: "GET", + Path: path, + }) + log.Printf("The resourceOpensearchGetOpenDistroUser res is " + string(res.Body)) + log.Printf("The resourceOpensearchGetOpenDistroUser res StatusCode is " + fmt.Sprint(res.StatusCode)) + if err != nil { + return *user, err } + body = res.Body var userDefinition map[string]UserBody @@ -204,7 +194,7 @@ func resourceOpensearchPutOpenDistroUser(d *schema.ResourceData, m interface{}) return response, fmt.Errorf("Body Error : %s", userJSON) } - path, err := uritemplates.Expand("/_opendistro/_security/api/internalusers/{name}", map[string]string{ + path, err := uritemplates.Expand("/_plugins/_security/api/internalusers/{name}", map[string]string{ "name": d.Get("username").(string), }) if err != nil { @@ -212,43 +202,38 @@ func resourceOpensearchPutOpenDistroUser(d *schema.ResourceData, m interface{}) } var body json.RawMessage - esClient, err := getClient(m.(*ProviderConf)) + osClient, err := getClient(m.(*ProviderConf)) if err != nil { return nil, err } - switch client := esClient.(type) { - case *elastic7.Client: - var res *elastic7.Response - log.Printf("[INFO] put opendistro user: %+v", userDefinition) - res, err = client.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ - Method: "PUT", - Path: path, - Body: string(userJSON), - // see https://github.com/opendistro-for- - // elasticsearch/security/issues/1095, this should return a 409, but - // retry on the 500 as well. We can't parse the message to only retry on - // the conlict exception becaues the client doesn't directly - // expose the error response body - RetryStatusCodes: []int{http.StatusConflict, http.StatusInternalServerError}, - Retrier: elastic7.NewBackoffRetrier( - elastic7.NewExponentialBackoff(100*time.Millisecond, 30*time.Second), - ), - }) - if err != nil { - e, ok := err.(*elastic7.Error) - if !ok { - log.Printf("[INFO] expected error to be of type *elastic.Error") - } else { - log.Printf("[INFO] error creating user: %v %v %v", res, res.Body, e) - } - return response, err + var res *elastic7.Response + log.Printf("[INFO] put opendistro user: %+v", userDefinition) + res, err = osClient.PerformRequest(context.TODO(), elastic7.PerformRequestOptions{ + Method: "PUT", + Path: path, + Body: string(userJSON), + // see https://github.com/opendistro-for- + // elasticsearch/security/issues/1095, this should return a 409, but + // retry on the 500 as well. We can't parse the message to only retry on + // the conlict exception becaues the client doesn't directly + // expose the error response body + RetryStatusCodes: []int{http.StatusConflict, http.StatusInternalServerError}, + Retrier: elastic7.NewBackoffRetrier( + elastic7.NewExponentialBackoff(100*time.Millisecond, 30*time.Second), + ), + }) + if err != nil { + e, ok := err.(*elastic7.Error) + if !ok { + log.Printf("[INFO] expected error to be of type *elastic.Error") + } else { + log.Printf("[INFO] error creating user: %v %v %v", res, res.Body, e) } - - body = res.Body - default: - return response, errors.New("User resource not implemented prior to v7") + return response, err } + body = res.Body + if err := json.Unmarshal(body, response); err != nil { return response, fmt.Errorf("Error unmarshalling user body: %+v: %+v", err, body) } diff --git a/provider/resource_opensearch_user_test.go b/provider/resource_opensearch_user_test.go index 73bf3f7..9a7c8a6 100644 --- a/provider/resource_opensearch_user_test.go +++ b/provider/resource_opensearch_user_test.go @@ -6,12 +6,10 @@ import ( "os" "testing" - elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + elastic7 "github.com/olivere/elastic/v7" ) func TestAccOpensearchOpenDistroUser(t *testing.T) { @@ -20,27 +18,12 @@ func TestAccOpensearchOpenDistroUser(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - var allowed bool - switch esClient.(type) { - case *elastic6.Client: - allowed = false - default: - allowed = true - } randomName := "test" + acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) - if !allowed { - t.Skip("Users only supported on ES >= 7") - } }, Providers: testAccOpendistroProviders, CheckDestroy: testAccCheckOpensearchUserDestroy, @@ -116,27 +99,12 @@ func TestAccOpensearchOpenDistroUserMultiple(t *testing.T) { if diags.HasError() { t.Skipf("err: %#v", diags) } - meta := provider.Meta() - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - t.Skipf("err: %s", err) - } - var allowed bool - switch esClient.(type) { - case *elastic6.Client: - allowed = false - default: - allowed = true - } randomName := "test" + acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) - if !allowed { - t.Skip("Users only supported on ES >= 7") - } }, Providers: testAccOpendistroProviders, CheckDestroy: testAccCheckOpensearchUserDestroy, @@ -160,16 +128,7 @@ func testAccCheckOpensearchUserDestroy(s *terraform.State) error { meta := testAccOpendistroProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - return err - } - switch esClient.(type) { - case *elastic7.Client: - _, err = resourceOpensearchGetOpenDistroUser(rs.Primary.ID, meta.(*ProviderConf)) - default: - } - + _, err = resourceOpensearchGetOpenDistroUser(rs.Primary.ID, meta.(*ProviderConf)) if err != nil { return nil // should be not found error } @@ -190,16 +149,7 @@ func testCheckOpensearchUserExists(name string) resource.TestCheckFunc { meta := testAccOpendistroProvider.Meta() var err error - esClient, err := getClient(meta.(*ProviderConf)) - if err != nil { - return err - } - switch esClient.(type) { - case *elastic7.Client: - _, err = resourceOpensearchGetOpenDistroUser(rs.Primary.ID, meta.(*ProviderConf)) - default: - } - + _, err = resourceOpensearchGetOpenDistroUser(rs.Primary.ID, meta.(*ProviderConf)) if err != nil { return err } @@ -218,25 +168,16 @@ func testCheckOpensearchUserConnects(name string) resource.TestCheckFunc { continue } - username := rs.Primary.Attributes["username"] - password := rs.Primary.Attributes["password"] - meta := testAccOpendistroProvider.Meta() - var err error - esClient, err := getClient(meta.(*ProviderConf)) if err != nil { return err } - switch esClient.(type) { - case *elastic7.Client: - var client *elastic7.Client - client, err = elastic7.NewClient( - elastic7.SetURL(os.Getenv("OPENSEARCH_URL")), - elastic7.SetBasicAuth(username, password)) - - if err == nil { - _, err = client.ClusterHealth().Do(context.TODO()) - } + var client *elastic7.Client + client, err = elastic7.NewClient( + elastic7.SetURL(os.Getenv("OPENSEARCH_URL"))) + + if err == nil { + _, err = client.ClusterHealth().Do(context.TODO()) } if err != nil { @@ -254,7 +195,7 @@ func testAccOpenDistroUserResource(resourceName string) string { return fmt.Sprintf(` resource "opensearch_user" "test" { username = "%s" - password = "passw0rd" + password = "passw0rd@complexTest" description = "test" backend_roles = ["some_role"] @@ -278,7 +219,7 @@ func testAccOpenDistroUserResourceUpdated(resourceName string) string { return fmt.Sprintf(` resource "opensearch_user" "test" { username = "%s" - password = "passw0rd" + password = "passw0rd@complexTest" description = "test" backend_roles = ["some_role", "monitor_role"] @@ -304,7 +245,7 @@ func testAccOpenDistroUserResourceMinimal(resourceName string) string { return fmt.Sprintf(` resource "opensearch_user" "test" { username = "%s" - password = "passw0rd" + password = "passw0rd@complexTest" } `, resourceName) } @@ -313,19 +254,19 @@ func testAccOpenDistroUserMultiple(resourceName string) string { return fmt.Sprintf(` resource "opensearch_user" "testuser1" { username = "%s-testuser1" - password = "testuser1" + password = "testuser1@complexTest" description = "testuser1" } resource "opensearch_user" "testuser2" { username = "%s-testuser2" - password = "testuser2" + password = "testuser2@complexTest" description = "testuser2" } resource "opensearch_user" "testuser3" { username = "%s-testuser3" - password = "testuser3" + password = "testuser3@complexTest" description = "testuser3" } `, resourceName, resourceName, resourceName) diff --git a/provider/util.go b/provider/util.go index 42a4a43..2863cac 100644 --- a/provider/util.go +++ b/provider/util.go @@ -15,7 +15,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/mitchellh/go-homedir" elastic7 "github.com/olivere/elastic/v7" - elastic6 "gopkg.in/olivere/elastic.v6" ) var ( @@ -38,29 +37,6 @@ func elastic7GetObject(client *elastic7.Client, index string, id string) (*elast return result, nil } -func elastic6GetObject(client *elastic6.Client, objectType string, index string, id string) (*elastic6.GetResult, error) { - result, err := client.Get(). - Index(index). - Type(objectType). - Id(id). - Do(context.TODO()) - - if err != nil { - return nil, err - } - if !result.Found { - return nil, errObjNotFound - } - - return result, nil -} - -func normalizeDestination(tpl map[string]interface{}) { - delete(tpl, "id") - delete(tpl, "last_update_time") - delete(tpl, "schema_version") -} - func normalizeMonitor(tpl map[string]interface{}) { if triggers, ok := tpl["triggers"].([]interface{}); ok { normalizeMonitorTriggers(triggers)