diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..3c5aa0c6 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,73 @@ +# Golang CircleCI 2.0 configuration file for terraform-provider-launchdarkly-private tests +# +# Check https://circleci.com/docs/2.0/language-go/ for more details +version: 2 +jobs: + build: + docker: + - image: circleci/golang:1.14 + + working_directory: /go/src/github.com/launchdarkly/terraform-provider-launchdarkly-private + steps: + - checkout + - run: + name: go vet + command: make vet + - run: + name: Test Custom Properties + command: TESTARGS="-run TestCustomProperties" make testacc + - run: + name: Test Data Sources + command: TESTARGS="-run TestAccDataSource" make testacc + - run: + name: Test Default Variations + command: TESTARGS="-run TestDefaultVariations" make testacc + - run: + name: Test Environment Helper + command: TESTARGS="-run TestEnvironmentPost" make testacc + - run: + name: Test Target Helper + command: TESTARGS="-run TestTargets" make testacc + - run: + name: Test Variations Helper + command: TESTARGS="-run TestVariations" make testacc + - run: + name: Test Handlers + command: TESTARGS="-run TestHandle" make testacc + - run: + name: Test Policy Statements + command: TESTARGS="-run TestPolicyStatement" make testacc + - run: + name: Test Access Token Resource + command: TESTARGS="-run TestAccAccessToken" make testacc + - run: + name: Test Custom Role Resource + command: TESTARGS="-run TestAccCustomRole" make testacc + - run: + name: Test Destination Resource + command: TESTARGS="-run TestAccDestination" make testacc + - run: + name: Test Environment Resource + command: TESTARGS="-run TestAccEnvironment" make testacc + - run: + name: Test Feature Flag Resource + command: TESTARGS="-run TestAccFeatureFlag" make testacc + - run: + name: Test Feature Flag Environment Resource + command: TESTARGS="-run TestAccFeatureFlagEnvironment" make testacc + - run: + name: Test Project Resource + command: TESTARGS="-run TestAccProject" make testacc + - run: + name: Test Segment Resource + command: TESTARGS="-run TestAccSegment" make testacc + - run: + name: Test Team Members + command: | + TESTARGS="-run TestAccTeamMember_CreateGeneric" make testacc + TESTARGS="-run TestAccTeamMember_UpdateGeneric" make testacc + TESTARGS="-run TestAccTeamMember_CreateWithCustomRole" make testacc + TESTARGS="-run TestAccTeamMember_UpdateWithCustomRole" make testacc + - run: + name: Test Webhook Resource + command: TESTARGS="-run TestAccWebhook" make testacc \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index bc3c6d9e..00000000 --- a/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -dist: xenial -sudo: required -services: - - docker -language: go -go: - - "1.14.x" - -env: - - GOFLAGS=-mod=vendor GO111MODULE=on - -install: - # This script is used by the Travis build to install a cookie for - # go.googlesource.com so rate limits are higher when using `go get` to fetch - # packages that live there. - # See: https://github.com/golang/go/issues/12933 - - bash scripts/gogetcookie.sh - -script: - - make test - - make vet - # - make website-test - -branches: - only: - - master -matrix: - fast_finish: true - allow_failures: - - go: tip diff --git a/CHANGELOG.md b/CHANGELOG.md index ae85c2bb..68079a4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ +## [1.5.0] (September 29, 2020) + +FEATURES: + +- Added a `launchdarkly_project` data source. + +- Added a `launchdarkly_environment` data source. + +- Added a `launchdarkly_feature_flag` data source. + +- Added a `launchdarkly_feature_flag_environment` data source. + +- Added a `launchdarkly_segment` data source. + +- Added a `launchdarkly_webhook` data source. + +ENHANCEMENTS: + +- Upgraded the LaunchDarkly API version to 3.5.0. + +BUG FIXES: + +- Resolved issues with the `launchdarkly_project`'s `environments` attribute. This attribute is no longer marked as deprecated and should be used when you wish to override the behavior of creating `Test` and `Production` environments during project creation. + +- Fixed a bug where creating a `launchdarkly_feature_flag_environment` with an `off_variation` was not actually setting the off variation. + +NOTES: + +- The `launchdarkly_project`'s `environments` attribute is no longer marked as `computed`. This means that if you have `launchdarkly_project` resources without nested `environments` that were created before this version, you will see a diff denoting the removal of the computed environments from your state. It is safe to apply this change as no changes be made to your LaunchDarkly resources when applied. + ## [1.4.1] (September 8, 2020) FEATURES: diff --git a/examples/multiple_projects/README.md b/examples/multiple_projects/README.md index 72f7d1a2..cabc80fd 100644 --- a/examples/multiple_projects/README.md +++ b/examples/multiple_projects/README.md @@ -1,19 +1,20 @@ ## Example: Configure multiple LaunchDarkly projects ### Introduction + LaunchDarkly projects allow you to manage multiple business objectives from a single LaunchDarkly account. Every project has its own unique set of associated environments and feature flags. For more, please see the [LaunchDarkly official documentation](https://docs.launchdarkly.com/home/managing-flags/projects). This directory contains an example of how one might configure multiple projects, each with their own environments and feature flags, in one go. Specifically, this example will create the following: + - a "Terraform Example Project 1" with the key `tf-project-1` containing: - - a "Terraform Test Environment" with key `tf-test` - - a "Terraform Production Environment" with key `tf-production` - - (automatically-created "Test" and "Production" environments that come with all new projects) - - a boolean "Basic feature flag" with key "basic-flag" - - a `tf-test`-specific flag configuration attached to the "Basic feature flag" + - a "Terraform Test Environment" with key `tf-test` + - a "Terraform Production Environment" with key `tf-production` + - a boolean "Basic feature flag" with key "basic-flag" + - a `tf-test`-specific flag configuration attached to the "Basic feature flag" - a "Terraform Example Project 2" with thte key `tf-project-2` containing: - - an "Example Environment A" with key `tf-example-env-a` - - an "Example Environment B" with key `tf-example-env-b` - - (automatically-created "Test" and "Production" environments that come with all new projects) + - an "Example Environment A" with key `tf-example-env-a` + - an "Example Environment B" with key `tf-example-env-b` + - (automatically-created "Test" and "Production" environments will also be created since this example does not use nested environments in the `launchdarkly_project` resource) Project 1 also contains an example of a feature flag that is configured differently in different environments using the `launchdarkly_feature_flag_environment` resource. You can see these differences from within the LaunchDarkly UI. When viewing the flag in the `tf_test` environment, the flag will look like this: @@ -23,13 +24,14 @@ From all other environments, it will simply look like this: ![basic flag](../assets/images/multiple-proj-basic-flag.png) - ### Important notes -- Keep in mind that all new projects will automatically come with 'test' and 'production' environments, so it is redundant to create those! + +- Keep in mind that all new projects that don't use nested `environments` blocks will automatically come with 'test' and 'production' environments, so it may be redundant to create those! - Project keys MUST be unique - Environment keys must be unique within their given project ### Run + Init your working directory from the CL with `terraform init` and then apply the changes with `terraform apply`. You should see output resembling the following: ``` @@ -63,6 +65,7 @@ Plan: 8 to add, 0 to change, 0 to destroy. ``` where all of the changes to be made should be described in the format seen above. Terraform will then ask you for your confirmation and then begin applying the changes: + ``` launchdarkly_project.tf_project_1: Creating... launchdarkly_project.tf_project_2: Creating... @@ -70,4 +73,5 @@ launchdarkly_project.tf_project_2: Creation complete after 0s [id=example-projec launchdarkly_environment.tf_env_a: Creating... launchdarkly_environment.tf_env_b: Creating... ``` -etc. Your projects should now be up, running, and accessible from your LaunchDarkly UI. \ No newline at end of file + +etc. Your projects should now be up, running, and accessible from your LaunchDarkly UI. diff --git a/examples/multiple_projects/example.tf b/examples/multiple_projects/example.tf index cf5b7501..eb85c39d 100644 --- a/examples/multiple_projects/example.tf +++ b/examples/multiple_projects/example.tf @@ -10,7 +10,7 @@ provider "launchdarkly" { # ----------------------------------------------------------------------------------- # # PROJECT 1 -# create the project +# create the project with nested environments blocks resource "launchdarkly_project" "tf_project_1" { key = "tf-project-1" name = "Terraform Example Project 1" @@ -18,31 +18,27 @@ resource "launchdarkly_project" "tf_project_1" { tags = [ "terraform-managed", ] -} - -# create a terraform-specific test environment within project 1 -resource "launchdarkly_environment" "tf_test" { - name = "Terraform Test Environment" - key = "tf-test" - color = "999999" - tags = [ - "terraform-managed", - "test" - ] - - project_key = launchdarkly_project.tf_project_1.key -} -# create a terraform-specific production environment within project 1 -resource "launchdarkly_environment" "tf_production" { - name = "Terraform Production Environment" - key = "tf-production" - color = "333333" - tags = [ - "terraform-managed", - ] + # create a terraform-specific test environment within the project + environments { + name = "Terraform Test Environment" + key = "tf-test" + color = "999999" + tags = [ + "terraform-managed", + "test" + ] + } - project_key = launchdarkly_project.tf_project_1.key + # create a terraform-specific production environment within the project + environments { + name = "Terraform Production Environment" + key = "tf-production" + color = "333333" + tags = [ + "terraform-managed", + ] + } } # create a basic feature flag within project 1 @@ -58,7 +54,10 @@ resource "launchdarkly_feature_flag" "basic" { # the flag will display variation 0 only to users whose country matches "de" or "fr". resource "launchdarkly_feature_flag_environment" "basic_variation" { flag_id = launchdarkly_feature_flag.basic.id - env_key = launchdarkly_environment.tf_test.key + + # since the environment was specified as a nested block in the project resource, the environment + # key must be retrieved through the `launchdarkly_project` resource. + env_key = launchdarkly_project.tf_project_1.environments.0.key targeting_enabled = true @@ -78,7 +77,8 @@ resource "launchdarkly_feature_flag_environment" "basic_variation" { } # ----------------------------------------------------------------------------------- # -# PROJECT 2 +# PROJECT 2 - an example of how to use dedicated `launchdarkly_enviromnent` resources instead +# of nested environments in the `launchdarkly_project` resource resource "launchdarkly_project" "tf_project_2" { key = "tf-project-2" @@ -110,4 +110,4 @@ resource "launchdarkly_environment" "tf_env_b" { ] project_key = launchdarkly_project.tf_project_2.key -} \ No newline at end of file +} diff --git a/go.mod b/go.mod index a25c413d..f3d7ab46 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,6 @@ go 1.14 require ( github.com/antihax/optional v1.0.0 github.com/hashicorp/terraform-plugin-sdk v1.15.0 - github.com/launchdarkly/api-client-go v3.2.1-0.20200812163818-441cfcaaa92c+incompatible + github.com/launchdarkly/api-client-go v3.5.0+incompatible github.com/stretchr/testify v1.6.1 ) diff --git a/go.sum b/go.sum index e945a0c1..93229a0f 100644 --- a/go.sum +++ b/go.sum @@ -154,8 +154,8 @@ github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3v github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/launchdarkly/api-client-go v3.2.1-0.20200812163818-441cfcaaa92c+incompatible h1:xWlvqEclZEIAX4+0k2TQZGxgWA4tElgXy/H1XNsD/cQ= -github.com/launchdarkly/api-client-go v3.2.1-0.20200812163818-441cfcaaa92c+incompatible/go.mod h1:INGa7NUZYSwVozwPV7l6ikgD7pzSOpZvg9I5sqCZIWs= +github.com/launchdarkly/api-client-go v3.5.0+incompatible h1:b2DN5SjdUZu4tf4AwEEt8BmvC1f1DXI/S+SeruNVbGM= +github.com/launchdarkly/api-client-go v3.5.0+incompatible/go.mod h1:INGa7NUZYSwVozwPV7l6ikgD7pzSOpZvg9I5sqCZIWs= github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= diff --git a/launchdarkly/account_cleaner_test.go b/launchdarkly/account_cleaner_test.go index 13822087..cd977add 100644 --- a/launchdarkly/account_cleaner_test.go +++ b/launchdarkly/account_cleaner_test.go @@ -87,7 +87,7 @@ func (c *Client) cleanTeamMembers() error { return handleLdapiErr(err) } for _, m := range members.Items { - if *m.Role != ldapi.OWNER_Role { + if *m.Role != ldapi.OWNER_Role && m.PendingInvite == true { _, err := c.ld.TeamMembersApi.DeleteMember(c.ctx, m.Id) if err != nil { return handleLdapiErr(err) diff --git a/launchdarkly/data_source_launchdarkly_environment.go b/launchdarkly/data_source_launchdarkly_environment.go new file mode 100644 index 00000000..c553f936 --- /dev/null +++ b/launchdarkly/data_source_launchdarkly_environment.go @@ -0,0 +1,20 @@ +package launchdarkly + +import "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + +func dataSourceEnvironment() *schema.Resource { + envSchema := dataSourceEnvironmentSchema(false) + envSchema[PROJECT_KEY] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validateKey(), + } + return &schema.Resource{ + Read: dataSourceEnvironmentRead, + Schema: envSchema, + } +} + +func dataSourceEnvironmentRead(d *schema.ResourceData, meta interface{}) error { + return environmentRead(d, meta, true) +} diff --git a/launchdarkly/data_source_launchdarkly_environment_test.go b/launchdarkly/data_source_launchdarkly_environment_test.go new file mode 100644 index 00000000..3d28b268 --- /dev/null +++ b/launchdarkly/data_source_launchdarkly_environment_test.go @@ -0,0 +1,131 @@ +package launchdarkly + +import ( + "fmt" + "os" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + ldapi "github.com/launchdarkly/api-client-go" + "github.com/stretchr/testify/require" +) + +const ( + testAccDataSourceEnvironment = ` +data "launchdarkly_environment" "test" { + key = "%s" + project_key = "%s" +} +` +) + +// testAccDataSourceEnvironmentScaffold creates a project with the given projectKey with the given env params +// for environment data source tests +func testAccDataSourceEnvironmentScaffold(client *Client, projectKey string, envBody ldapi.EnvironmentPost) (*ldapi.Environment, error) { + // create project + projectBody := ldapi.ProjectBody{ + Name: "Env Test Project", + Key: projectKey, + Environments: []ldapi.EnvironmentPost{ + envBody, + }, + } + project, err := testAccDataSourceProjectCreate(client, projectBody) + if err != nil { + return nil, err + } + for _, env := range project.Environments { + if env.Key == envBody.Key { + return &env, nil + } + } + return nil, fmt.Errorf("failed to create env") +} + +func TestAccDataSourceEnvironment_noMatchReturnsError(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false) + require.NoError(t, err) + projectKey := "tf-env-test-proj" + projectBody := ldapi.ProjectBody{ + Name: "Terraform Env Test Project", + Key: projectKey, + } + project, err := testAccDataSourceProjectCreate(client, projectBody) + require.NoError(t, err) + + envKey := "bad-env-key" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccDataSourceEnvironment, envKey, project.Key), + ExpectError: regexp.MustCompile(`errors during refresh: failed to get environment with key "bad-env-key" for project key: "tf-env-test-proj": 404 Not Found: {"message":"Unknown environment key bad-env-key"}`), + }, + }, + }) + err = testAccDataSourceProjectDelete(client, projectKey) + require.NoError(t, err) +} + +func TestAccDataSourceEnv_exists(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + + projectKey := "env-test-project" + envName := "Terraform Test Env" + envKey := "tf-test-env" + envColor := "fff000" + client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false) + require.NoError(t, err) + + envBody := ldapi.EnvironmentPost{ + Name: envName, + Key: envKey, + Color: envColor, + SecureMode: true, + Tags: []string{ + "some", "tag", + }, + } + + env, err := testAccDataSourceEnvironmentScaffold(client, projectKey, envBody) + require.NoError(t, err) + + resourceName := "data.launchdarkly_environment.test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccDataSourceEnvironment, envKey, projectKey), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "key"), + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttrSet(resourceName, "color"), + resource.TestCheckResourceAttr(resourceName, "key", env.Key), + resource.TestCheckResourceAttr(resourceName, "name", env.Name), + resource.TestCheckResourceAttr(resourceName, "color", env.Color), + resource.TestCheckResourceAttr(resourceName, "tags.#", "2"), + resource.TestCheckResourceAttr(resourceName, "mobile_key", env.MobileKey), + resource.TestCheckResourceAttr(resourceName, "default_ttl", "0"), + resource.TestCheckResourceAttr(resourceName, "id", projectKey+"/"+env.Key), + ), + }, + }, + }) + + err = testAccDataSourceProjectDelete(client, projectKey) + require.NoError(t, err) +} diff --git a/launchdarkly/data_source_launchdarkly_feature_flag.go b/launchdarkly/data_source_launchdarkly_feature_flag.go new file mode 100644 index 00000000..f79fb2ad --- /dev/null +++ b/launchdarkly/data_source_launchdarkly_feature_flag.go @@ -0,0 +1,46 @@ +package launchdarkly + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func dataSourceFeatureFlag() *schema.Resource { + schemaMap := baseFeatureFlagSchema() + schemaMap[NAME] = &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The feature flag's human-readable name", + } + schemaMap[VARIATION_TYPE] = &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: fmt.Sprintf("The uniform type for all variations. Can be either %q, %q, %q, or %q.", + BOOL_VARIATION, STRING_VARIATION, NUMBER_VARIATION, JSON_VARIATION), + } + schemaMap[CLIENT_SIDE_AVAILABILITY] = &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "using_environment_id": { + Type: schema.TypeBool, + Optional: true, + }, + "using_mobile_key": { + Type: schema.TypeBool, + Optional: true, + }, + }, + }, + } + return &schema.Resource{ + Read: dataSourceFeatureFlagRead, + Schema: schemaMap, + } +} + +func dataSourceFeatureFlagRead(d *schema.ResourceData, raw interface{}) error { + return featureFlagRead(d, raw, true) +} diff --git a/launchdarkly/data_source_launchdarkly_feature_flag_environment.go b/launchdarkly/data_source_launchdarkly_feature_flag_environment.go new file mode 100644 index 00000000..4178de99 --- /dev/null +++ b/launchdarkly/data_source_launchdarkly_feature_flag_environment.go @@ -0,0 +1,14 @@ +package launchdarkly + +import "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + +func dataSourceFeatureFlagEnvironment() *schema.Resource { + return &schema.Resource{ + Read: dataSourceFeatureFlagEnvironmentRead, + Schema: baseFeatureFlagEnvironmentSchema(), + } +} + +func dataSourceFeatureFlagEnvironmentRead(d *schema.ResourceData, meta interface{}) error { + return featureFlagEnvironmentRead(d, meta, true) +} diff --git a/launchdarkly/data_source_launchdarkly_feature_flag_environment_test.go b/launchdarkly/data_source_launchdarkly_feature_flag_environment_test.go new file mode 100644 index 00000000..7e19f4fc --- /dev/null +++ b/launchdarkly/data_source_launchdarkly_feature_flag_environment_test.go @@ -0,0 +1,192 @@ +package launchdarkly + +import ( + "fmt" + "net/http" + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + ldapi "github.com/launchdarkly/api-client-go" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const ( + testAccDataSourceFeatureFlagEnvironment = ` +data "launchdarkly_feature_flag_environment" "test" { + env_key = "%s" + flag_id = "%s" +} +` +) + +func testAccDataSourceFeatureFlagEnvironmentScaffold(client *Client, projectKey, envKey, flagKey string, envConfigPatches []ldapi.PatchOperation) (*ldapi.FeatureFlag, error) { + // create a flag + flagBody := ldapi.FeatureFlagBody{ + Name: "Feature Flag Env Data Source Test", + Key: flagKey, + Variations: []ldapi.Variation{ + {Value: intfPtr(true)}, + {Value: intfPtr(false)}, + }, + } + _, err := testAccDataSourceFeatureFlagScaffold(client, projectKey, flagBody) + if err != nil { + return nil, err + } + + // patch feature flag with env-specific config + patch := ldapi.PatchComment{ + Comment: "Terraform feature flag env data source test", + Patch: envConfigPatches, + } + _, _, err = handleRateLimit(func() (interface{}, *http.Response, error) { + return handleNoConflict(func() (interface{}, *http.Response, error) { + return client.ld.FeatureFlagsApi.PatchFeatureFlag(client.ctx, projectKey, flagKey, patch) + }) + }) + if err != nil { + // delete project if anything fails because otherwise we will see a + // 409 error later and have to clean it up manually + _ = testAccDataSourceProjectDelete(client, projectKey) + return nil, fmt.Errorf("failed to create feature flag env config: %s", err.Error()) + } + flagRaw, _, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.FeatureFlagsApi.GetFeatureFlag(client.ctx, projectKey, flagKey, nil) + }) + if err != nil { + _ = testAccDataSourceProjectDelete(client, projectKey) + return nil, fmt.Errorf("failed to get feature flag: %s", err.Error()) + } + + flag, ok := flagRaw.(ldapi.FeatureFlag) + if !ok { + _ = testAccDataSourceProjectDelete(client, projectKey) + return nil, fmt.Errorf("failed to create feature flag env config") + } + return &flag, nil +} + +func TestAccDataSourceFeatureFlagEnvironment_noMatchReturnsError(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + + projectKey := "ff-env-ds-test" + envKey := "bad-env" + flagKey := "flag-no-env" + client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false) + require.NoError(t, err) + + // create some fake config + patches := []ldapi.PatchOperation{ + patchReplace("/environments/"+envKey+"/on", false), + } + _, err = testAccDataSourceFeatureFlagEnvironmentScaffold(client, projectKey, envKey, flagKey, patches) + assert.Error(t, err) + assert.Contains(t, err.Error(), "400 Bad Request") +} + +func TestAccDataSourceFeatureFlagEnvironment_exists(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + + projectKey := "ff-env-ds-test2" + envKey := "test" + flagKey := "test-env-config" + client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false) + require.NoError(t, err) + + rules := []rule{ + { + Variation: intPtr(1), + Clauses: []ldapi.Clause{ + { + Attribute: "thing", + Op: "contains", + Values: []interface{}{"test"}, + }, + }, + }, + } + prerequisites := []ldapi.Prerequisite{ + { + Key: "some-other-flag", + Variation: 1, + }, + } + targets := []ldapi.Target{ + { + Values: []string{"some@email.com", "some_other@email.com"}, + Variation: 1, + }, + } + fall := fallthroughModel{ + Variation: intPtr(0), + } + + basePatchPath := "/environments/" + envKey + "/" + patches := []ldapi.PatchOperation{ + patchReplace(basePatchPath+"on", true), + patchReplace(basePatchPath+"trackEvents", true), + patchReplace(basePatchPath+"rules", rules), + patchReplace(basePatchPath+"prerequisites", prerequisites), + patchReplace(basePatchPath+"offVariation", 0), + patchReplace(basePatchPath+"targets", targets), + patchReplace(basePatchPath+"fallthrough", fall), + } + flag, err := testAccDataSourceFeatureFlagEnvironmentScaffold(client, projectKey, envKey, flagKey, patches) + require.NoError(t, err) + + thisConfig := flag.Environments[envKey] + otherConfig := flag.Environments["production"] + + flagId := projectKey + "/" + flagKey + resourceName := "data.launchdarkly_feature_flag_environment.test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccDataSourceFeatureFlagEnvironment, envKey, flagId), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "flag_id"), + resource.TestCheckResourceAttr(resourceName, "env_key", envKey), + resource.TestCheckResourceAttr(resourceName, "targeting_enabled", fmt.Sprint(thisConfig.On)), + resource.TestCheckResourceAttr(resourceName, "track_events", fmt.Sprint(thisConfig.TrackEvents)), + resource.TestCheckResourceAttr(resourceName, "rules.0.variation", fmt.Sprint(thisConfig.Rules[0].Variation)), + resource.TestCheckResourceAttr(resourceName, "rules.0.clauses.0.attribute", thisConfig.Rules[0].Clauses[0].Attribute), + resource.TestCheckResourceAttr(resourceName, "rules.0.clauses.0.op", thisConfig.Rules[0].Clauses[0].Op), + resource.TestCheckResourceAttr(resourceName, "rules.0.clauses.0.values.0", fmt.Sprint(thisConfig.Rules[0].Clauses[0].Values[0])), + resource.TestCheckResourceAttr(resourceName, "prerequisites.0.flag_key", thisConfig.Prerequisites[0].Key), + resource.TestCheckResourceAttr(resourceName, "prerequisites.0.variation", fmt.Sprint(thisConfig.Prerequisites[0].Variation)), + resource.TestCheckResourceAttr(resourceName, "off_variation", fmt.Sprint(thisConfig.OffVariation)), + // user targets will be two long because there is an empty one for the 0 value + resource.TestCheckResourceAttr(resourceName, "user_targets.1.values.#", fmt.Sprint(len(thisConfig.Targets[0].Values))), + resource.TestCheckResourceAttr(resourceName, "flag_fallthrough.0.variation", fmt.Sprint(thisConfig.Fallthrough_.Variation)), + ), + }, + { + Config: fmt.Sprintf(testAccDataSourceFeatureFlagEnvironment, "production", flagId), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "flag_id"), + resource.TestCheckResourceAttr(resourceName, "env_key", "production"), + resource.TestCheckResourceAttr(resourceName, "targeting_enabled", fmt.Sprint(otherConfig.On)), + resource.TestCheckResourceAttr(resourceName, "track_events", fmt.Sprint(otherConfig.TrackEvents)), + resource.TestCheckResourceAttr(resourceName, "rules.#", fmt.Sprint(len(otherConfig.Rules))), + resource.TestCheckResourceAttr(resourceName, "prerequisites.#", fmt.Sprint(len(otherConfig.Prerequisites))), + resource.TestCheckResourceAttr(resourceName, "user_targets.#", fmt.Sprint(len(otherConfig.Targets))), + ), + }, + }, + }) + + err = testAccDataSourceProjectDelete(client, projectKey) + require.NoError(t, err) +} diff --git a/launchdarkly/data_source_launchdarkly_feature_flag_test.go b/launchdarkly/data_source_launchdarkly_feature_flag_test.go new file mode 100644 index 00000000..6346668c --- /dev/null +++ b/launchdarkly/data_source_launchdarkly_feature_flag_test.go @@ -0,0 +1,115 @@ +package launchdarkly + +import ( + "fmt" + "os" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + ldapi "github.com/launchdarkly/api-client-go" + "github.com/stretchr/testify/require" +) + +const ( + testAccDataSourceFeatureFlag = ` +data "launchdarkly_feature_flag" "test" { + key = "%s" + project_key = "%s" +} +` +) + +func TestAccDataSourceFeatureFlag_noMatchReturnsError(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false) + require.NoError(t, err) + projectKey := "tf-flag-test-proj" + projectBody := ldapi.ProjectBody{ + Name: "Terraform Flag Test Project", + Key: projectKey, + } + project, err := testAccDataSourceProjectCreate(client, projectBody) + require.NoError(t, err) + + flagKey := "nonexistent-flag" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccDataSourceFeatureFlag, flagKey, project.Key), + ExpectError: regexp.MustCompile(`errors during refresh: failed to get flag "nonexistent-flag" of project "tf-flag-test-proj": 404 Not Found:`), + }, + }, + }) + + err = testAccDataSourceProjectDelete(client, projectKey) + require.NoError(t, err) +} + +func TestAccDataSourceFeatureFlag_exists(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + + projectKey := "flag-test-project" + client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false) + require.NoError(t, err) + + flagName := "Flag Data Source Test" + flagKey := "flag-ds-test" + flagBody := ldapi.FeatureFlagBody{ + Name: flagName, + Key: flagKey, + Variations: []ldapi.Variation{ + {Value: intfPtr(true)}, + {Value: intfPtr(false)}, + }, + Description: "a flag to test the terraform flag data source", + Temporary: true, + ClientSideAvailability: &ldapi.ClientSideAvailability{ + UsingEnvironmentId: true, + UsingMobileKey: false, + }, + } + flag, err := testAccDataSourceFeatureFlagScaffold(client, projectKey, flagBody) + require.NoError(t, err) + + resourceName := "data.launchdarkly_feature_flag.test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccDataSourceFeatureFlag, flagKey, projectKey), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "key"), + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttrSet(resourceName, "project_key"), + resource.TestCheckResourceAttr(resourceName, "key", flag.Key), + resource.TestCheckResourceAttr(resourceName, "name", flag.Name), + resource.TestCheckResourceAttr(resourceName, "description", flag.Description), + resource.TestCheckResourceAttr(resourceName, "temporary", "true"), + resource.TestCheckResourceAttr(resourceName, "variations.#", "2"), + resource.TestCheckResourceAttr(resourceName, "variations.0.value", "true"), + resource.TestCheckResourceAttr(resourceName, "variations.1.value", "false"), + resource.TestCheckResourceAttr(resourceName, "id", projectKey+"/"+flag.Key), + resource.TestCheckResourceAttr(resourceName, "client_side_availability.using_environment_id", "true"), + resource.TestCheckResourceAttr(resourceName, "client_side_availability.using_mobile_key", "false"), + ), + }, + }, + }) + + err = testAccDataSourceProjectDelete(client, projectKey) + require.NoError(t, err) +} diff --git a/launchdarkly/data_source_launchdarkly_project.go b/launchdarkly/data_source_launchdarkly_project.go new file mode 100644 index 00000000..4ba3b60a --- /dev/null +++ b/launchdarkly/data_source_launchdarkly_project.go @@ -0,0 +1,43 @@ +package launchdarkly + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func dataSourceProject() *schema.Resource { + return &schema.Resource{ + Read: dataSourceProjectRead, + + Schema: map[string]*schema.Schema{ + KEY: { + Type: schema.TypeString, + Required: true, + }, + NAME: { + Type: schema.TypeString, + Computed: true, + }, + CLIENT_SIDE_AVAILABILITY: { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "using_environment_id": { + Type: schema.TypeBool, + Optional: true, + }, + "using_mobile_key": { + Type: schema.TypeBool, + Optional: true, + }, + }, + }, + }, + TAGS: tagsSchema(), + }, + } +} + +func dataSourceProjectRead(d *schema.ResourceData, meta interface{}) error { + return projectRead(d, meta, true) +} diff --git a/launchdarkly/data_source_launchdarkly_project_test.go b/launchdarkly/data_source_launchdarkly_project_test.go new file mode 100644 index 00000000..cfd6d961 --- /dev/null +++ b/launchdarkly/data_source_launchdarkly_project_test.go @@ -0,0 +1,112 @@ +package launchdarkly + +import ( + "fmt" + "os" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + ldapi "github.com/launchdarkly/api-client-go" + "github.com/stretchr/testify/require" +) + +const ( + testAccProjectBasic = ` +data "launchdarkly_project" "test" { + key = "%s" +} +` + + testAccProjectExists = ` +data "launchdarkly_project" "test" { + key = "%s" + } + ` +) + +func TestAccDataSourceProject_noMatchReturnsError(t *testing.T) { + projectKey := "nonexistent-project-key" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccProjectBasic, projectKey), + ExpectError: regexp.MustCompile(`errors during refresh: failed to get project with key "nonexistent-project-key": 404 Not Found`), + }, + }, + }) +} + +func TestAccDataSourceProject_exists(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + + projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + projectName := "Terraform Test Project" + envName := "Test Environment" + envKey := "test-environment" + envColor := "000000" + tag := "test-tag" + client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false) + require.NoError(t, err) + + projectBody := ldapi.ProjectBody{ + Name: projectName, + Key: projectKey, + DefaultClientSideAvailability: &ldapi.ClientSideAvailability{ + UsingEnvironmentId: false, + UsingMobileKey: false, + }, + Tags: []string{ + tag, + }, + Environments: []ldapi.EnvironmentPost{ + { + Name: envName, + Key: envKey, + Color: envColor, + SecureMode: true, + ConfirmChanges: true, + RequireComments: true, + Tags: []string{ + tag, + }, + }, + }, + } + + project, err := testAccDataSourceProjectCreate(client, projectBody) + require.NoError(t, err) + + resourceName := "data.launchdarkly_project.test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccProjectExists, projectKey), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "key"), + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttr(resourceName, "key", project.Key), + resource.TestCheckResourceAttr(resourceName, "name", project.Name), + resource.TestCheckResourceAttr(resourceName, "id", project.Id), + resource.TestCheckResourceAttr(resourceName, "tags.#", "1"), + resource.TestCheckResourceAttr(resourceName, "client_side_availability.using_environment_id", "false"), + resource.TestCheckResourceAttr(resourceName, "client_side_availability.using_mobile_key", "false"), + ), + }, + }, + }) + err = testAccDataSourceProjectDelete(client, projectKey) + require.NoError(t, err) +} diff --git a/launchdarkly/data_source_launchdarkly_segment.go b/launchdarkly/data_source_launchdarkly_segment.go new file mode 100644 index 00000000..4cf3b148 --- /dev/null +++ b/launchdarkly/data_source_launchdarkly_segment.go @@ -0,0 +1,34 @@ +package launchdarkly + +import "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + +func dataSourceSegment() *schema.Resource { + schemaMap := baseSegmentSchema() + schemaMap[PROJECT_KEY] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validateKey(), + } + schemaMap[ENV_KEY] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validateKey(), + } + schemaMap[KEY] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validateKey(), + } + schemaMap[NAME] = &schema.Schema{ + Type: schema.TypeString, + Computed: true, + } + return &schema.Resource{ + Read: dataSourceSegmentRead, + Schema: schemaMap, + } +} + +func dataSourceSegmentRead(d *schema.ResourceData, raw interface{}) error { + return segmentRead(d, raw, true) +} diff --git a/launchdarkly/data_source_launchdarkly_segment_test.go b/launchdarkly/data_source_launchdarkly_segment_test.go new file mode 100644 index 00000000..8a9f00ea --- /dev/null +++ b/launchdarkly/data_source_launchdarkly_segment_test.go @@ -0,0 +1,165 @@ +package launchdarkly + +import ( + "fmt" + "net/http" + "os" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + ldapi "github.com/launchdarkly/api-client-go" + "github.com/stretchr/testify/require" +) + +const ( + testAccDataSourceSegment = ` +data "launchdarkly_segment" "test" { + key = "%s" + project_key = "%s" + env_key = "test" +} +` +) + +type testSegmentUpdate struct { + Included []interface{} + Excluded []interface{} + Rules []ldapi.UserSegmentRule +} + +func testAccDataSourceSegmentCreate(client *Client, projectKey, segmentKey string, properties testSegmentUpdate) (*ldapi.UserSegment, error) { + envKey := "test" + projectBody := ldapi.ProjectBody{ + Name: "Terraform Segment DS Test", + Key: projectKey, + } + project, err := testAccDataSourceProjectCreate(client, projectBody) + if err != nil { + return nil, err + } + + segmentBody := ldapi.UserSegmentBody{ + Name: "Data Source Test Segment", + Key: segmentKey, + Description: "test description", + Tags: []string{"terraform"}, + } + _, _, err = handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.UserSegmentsApi.PostUserSegment(client.ctx, project.Key, envKey, segmentBody) + }) + if err != nil { + return nil, fmt.Errorf("failed to create segment %q in project %q: %s", segmentKey, projectKey, handleLdapiErr(err)) + } + + patch := []ldapi.PatchOperation{ + patchReplace("/included", properties.Included), + patchReplace("/excluded", properties.Excluded), + patchReplace("/rules", properties.Rules), + } + rawSegment, _, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return handleNoConflict(func() (interface{}, *http.Response, error) { + return client.ld.UserSegmentsApi.PatchUserSegment(client.ctx, projectKey, envKey, segmentKey, patch) + }) + }) + if err != nil { + return nil, fmt.Errorf("failed to update segment %q in project %q: %s", segmentKey, projectKey, handleLdapiErr(err)) + } + + if segment, ok := rawSegment.(ldapi.UserSegment); ok { + return &segment, nil + } + return nil, fmt.Errorf("failed to create segment %q in project %q: %s", segmentKey, projectKey, handleLdapiErr(err)) +} + +func TestAccDataSourceSegment_noMatchReturnsError(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + + projectKey := "tf-segment-test" + segmentKey := "bad-segment-key" + client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false) + require.NoError(t, err) + _, err = testAccDataSourceProjectCreate(client, ldapi.ProjectBody{Name: "Segment DS No Match Test", Key: projectKey}) + require.NoError(t, err) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccDataSourceSegment, segmentKey, projectKey), + ExpectError: regexp.MustCompile(`errors during refresh: failed to get segment "bad-segment-key" of project "tf-segment-test": 404 Not Found:`), + }, + }, + }) + + testAccDataSourceProjectDelete(client, projectKey) + require.NoError(t, err) +} + +func TestAccDataSourceSegment_exists(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + + projectKey := "tf-segment-test2" + segmentKey := "data-source-test" + client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false) + require.NoError(t, err) + + properties := testSegmentUpdate{ + Included: []interface{}{"some@email.com", "some_other@email.com"}, + Excluded: []interface{}{"some_bad@email.com"}, + Rules: []ldapi.UserSegmentRule{ + { + Clauses: []ldapi.Clause{ + { + Attribute: "name", + Op: "startsWith", + Values: []interface{}{"a"}, + }, + }, + }, + }, + } + segment, err := testAccDataSourceSegmentCreate(client, projectKey, segmentKey, properties) + require.NoError(t, err) + + resourceName := "data.launchdarkly_segment.test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccDataSourceSegment, segmentKey, projectKey), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "key"), + resource.TestCheckResourceAttr(resourceName, "name", segment.Name), + resource.TestCheckResourceAttr(resourceName, "key", segment.Key), + resource.TestCheckResourceAttr(resourceName, "id", projectKey+"/test/"+segmentKey), + resource.TestCheckResourceAttr(resourceName, "project_key", projectKey), + resource.TestCheckResourceAttr(resourceName, "env_key", "test"), + resource.TestCheckResourceAttr(resourceName, "rules.0.clauses.0.attribute", "name"), + resource.TestCheckResourceAttr(resourceName, "rules.0.clauses.0.op", "startsWith"), + resource.TestCheckResourceAttr(resourceName, "rules.0.clauses.0.values.#", "1"), + resource.TestCheckResourceAttr(resourceName, "included.#", "2"), + resource.TestCheckResourceAttr(resourceName, "included.0", "some@email.com"), + resource.TestCheckResourceAttr(resourceName, "excluded.#", "1"), + resource.TestCheckResourceAttr(resourceName, "excluded.0", "some_bad@email.com"), + resource.TestCheckResourceAttr(resourceName, "tags.#", "1"), + ), + }, + }, + }) + + testAccDataSourceProjectDelete(client, projectKey) + require.NoError(t, err) +} diff --git a/launchdarkly/data_source_launchdarkly_team_member_test.go b/launchdarkly/data_source_launchdarkly_team_member_test.go index 4da93862..fae97900 100644 --- a/launchdarkly/data_source_launchdarkly_team_member_test.go +++ b/launchdarkly/data_source_launchdarkly_team_member_test.go @@ -78,6 +78,7 @@ func TestAccDataSourceTeamMember_exists(t *testing.T) { teamMembers = append(teamMembers, *member) } + resourceName := "data.launchdarkly_team_member.test" testMember := teamMembers[teamMemberCount-1] resource.Test(t, resource.TestCase{ PreCheck: func() { @@ -88,11 +89,11 @@ func TestAccDataSourceTeamMember_exists(t *testing.T) { { Config: testAccDataSourceTeamMemberConfig(testMember.Email), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet("data.launchdarkly_team_member.test", "email"), - resource.TestCheckResourceAttr("data.launchdarkly_team_member.test", "email", testMember.Email), - resource.TestCheckResourceAttr("data.launchdarkly_team_member.test", "first_name", testMember.FirstName), - resource.TestCheckResourceAttr("data.launchdarkly_team_member.test", "last_name", testMember.LastName), - resource.TestCheckResourceAttr("data.launchdarkly_team_member.test", "id", testMember.Id), + resource.TestCheckResourceAttrSet(resourceName, "email"), + resource.TestCheckResourceAttr(resourceName, "email", testMember.Email), + resource.TestCheckResourceAttr(resourceName, "first_name", testMember.FirstName), + resource.TestCheckResourceAttr(resourceName, "last_name", testMember.LastName), + resource.TestCheckResourceAttr(resourceName, "id", testMember.Id), ), }, }, diff --git a/launchdarkly/data_source_launchdarkly_webhook.go b/launchdarkly/data_source_launchdarkly_webhook.go new file mode 100644 index 00000000..f8d3cca5 --- /dev/null +++ b/launchdarkly/data_source_launchdarkly_webhook.go @@ -0,0 +1,29 @@ +package launchdarkly + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func dataSourceWebhook() *schema.Resource { + schemaMap := baseWebhookSchema() + schemaMap[URL] = &schema.Schema{ + Type: schema.TypeString, + Computed: true, + } + schemaMap[ENABLED] = &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + } + schemaMap[ID] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + } + return &schema.Resource{ + Read: dataSourceWebhookRead, + Schema: schemaMap, + } +} + +func dataSourceWebhookRead(d *schema.ResourceData, meta interface{}) error { + return webhookRead(d, meta, true) +} diff --git a/launchdarkly/data_source_launchdarkly_webhook_test.go b/launchdarkly/data_source_launchdarkly_webhook_test.go new file mode 100644 index 00000000..7444b6f6 --- /dev/null +++ b/launchdarkly/data_source_launchdarkly_webhook_test.go @@ -0,0 +1,121 @@ +package launchdarkly + +import ( + "fmt" + "net/http" + "os" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + ldapi "github.com/launchdarkly/api-client-go" + "github.com/stretchr/testify/require" +) + +const ( + testAccDataSourceWebhook = ` +data "launchdarkly_webhook" "test" { + id = "%s" +} +` +) + +func testAccDataSourceWebhookCreate(client *Client, webhookName string) (*ldapi.Webhook, error) { + webhookBody := ldapi.WebhookBody{ + Url: "https://www.example.com", + Sign: false, + On: true, + Name: webhookName, + Tags: []string{"terraform"}, + Statements: []ldapi.Statement{ + { + Resources: []string{"proj/*"}, + Actions: []string{"turnFlagOn"}, + Effect: "allow", + }, + }, + } + webhookRaw, _, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.WebhooksApi.PostWebhook(client.ctx, webhookBody) + }) + if err != nil { + return nil, fmt.Errorf("failed to create webhook with name %q: %s", webhookName, handleLdapiErr(err)) + } + + if webhook, ok := webhookRaw.(ldapi.Webhook); ok { + return &webhook, nil + } + return nil, fmt.Errorf("failed to create webhook") +} + +func testAccDataSourceWebhookDelete(client *Client, webhookId string) error { + _, _, err := handleRateLimit(func() (interface{}, *http.Response, error) { + res, err := client.ld.WebhooksApi.DeleteWebhook(client.ctx, webhookId) + return nil, res, err + }) + if err != nil { + return fmt.Errorf("failed to delete webhook with id %q: %s", webhookId, handleLdapiErr(err)) + } + return nil +} + +func TestAccDataSourceWebhook_noMatchReturnsError(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + + webhookId := acctest.RandStringFromCharSet(24, acctest.CharSetAlphaNum) + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccDataSourceWebhook, webhookId), + ExpectError: regexp.MustCompile(fmt.Sprintf(`errors during refresh: failed to get webhook with id "%s": 404 Not Found:`, webhookId)), + }, + }, + }) +} + +func TestAccDataSourceWebhook_exists(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + + webhookName := "Data Source Test" + client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false) + require.NoError(t, err) + webhook, err := testAccDataSourceWebhookCreate(client, webhookName) + require.NoError(t, err) + + resourceName := "data.launchdarkly_webhook.test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccDataSourceWebhook, webhook.Id), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "id", webhook.Id), + resource.TestCheckResourceAttr(resourceName, "name", webhookName), + resource.TestCheckResourceAttr(resourceName, "url", webhook.Url), + resource.TestCheckResourceAttr(resourceName, "enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "secret", webhook.Secret), + resource.TestCheckResourceAttr(resourceName, "tags.#", "1"), + resource.TestCheckResourceAttr(resourceName, "policy_statements.#", "1"), + resource.TestCheckResourceAttr(resourceName, "policy_statements.0.resources.0", "proj/*"), + resource.TestCheckResourceAttr(resourceName, "policy_statements.0.actions.0", "turnFlagOn"), + resource.TestCheckResourceAttr(resourceName, "policy_statements.0.effect", "allow"), + ), + }, + }, + }) +} diff --git a/launchdarkly/environments_helper.go b/launchdarkly/environments_helper.go index 02f548f6..202c3241 100644 --- a/launchdarkly/environments_helper.go +++ b/launchdarkly/environments_helper.go @@ -1,29 +1,33 @@ package launchdarkly import ( + "fmt" + "log" + "net/http" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" ldapi "github.com/launchdarkly/api-client-go" ) -func environmentSchema() map[string]*schema.Schema { +// baseEnvironmentSchema covers the overlap between the data source and resource schemas +// certain attributes are required for the resource that are not for the data source and so those +// will need to be differentiated +func baseEnvironmentSchema(forProject bool) map[string]*schema.Schema { return map[string]*schema.Schema{ - KEY: &schema.Schema{ - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validateKey(), - }, - NAME: &schema.Schema{ + KEY: { Type: schema.TypeString, Required: true, + // Don't force new if the environment schema will be nested in a project + ForceNew: !forProject, + ValidateFunc: validateKey(), }, - API_KEY: &schema.Schema{ + API_KEY: { Type: schema.TypeString, Computed: true, Sensitive: true, }, - MOBILE_KEY: &schema.Schema{ + MOBILE_KEY: { Type: schema.TypeString, Computed: true, Sensitive: true, @@ -33,41 +37,115 @@ func environmentSchema() map[string]*schema.Schema { Computed: true, Sensitive: true, }, - COLOR: &schema.Schema{ - Type: schema.TypeString, - Required: true, - }, - DEFAULT_TTL: &schema.Schema{ + DEFAULT_TTL: { Type: schema.TypeInt, Optional: true, + Computed: true, // Default TTL should be between 0 and 60 minutes: https://docs.launchdarkly.com/docs/environments ValidateFunc: validation.IntBetween(0, 60), + Description: "The TTL for the environment. This must be between 0 and 60 minutes. The TTL setting only applies to environments using the PHP SDK.", }, - SECURE_MODE: &schema.Schema{ - Type: schema.TypeBool, - Optional: true, + SECURE_MODE: { + Computed: true, + Type: schema.TypeBool, + Optional: true, + Description: "Secure mode ensures a user of the client-side SDK cannot impersonate another user", }, - DEFAULT_TRACK_EVENTS: &schema.Schema{ - Type: schema.TypeBool, - Optional: true, + DEFAULT_TRACK_EVENTS: { + Computed: true, + Type: schema.TypeBool, + Optional: true, + Description: "Whether or not to send data export events for every flag created in the environment", }, - REQUIRE_COMMENTS: &schema.Schema{ - Type: schema.TypeBool, - Optional: true, + REQUIRE_COMMENTS: { + Computed: true, + Type: schema.TypeBool, + Optional: true, + Description: "Whether or not to require comments for a flag and segment changes in this environment", }, - CONFIRM_CHANGES: &schema.Schema{ - Type: schema.TypeBool, - Optional: true, + CONFIRM_CHANGES: { + Computed: true, + Type: schema.TypeBool, + Optional: true, + Description: "Whether or not to require confirmation for a flag and segment changes in this environment", }, TAGS: tagsSchema(), } } -func environmentPostsFromResourceData(d *schema.ResourceData) []ldapi.EnvironmentPost { - schemaEnvs := d.Get(ENVIRONMENTS).([]interface{}) +func getEnvironmentUpdatePatches(config map[string]interface{}) []ldapi.PatchOperation { + // Always include required fields + name := config[NAME] + color := config[COLOR] + patches := []ldapi.PatchOperation{ + patchReplace("/name", name), + patchReplace("/color", color), + } + + // Add optional fields if they exist + defaultTtl, ok := config[DEFAULT_TTL] + if ok { + patches = append(patches, patchReplace("/defaultTtl", defaultTtl)) + } + + secureMode, ok := config[SECURE_MODE] + if ok { + patches = append(patches, patchReplace("/secureMode", secureMode)) + } + + defaultTrackEvents, ok := config[DEFAULT_TRACK_EVENTS] + if ok { + patches = append(patches, patchReplace("/defaultTrackEvents", defaultTrackEvents)) + } + + requireComments, ok := config[REQUIRE_COMMENTS] + if ok { + patches = append(patches, patchReplace("/requireComments", requireComments)) + } + + confirmChanges, ok := config[CONFIRM_CHANGES] + if ok { + patches = append(patches, patchReplace("/confirmChanges", confirmChanges)) + } + + tags, ok := config[TAGS] + if ok { + envTags := stringsFromSchemaSet(tags.(*schema.Set)) + patches = append(patches, patchReplace("/tags", &envTags)) + } + return patches +} - envs := make([]ldapi.EnvironmentPost, len(schemaEnvs)) - for i, env := range schemaEnvs { +func environmentSchema(forProject bool) map[string]*schema.Schema { + schemaMap := baseEnvironmentSchema(forProject) + schemaMap[NAME] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + } + schemaMap[COLOR] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + } + return schemaMap +} + +func dataSourceEnvironmentSchema(forPoject bool) map[string]*schema.Schema { + schemaMap := baseEnvironmentSchema(forPoject) + schemaMap[NAME] = &schema.Schema{ + Type: schema.TypeString, + Computed: true, + } + schemaMap[COLOR] = &schema.Schema{ + Type: schema.TypeString, + Computed: true, + } + return schemaMap +} + +func environmentPostsFromResourceData(d *schema.ResourceData) []ldapi.EnvironmentPost { + schemaEnvList := d.Get(ENVIRONMENTS).([]interface{}) + envs := make([]ldapi.EnvironmentPost, len(schemaEnvList)) + for i, env := range schemaEnvList { envs[i] = environmentPostFromResourceData(env) } return envs @@ -87,22 +165,74 @@ func environmentPostFromResourceData(env interface{}) ldapi.EnvironmentPost { return envPost } -func environmentsToResourceData(envs []ldapi.Environment) []interface{} { - transformed := make([]interface{}, len(envs)) - - for i, env := range envs { - transformed[i] = map[string]interface{}{ - KEY: env.Key, - NAME: env.Name, - API_KEY: env.ApiKey, - MOBILE_KEY: env.MobileKey, - CLIENT_SIDE_ID: env.Id, - COLOR: env.Color, - DEFAULT_TTL: int(env.DefaultTtl), - SECURE_MODE: env.SecureMode, - DEFAULT_TRACK_EVENTS: env.DefaultTrackEvents, - TAGS: env.Tags, - } - } - return transformed +type envResourceData map[string]interface{} + +func environmentsToResourceDataMap(envs []ldapi.Environment) map[string]envResourceData { + envMap := make(map[string]envResourceData, len(envs)) + for _, env := range envs { + envMap[env.Key] = environmentToResourceData(env) + } + + return envMap +} + +func environmentToResourceData(env ldapi.Environment) envResourceData { + return envResourceData{ + KEY: env.Key, + NAME: env.Name, + API_KEY: env.ApiKey, + MOBILE_KEY: env.MobileKey, + CLIENT_SIDE_ID: env.Id, + COLOR: env.Color, + DEFAULT_TTL: int(env.DefaultTtl), + SECURE_MODE: env.SecureMode, + DEFAULT_TRACK_EVENTS: env.DefaultTrackEvents, + REQUIRE_COMMENTS: env.RequireComments, + CONFIRM_CHANGES: env.ConfirmChanges, + TAGS: env.Tags, + } +} + +func rawEnvironmentConfigsToKeyList(rawEnvs []interface{}) []string { + keys := make([]string, 0, len(rawEnvs)) + for _, rawEnv := range rawEnvs { + env := rawEnv.(map[string]interface{}) + envKey := env[KEY].(string) + keys = append(keys, envKey) + } + return keys +} + +func environmentRead(d *schema.ResourceData, meta interface{}, isDataSource bool) error { + client := meta.(*Client) + projectKey := d.Get(PROJECT_KEY).(string) + key := d.Get(KEY).(string) + + envRaw, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.EnvironmentsApi.GetEnvironment(client.ctx, projectKey, key) + }) + if isStatusNotFound(res) && !isDataSource { + log.Printf("[WARN] failed to find environment with key %q in project %q, removing from state", key, projectKey) + d.SetId("") + return nil + } + if err != nil { + return fmt.Errorf("failed to get environment with key %q for project key: %q: %v", key, projectKey, handleLdapiErr(err)) + } + + env := envRaw.(ldapi.Environment) + d.SetId(projectKey + "/" + key) + _ = d.Set(key, env.Key) + _ = d.Set(NAME, env.Name) + _ = d.Set(API_KEY, env.ApiKey) + _ = d.Set(MOBILE_KEY, env.MobileKey) + _ = d.Set(CLIENT_SIDE_ID, env.Id) + _ = d.Set(COLOR, env.Color) + _ = d.Set(DEFAULT_TTL, int(env.DefaultTtl)) + _ = d.Set(SECURE_MODE, env.SecureMode) + _ = d.Set(DEFAULT_TRACK_EVENTS, env.DefaultTrackEvents) + _ = d.Set(TAGS, env.Tags) + _ = d.Set(REQUIRE_COMMENTS, env.RequireComments) + _ = d.Set(CONFIRM_CHANGES, env.ConfirmChanges) + return nil } diff --git a/launchdarkly/feature_flag_environment_helper.go b/launchdarkly/feature_flag_environment_helper.go new file mode 100644 index 00000000..f1b7698b --- /dev/null +++ b/launchdarkly/feature_flag_environment_helper.go @@ -0,0 +1,124 @@ +package launchdarkly + +import ( + "fmt" + "log" + "net/http" + "strings" + + "github.com/antihax/optional" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + ldapi "github.com/launchdarkly/api-client-go" +) + +func baseFeatureFlagEnvironmentSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + FLAG_ID: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateFlagID, + }, + ENV_KEY: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateKey(), + }, + TARGETING_ENABLED: { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + USER_TARGETS: targetsSchema(), + RULES: rulesSchema(), + PREREQUISITES: prerequisitesSchema(), + FLAG_FALLTHROUGH: fallthroughSchema(), + TRACK_EVENTS: { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + OFF_VARIATION: { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ValidateFunc: validation.IntAtLeast(0), + }, + } +} + +// get FeatureFlagEnvironment uses a query parameter to get the ldapi.FeatureFlag with only a single environment. +func getFeatureFlagEnvironment(client *Client, projectKey, flagKey, environmentKey string) (ldapi.FeatureFlag, *http.Response, error) { + flagRaw, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.FeatureFlagsApi.GetFeatureFlag(client.ctx, projectKey, flagKey, &ldapi.GetFeatureFlagOpts{ + Env: optional.NewInterface(environmentKey), + }) + }) + flag := flagRaw.(ldapi.FeatureFlag) + return flag, res, err +} + +func featureFlagEnvironmentRead(d *schema.ResourceData, raw interface{}, isDataSource bool) error { + client := raw.(*Client) + flagId := d.Get(FLAG_ID).(string) + projectKey, flagKey, err := flagIdToKeys(flagId) + if err != nil { + return err + } + envKey := d.Get(ENV_KEY).(string) + + flag, res, err := getFeatureFlagEnvironment(client, projectKey, flagKey, envKey) + if isStatusNotFound(res) && !isDataSource { + log.Printf("[WARN] failed to find flag %q in project %q, removing from state", flagKey, projectKey) + d.SetId("") + return nil + } + + if err != nil { + return fmt.Errorf("failed to get flag %q of project %q: %s", flagKey, projectKey, handleLdapiErr(err)) + } + + environment, ok := flag.Environments[envKey] + if !ok { + log.Printf("[WARN] failed to find environment %q for flag %q, removing from state", envKey, flagKey) + d.SetId("") + return nil + } + + if isDataSource { + d.SetId(projectKey + "/" + envKey + "/" + flagKey) + } + _ = d.Set(KEY, flag.Key) + + // Computed values are set even if they do not exist on the config + _ = d.Set(TARGETING_ENABLED, environment.On) + _ = d.Set(OFF_VARIATION, environment.OffVariation) + _ = d.Set(TRACK_EVENTS, environment.TrackEvents) + _ = d.Set(PREREQUISITES, prerequisitesToResourceData(environment.Prerequisites)) + + err = d.Set(RULES, rulesToResourceData(environment.Rules)) + if err != nil { + return fmt.Errorf("failed to set rules on flag with key %q: %v", flagKey, err) + } + + err = d.Set(USER_TARGETS, targetsToResourceData(environment.Targets)) + if err != nil { + return fmt.Errorf("failed to set targets on flag with key %q: %v", flagKey, err) + } + + err = d.Set(FLAG_FALLTHROUGH, fallthroughToResourceData(environment.Fallthrough_)) + if err != nil { + return fmt.Errorf("failed to set flag fallthrough on flag with key %q: %v", flagKey, err) + } + return nil +} + +func patchFlagEnvPath(d *schema.ResourceData, op string) string { + path := []string{"/environments"} + path = append(path, d.Get(ENV_KEY).(string)) + path = append(path, op) + + return strings.Join(path, "/") +} diff --git a/launchdarkly/feature_flags_helper.go b/launchdarkly/feature_flags_helper.go new file mode 100644 index 00000000..51dd8832 --- /dev/null +++ b/launchdarkly/feature_flags_helper.go @@ -0,0 +1,159 @@ +package launchdarkly + +import ( + "fmt" + "log" + "net/http" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ldapi "github.com/launchdarkly/api-client-go" +) + +func baseFeatureFlagSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + PROJECT_KEY: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The feature flag's project key", + ValidateFunc: validateKey(), + }, + KEY: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateKey(), + Description: "The human-readable name of the feature flag", + }, + MAINTAINER_ID: { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateID(), + }, + DESCRIPTION: { + Type: schema.TypeString, + Optional: true, + }, + VARIATIONS: variationsSchema(), + TEMPORARY: { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + INCLUDE_IN_SNIPPET: { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + TAGS: tagsSchema(), + CUSTOM_PROPERTIES: customPropertiesSchema(), + DEFAULT_ON_VARIATION: { + Type: schema.TypeString, + Optional: true, + Description: "The value of the variation served when the flag is on for new environments", + }, + DEFAULT_OFF_VARIATION: { + Type: schema.TypeString, + Optional: true, + Description: "The value of the variation served when the flag is off for new environments", + }, + } +} + +func featureFlagRead(d *schema.ResourceData, raw interface{}, isDataSource bool) error { + client := raw.(*Client) + projectKey := d.Get(PROJECT_KEY).(string) + key := d.Get(KEY).(string) + + flagRaw, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.FeatureFlagsApi.GetFeatureFlag(client.ctx, projectKey, key, nil) + }) + flag := flagRaw.(ldapi.FeatureFlag) + if isStatusNotFound(res) && !isDataSource { + log.Printf("[WARN] feature flag %q in project %q not found, removing from state", key, projectKey) + d.SetId("") + return nil + } + + if err != nil { + return fmt.Errorf("failed to get flag %q of project %q: %s", key, projectKey, handleLdapiErr(err)) + } + + transformedCustomProperties := customPropertiesToResourceData(flag.CustomProperties) + _ = d.Set(key, flag.Key) + _ = d.Set(NAME, flag.Name) + _ = d.Set(DESCRIPTION, flag.Description) + _ = d.Set(INCLUDE_IN_SNIPPET, flag.IncludeInSnippet) + _ = d.Set(TEMPORARY, flag.Temporary) + + if isDataSource { + CSA := *flag.ClientSideAvailability + clientSideAvailability := map[string]string{ + "using_environment_id": fmt.Sprintf("%v", CSA.UsingEnvironmentId), + "using_mobile_key": fmt.Sprintf("%v", CSA.UsingMobileKey), + } + _ = d.Set(CLIENT_SIDE_AVAILABILITY, clientSideAvailability) + } else { + _ = d.Set(INCLUDE_IN_SNIPPET, flag.IncludeInSnippet) + } + + // Only set the maintainer ID if is specified in the schema + _, ok := d.GetOk(MAINTAINER_ID) + if ok { + _ = d.Set(MAINTAINER_ID, flag.MaintainerId) + } + + variationType, err := variationsToVariationType(flag.Variations) + if err != nil { + return fmt.Errorf("failed to determine variation type on flag with key %q: %v", flag.Key, err) + } + err = d.Set(VARIATION_TYPE, variationType) + if err != nil { + return fmt.Errorf("failed to set variation type on flag with key %q: %v", flag.Key, err) + } + + parsedVariations, err := variationsToResourceData(flag.Variations, variationType) + if err != nil { + return fmt.Errorf("failed to parse variations on flag with key %q: %v", flag.Key, err) + } + err = d.Set(VARIATIONS, parsedVariations) + if err != nil { + return fmt.Errorf("failed to set variations on flag with key %q: %v", flag.Key, err) + } + + err = d.Set(TAGS, flag.Tags) + if err != nil { + return fmt.Errorf("failed to set tags on flag with key %q: %v", flag.Key, err) + } + + err = d.Set(CUSTOM_PROPERTIES, transformedCustomProperties) + if err != nil { + return fmt.Errorf("failed to set custom properties on flag with key %q: %v", flag.Key, err) + } + + if flag.Defaults != nil { + onValue, err := variationValueToString(flag.Variations[flag.Defaults.OnVariation].Value, variationType) + if err != nil { + return err + } + _ = d.Set(DEFAULT_ON_VARIATION, onValue) + offValue, err := variationValueToString(flag.Variations[flag.Defaults.OffVariation].Value, variationType) + if err != nil { + return err + } + _ = d.Set(DEFAULT_OFF_VARIATION, offValue) + } + + d.SetId(projectKey + "/" + key) + return nil +} + +func flagIdToKeys(id string) (projectKey string, flagKey string, err error) { + if strings.Count(id, "/") != 1 { + return "", "", fmt.Errorf("found unexpected flag id format: %q expected format: 'project_key/flag_key'", id) + } + parts := strings.SplitN(id, "/", 2) + projectKey, flagKey = parts[0], parts[1] + return projectKey, flagKey, nil +} diff --git a/launchdarkly/keys.go b/launchdarkly/keys.go index 778b1ecd..ba671c39 100644 --- a/launchdarkly/keys.go +++ b/launchdarkly/keys.go @@ -3,70 +3,72 @@ package launchdarkly const ( // keys used in terraform files referencing keys in launchdarkly resource objects. // The name of each constant is the same as its value. - PROJECT_KEY = "project_key" - ENV_KEY = "env_key" - KEY = "key" - FLAG_ID = "flag_id" - NAME = "name" - TAGS = "tags" - ENVIRONMENTS = "environments" - API_KEY = "api_key" - MOBILE_KEY = "mobile_key" - CLIENT_SIDE_ID = "client_side_id" - COLOR = "color" - DEFAULT_TTL = "default_ttl" - SECURE_MODE = "secure_mode" - DEFAULT_TRACK_EVENTS = "default_track_events" - REQUIRE_COMMENTS = "require_comments" - CONFIRM_CHANGES = "confirm_changes" - DESCRIPTION = "description" - MAINTAINER_ID = "maintainer_id" - VARIATION_TYPE = "variation_type" - VARIATIONS = "variations" - TEMPORARY = "temporary" - INCLUDE_IN_SNIPPET = "include_in_snippet" - VALUE = "value" - URL = "url" - SECRET = "secret" - ENABLED = "enabled" - RESOURCES = "resources" - NOT_RESOURCES = "not_resources" - ACTIONS = "actions" - NOT_ACTIONS = "not_actions" - EFFECT = "effect" - POLICY = "policy" - POLICY_STATEMENTS = "policy_statements" - EXCLUDED = "excluded" - INCLUDED = "included" - CUSTOM_PROPERTIES = "custom_properties" - EMAIL = "email" - FIRST_NAME = "first_name" - LAST_NAME = "last_name" - ROLE = "role" - CUSTOM_ROLES = "custom_roles" - RULES = "rules" - ATTRIBUTE = "attribute" - OP = "op" - VALUES = "values" - NEGATE = "negate" - CLAUSES = "clauses" - WEIGHT = "weight" - BUCKET_BY = "bucket_by" - ROLLOUT_WEIGHTS = "rollout_weights" - VARIATION = "variation" - USER_TARGETS = "user_targets" - PREREQUISITES = "prerequisites" - FLAG_KEY = "flag_key" - TARGETING_ENABLED = "targeting_enabled" - TRACK_EVENTS = "track_events" - OFF_VARIATION = "off_variation" - FLAG_FALLTHROUGH = "flag_fallthrough" - KIND = "kind" - CONFIG = "config" - DEFAULT_ON_VARIATION = "default_on_variation" - DEFAULT_OFF_VARIATION = "default_off_variation" - SERVICE_TOKEN = "service_token" - DEFAULT_API_VERSION = "default_api_version" - TOKEN = "token" - EXPIRE = "expire" + PROJECT_KEY = "project_key" + ENV_KEY = "env_key" + KEY = "key" + FLAG_ID = "flag_id" + NAME = "name" + TAGS = "tags" + ENVIRONMENTS = "environments" + API_KEY = "api_key" + MOBILE_KEY = "mobile_key" + CLIENT_SIDE_ID = "client_side_id" + COLOR = "color" + DEFAULT_TTL = "default_ttl" + SECURE_MODE = "secure_mode" + DEFAULT_TRACK_EVENTS = "default_track_events" + REQUIRE_COMMENTS = "require_comments" + CONFIRM_CHANGES = "confirm_changes" + DESCRIPTION = "description" + MAINTAINER_ID = "maintainer_id" + VARIATION_TYPE = "variation_type" + VARIATIONS = "variations" + TEMPORARY = "temporary" + INCLUDE_IN_SNIPPET = "include_in_snippet" + VALUE = "value" + URL = "url" + SECRET = "secret" + ENABLED = "enabled" + RESOURCES = "resources" + NOT_RESOURCES = "not_resources" + ACTIONS = "actions" + NOT_ACTIONS = "not_actions" + EFFECT = "effect" + POLICY = "policy" + POLICY_STATEMENTS = "policy_statements" + EXCLUDED = "excluded" + INCLUDED = "included" + CUSTOM_PROPERTIES = "custom_properties" + EMAIL = "email" + FIRST_NAME = "first_name" + LAST_NAME = "last_name" + ROLE = "role" + CUSTOM_ROLES = "custom_roles" + RULES = "rules" + ATTRIBUTE = "attribute" + OP = "op" + VALUES = "values" + NEGATE = "negate" + CLAUSES = "clauses" + WEIGHT = "weight" + BUCKET_BY = "bucket_by" + ROLLOUT_WEIGHTS = "rollout_weights" + VARIATION = "variation" + USER_TARGETS = "user_targets" + PREREQUISITES = "prerequisites" + FLAG_KEY = "flag_key" + TARGETING_ENABLED = "targeting_enabled" + TRACK_EVENTS = "track_events" + OFF_VARIATION = "off_variation" + FLAG_FALLTHROUGH = "flag_fallthrough" + KIND = "kind" + CONFIG = "config" + DEFAULT_ON_VARIATION = "default_on_variation" + DEFAULT_OFF_VARIATION = "default_off_variation" + SERVICE_TOKEN = "service_token" + DEFAULT_API_VERSION = "default_api_version" + TOKEN = "token" + EXPIRE = "expire" + ID = "id" + CLIENT_SIDE_AVAILABILITY = "client_side_availability" ) diff --git a/launchdarkly/policy_statements_helper_test.go b/launchdarkly/policy_statements_helper_test.go index 9dc00ca4..0c449143 100644 --- a/launchdarkly/policy_statements_helper_test.go +++ b/launchdarkly/policy_statements_helper_test.go @@ -27,7 +27,7 @@ func TestPolicyStatementsRoundTripConversion(t *testing.T) { }, }, expected: []ldapi.Statement{ - ldapi.Statement{ + { Resources: []string{"proj/*"}, Actions: []string{"*"}, Effect: "allow", @@ -51,12 +51,12 @@ func TestPolicyStatementsRoundTripConversion(t *testing.T) { }, }, expected: []ldapi.Statement{ - ldapi.Statement{ + { Resources: []string{"proj/*:env/*;qa_*"}, Actions: []string{"*"}, Effect: "allow", }, - ldapi.Statement{ + { Resources: []string{"proj/*:env/*;qa_*:/flag/*"}, Actions: []string{"*"}, Effect: "allow", @@ -75,7 +75,7 @@ func TestPolicyStatementsRoundTripConversion(t *testing.T) { }, }, expected: []ldapi.Statement{ - ldapi.Statement{ + { NotResources: []string{"proj/*:env/production:flag/*"}, Actions: []string{"*"}, Effect: "allow", diff --git a/launchdarkly/project_helper.go b/launchdarkly/project_helper.go new file mode 100644 index 00000000..53dacafd --- /dev/null +++ b/launchdarkly/project_helper.go @@ -0,0 +1,80 @@ +package launchdarkly + +import ( + "fmt" + "log" + "net/http" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ldapi "github.com/launchdarkly/api-client-go" +) + +func projectRead(d *schema.ResourceData, meta interface{}, isDataSource bool) error { + client := meta.(*Client) + projectKey := d.Get(KEY).(string) + + rawProject, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.ProjectsApi.GetProject(client.ctx, projectKey) + }) + // return nil error for resource reads but 404 for data source reads + if isStatusNotFound(res) && !isDataSource { + log.Printf("[WARN] failed to find project with key %q, removing from state if present", projectKey) + d.SetId("") + return nil + } + if err != nil { + return fmt.Errorf("failed to get project with key %q: %v", projectKey, err) + } + + project := rawProject.(ldapi.Project) + // the Id needs to be set on reads for the data source, but it will mess up the state for resource reads + if isDataSource { + d.SetId(project.Id) + } + _ = d.Set(KEY, project.Key) + _ = d.Set(NAME, project.Name) + + // Only allow nested environments for the launchdarkly_project resource. The dedicated environment data source + // should be used if a data source is required for a LaunchDarkly environment + if !isDataSource { + // Convert the returned environment list to a map so we can lookup each environment by key while preserving the + // order defined in the config + envMap := environmentsToResourceDataMap(project.Environments) + + // iterate over the environment keys in the order defined by the config and look up the environment returned by + // LD's API + rawEnvs := d.Get(ENVIRONMENTS).([]interface{}) + envConfigKeys := rawEnvironmentConfigsToKeyList(rawEnvs) + environments := make([]interface{}, 0, len(envConfigKeys)) + for _, envKey := range envConfigKeys { + environments = append(environments, envMap[envKey]) + } + + err = d.Set(ENVIRONMENTS, environments) + if err != nil { + return fmt.Errorf("could not set environments on project with key %q: %v", project.Key, err) + } + } + + err = d.Set(TAGS, project.Tags) + if err != nil { + return fmt.Errorf("could not set tags on project with key %q: %v", project.Key, err) + } + if isDataSource { + defaultCSA := *project.DefaultClientSideAvailability + clientSideAvailability := map[string]string{ + "using_environment_id": fmt.Sprintf("%v", defaultCSA.UsingEnvironmentId), + "using_mobile_key": fmt.Sprintf("%v", defaultCSA.UsingMobileKey), + } + err = d.Set(CLIENT_SIDE_AVAILABILITY, clientSideAvailability) + if err != nil { + return fmt.Errorf("could not set client_side_availability on project with key %q: %v", project.Key, err) + } + } else { + err = d.Set(INCLUDE_IN_SNIPPET, project.IncludeInSnippetByDefault) + if err != nil { + return fmt.Errorf("could not set include_in_snippet on project with key %q: %v", project.Key, err) + } + } + return nil +} diff --git a/launchdarkly/provider.go b/launchdarkly/provider.go index 7c9ed5be..77d01fdb 100644 --- a/launchdarkly/provider.go +++ b/launchdarkly/provider.go @@ -57,7 +57,13 @@ func Provider() terraform.ResourceProvider { "launchdarkly_access_token": resourceAccessToken(), }, DataSourcesMap: map[string]*schema.Resource{ - "launchdarkly_team_member": dataSourceTeamMember(), + "launchdarkly_team_member": dataSourceTeamMember(), + "launchdarkly_project": dataSourceProject(), + "launchdarkly_environment": dataSourceEnvironment(), + "launchdarkly_feature_flag": dataSourceFeatureFlag(), + "launchdarkly_feature_flag_environment": dataSourceFeatureFlagEnvironment(), + "launchdarkly_webhook": dataSourceWebhook(), + "launchdarkly_segment": dataSourceSegment(), }, ConfigureFunc: providerConfigure, } diff --git a/launchdarkly/resource_launchdarkly_access_token.go b/launchdarkly/resource_launchdarkly_access_token.go index 52ef66af..cae7bf50 100644 --- a/launchdarkly/resource_launchdarkly_access_token.go +++ b/launchdarkly/resource_launchdarkly_access_token.go @@ -226,8 +226,8 @@ func resourceAccessTokenUpdate(d *schema.ResourceData, metaRaw interface{}) erro if err != nil { return fmt.Errorf("failed to reset access token with id %q: %s", accessTokenID, handleLdapiErr(err)) } - d.Set(EXPIRE, newExpire) - d.Set(TOKEN, token.Token) + _ = d.Set(EXPIRE, newExpire) + _ = d.Set(TOKEN, token.Token) } } diff --git a/launchdarkly/resource_launchdarkly_environment.go b/launchdarkly/resource_launchdarkly_environment.go index def6704e..0e72b48c 100644 --- a/launchdarkly/resource_launchdarkly_environment.go +++ b/launchdarkly/resource_launchdarkly_environment.go @@ -2,7 +2,6 @@ package launchdarkly import ( "fmt" - "log" "net/http" "strings" @@ -11,7 +10,7 @@ import ( ) func resourceEnvironment() *schema.Resource { - envSchema := environmentSchema() + envSchema := environmentSchema(false) envSchema[PROJECT_KEY] = &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -70,37 +69,7 @@ func resourceEnvironmentCreate(d *schema.ResourceData, metaRaw interface{}) erro } func resourceEnvironmentRead(d *schema.ResourceData, metaRaw interface{}) error { - client := metaRaw.(*Client) - projectKey := d.Get(PROJECT_KEY).(string) - key := d.Get(KEY).(string) - - envRaw, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { - return client.ld.EnvironmentsApi.GetEnvironment(client.ctx, projectKey, key) - }) - env := envRaw.(ldapi.Environment) - if isStatusNotFound(res) { - log.Printf("[WARN] failed to find environment with key %q in project %q, removing from state", key, projectKey) - d.SetId("") - return nil - } - if err != nil { - return fmt.Errorf("failed to get environment with key %q for project key: %q: %v", key, projectKey, handleLdapiErr(err)) - } - - d.SetId(projectKey + "/" + key) - _ = d.Set(key, env.Key) - _ = d.Set(NAME, env.Name) - _ = d.Set(API_KEY, env.ApiKey) - _ = d.Set(MOBILE_KEY, env.MobileKey) - _ = d.Set(CLIENT_SIDE_ID, env.Id) - _ = d.Set(COLOR, env.Color) - _ = d.Set(DEFAULT_TTL, int(env.DefaultTtl)) - _ = d.Set(SECURE_MODE, env.SecureMode) - _ = d.Set(DEFAULT_TRACK_EVENTS, env.DefaultTrackEvents) - _ = d.Set(TAGS, env.Tags) - _ = d.Set(REQUIRE_COMMENTS, env.RequireComments) - _ = d.Set(CONFIRM_CHANGES, env.ConfirmChanges) - return nil + return environmentRead(d, metaRaw, false) } func resourceEnvironmentUpdate(d *schema.ResourceData, metaRaw interface{}) error { @@ -160,17 +129,28 @@ func resourceEnvironmentExists(d *schema.ResourceData, metaRaw interface{}) (boo } func environmentExists(projectKey string, key string, meta *Client) (bool, error) { - _, res, err := meta.ld.EnvironmentsApi.GetEnvironment(meta.ctx, projectKey, key) + _, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return meta.ld.EnvironmentsApi.GetEnvironment(meta.ctx, projectKey, key) + }) if isStatusNotFound(res) { return false, nil } if err != nil { - return false, fmt.Errorf("failed to get project with key %q for project %q: %v", key, projectKey, handleLdapiErr(err)) + return false, fmt.Errorf("failed to get environment with key %q for project %q: %v", key, projectKey, handleLdapiErr(err)) } return true, nil } +func environmentExistsInProject(project ldapi.Project, envKey string) bool { + for _, env := range project.Environments { + if env.Key == envKey { + return true + } + } + return false +} + func resourceEnvironmentImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { id := d.Id() diff --git a/launchdarkly/resource_launchdarkly_feature_flag.go b/launchdarkly/resource_launchdarkly_feature_flag.go index 4230be81..87ae815b 100644 --- a/launchdarkly/resource_launchdarkly_feature_flag.go +++ b/launchdarkly/resource_launchdarkly_feature_flag.go @@ -2,15 +2,20 @@ package launchdarkly import ( "fmt" - "log" "net/http" - "strings" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ldapi "github.com/launchdarkly/api-client-go" ) func resourceFeatureFlag() *schema.Resource { + schemaMap := baseFeatureFlagSchema() + schemaMap[NAME] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The feature flag's description", + } + schemaMap[VARIATION_TYPE] = variationTypeSchema() return &schema.Resource{ Create: resourceFeatureFlagCreate, Read: resourceFeatureFlagRead, @@ -21,61 +26,7 @@ func resourceFeatureFlag() *schema.Resource { Importer: &schema.ResourceImporter{ State: resourceFeatureFlagImport, }, - - Schema: map[string]*schema.Schema{ - PROJECT_KEY: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: "The feature flag's project key", - ValidateFunc: validateKey(), - }, - KEY: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validateKey(), - Description: "The human-readable name of the feature flag", - }, - NAME: { - Type: schema.TypeString, - Required: true, - Description: "The feature flag's description", - }, - MAINTAINER_ID: { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validateID(), - }, - DESCRIPTION: { - Type: schema.TypeString, - Optional: true, - }, - VARIATION_TYPE: variationTypeSchema(), - VARIATIONS: variationsSchema(), - TEMPORARY: { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - INCLUDE_IN_SNIPPET: { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - TAGS: tagsSchema(), - CUSTOM_PROPERTIES: customPropertiesSchema(), - DEFAULT_ON_VARIATION: { - Type: schema.TypeString, - Optional: true, - Description: "The value of the variation served when the flag is on for new environments", - }, - DEFAULT_OFF_VARIATION: { - Type: schema.TypeString, - Optional: true, - Description: "The value of the variation served when the flag is off for new environments", - }, - }, + Schema: schemaMap, } } @@ -144,80 +95,7 @@ func resourceFeatureFlagCreate(d *schema.ResourceData, metaRaw interface{}) erro } func resourceFeatureFlagRead(d *schema.ResourceData, metaRaw interface{}) error { - client := metaRaw.(*Client) - projectKey := d.Get(PROJECT_KEY).(string) - key := d.Get(KEY).(string) - - flagRaw, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { - return client.ld.FeatureFlagsApi.GetFeatureFlag(client.ctx, projectKey, key, nil) - }) - flag := flagRaw.(ldapi.FeatureFlag) - if isStatusNotFound(res) { - log.Printf("[WARN] feature flag %q in project %q not found, removing from state", key, projectKey) - d.SetId("") - return nil - } - - if err != nil { - return fmt.Errorf("failed to get flag %q of project %q: %s", key, projectKey, handleLdapiErr(err)) - } - - transformedCustomProperties := customPropertiesToResourceData(flag.CustomProperties) - _ = d.Set(key, flag.Key) - _ = d.Set(NAME, flag.Name) - _ = d.Set(DESCRIPTION, flag.Description) - _ = d.Set(INCLUDE_IN_SNIPPET, flag.IncludeInSnippet) - _ = d.Set(TEMPORARY, flag.Temporary) - - // Only set the maintainer ID if is specified in the schema - _, ok := d.GetOk(MAINTAINER_ID) - if ok { - _ = d.Set(MAINTAINER_ID, flag.MaintainerId) - } - - variationType, err := variationsToVariationType(flag.Variations) - if err != nil { - return fmt.Errorf("failed to determine variation type on flag with key %q: %v", flag.Key, err) - } - err = d.Set(VARIATION_TYPE, variationType) - if err != nil { - return fmt.Errorf("failed to set variation type on flag with key %q: %v", flag.Key, err) - } - - parsedVariations, err := variationsToResourceData(flag.Variations, variationType) - if err != nil { - return fmt.Errorf("failed to parse variations on flag with key %q: %v", flag.Key, err) - } - err = d.Set(VARIATIONS, parsedVariations) - if err != nil { - return fmt.Errorf("failed to set variations on flag with key %q: %v", flag.Key, err) - } - - err = d.Set(TAGS, flag.Tags) - if err != nil { - return fmt.Errorf("failed to set tags on flag with key %q: %v", flag.Key, err) - } - - err = d.Set(CUSTOM_PROPERTIES, transformedCustomProperties) - if err != nil { - return fmt.Errorf("failed to set custom properties on flag with key %q: %v", flag.Key, err) - } - - if flag.Defaults != nil { - onValue, err := variationValueToString(flag.Variations[flag.Defaults.OnVariation].Value, variationType) - if err != nil { - return err - } - _ = d.Set(DEFAULT_ON_VARIATION, onValue) - offValue, err := variationValueToString(flag.Variations[flag.Defaults.OffVariation].Value, variationType) - if err != nil { - return err - } - _ = d.Set(DEFAULT_OFF_VARIATION, offValue) - } - - d.SetId(projectKey + "/" + key) - return nil + return featureFlagRead(d, metaRaw, false) } func resourceFeatureFlagUpdate(d *schema.ResourceData, metaRaw interface{}) error { @@ -319,12 +197,3 @@ func resourceFeatureFlagImport(d *schema.ResourceData, meta interface{}) ([]*sch return []*schema.ResourceData{d}, nil } - -func flagIdToKeys(id string) (projectKey string, flagKey string, err error) { - if strings.Count(id, "/") != 1 { - return "", "", fmt.Errorf("found unexpected flag id format: %q expected format: 'project_key/flag_key'", id) - } - parts := strings.SplitN(id, "/", 2) - projectKey, flagKey = parts[0], parts[1] - return projectKey, flagKey, nil -} diff --git a/launchdarkly/resource_launchdarkly_feature_flag_environment.go b/launchdarkly/resource_launchdarkly_feature_flag_environment.go index 562b7f2e..d15702a7 100644 --- a/launchdarkly/resource_launchdarkly_feature_flag_environment.go +++ b/launchdarkly/resource_launchdarkly_feature_flag_environment.go @@ -7,7 +7,6 @@ import ( "strings" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" ldapi "github.com/launchdarkly/api-client-go" ) @@ -21,40 +20,7 @@ func resourceFeatureFlagEnvironment() *schema.Resource { Importer: &schema.ResourceImporter{ State: resourceFeatureFlagEnvironmentImport, }, - Schema: map[string]*schema.Schema{ - FLAG_ID: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validateFlagID, - }, - ENV_KEY: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validateKey(), - }, - TARGETING_ENABLED: { - Type: schema.TypeBool, - Optional: true, - Computed: true, - }, - USER_TARGETS: targetsSchema(), - RULES: rulesSchema(), - PREREQUISITES: prerequisitesSchema(), - FLAG_FALLTHROUGH: fallthroughSchema(), - TRACK_EVENTS: { - Type: schema.TypeBool, - Optional: true, - Computed: true, - }, - OFF_VARIATION: { - Type: schema.TypeInt, - Optional: true, - Computed: true, - ValidateFunc: validation.IntAtLeast(0), - }, - }, + Schema: baseFeatureFlagEnvironmentSchema(), } } @@ -103,7 +69,10 @@ func resourceFeatureFlagEnvironmentCreate(d *schema.ResourceData, metaRaw interf patches = append(patches, patchReplace(patchFlagEnvPath(d, "on"), enabled.(bool))) } - offVariation, ok := d.GetOk(OFF_VARIATION) + // GetOKExists is marked deprecated by Hashicorp, however it seems to be the only solution for setting the + // offVariation to 0 during creation. According to Hashicorp, it will not be removed until a replacement function is + // implemented. https://github.com/hashicorp/terraform-plugin-sdk/pull/350#issuecomment-597888969 + offVariation, ok := d.GetOkExists(OFF_VARIATION) if ok { patches = append(patches, patchReplace(patchFlagEnvPath(d, "offVariation"), offVariation.(int))) } @@ -165,58 +134,7 @@ func resourceFeatureFlagEnvironmentCreate(d *schema.ResourceData, metaRaw interf } func resourceFeatureFlagEnvironmentRead(d *schema.ResourceData, metaRaw interface{}) error { - client := metaRaw.(*Client) - flagId := d.Get(FLAG_ID).(string) - projectKey, flagKey, err := flagIdToKeys(flagId) - if err != nil { - return err - } - envKey := d.Get(ENV_KEY).(string) - - flagRaw, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { - return client.ld.FeatureFlagsApi.GetFeatureFlag(client.ctx, projectKey, flagKey, nil) - }) - flag := flagRaw.(ldapi.FeatureFlag) - if isStatusNotFound(res) { - log.Printf("[WARN] failed to find flag %q in project %q, removing from state", flagKey, projectKey) - d.SetId("") - return nil - } - - if err != nil { - return fmt.Errorf("failed to get flag %q of project %q: %s", flagKey, projectKey, handleLdapiErr(err)) - } - - environment, ok := flag.Environments[envKey] - if !ok { - log.Printf("[WARN] failed to find environment %q for flag %q, removing from state", envKey, flagKey) - d.SetId("") - return nil - } - - _ = d.Set(KEY, flag.Key) - - // Computed values are set even if they do not exist on the config - _ = d.Set(TARGETING_ENABLED, environment.On) - _ = d.Set(OFF_VARIATION, environment.OffVariation) - _ = d.Set(TRACK_EVENTS, environment.TrackEvents) - _ = d.Set(PREREQUISITES, prerequisitesToResourceData(environment.Prerequisites)) - - err = d.Set(RULES, rulesToResourceData(environment.Rules)) - if err != nil { - return fmt.Errorf("failed to set rules on flag with key %q: %v", flagKey, err) - } - - err = d.Set(USER_TARGETS, targetsToResourceData(environment.Targets)) - if err != nil { - return fmt.Errorf("failed to set targets on flag with key %q: %v", flagKey, err) - } - - err = d.Set(FLAG_FALLTHROUGH, fallthroughToResourceData(environment.Fallthrough_)) - if err != nil { - return fmt.Errorf("failed to set flag fallthrough on flag with key %q: %v", flagKey, err) - } - return nil + return featureFlagEnvironmentRead(d, metaRaw, false) } func resourceFeatureFlagEnvironmentUpdate(d *schema.ResourceData, metaRaw interface{}) error { @@ -350,11 +268,3 @@ func resourceFeatureFlagEnvironmentImport(d *schema.ResourceData, meta interface return []*schema.ResourceData{d}, nil } - -func patchFlagEnvPath(d *schema.ResourceData, op string) string { - path := []string{"/environments"} - path = append(path, d.Get(ENV_KEY).(string)) - path = append(path, op) - - return strings.Join(path, "/") -} diff --git a/launchdarkly/resource_launchdarkly_feature_flag_environment_test.go b/launchdarkly/resource_launchdarkly_feature_flag_environment_test.go index fa186fcb..a18fc719 100644 --- a/launchdarkly/resource_launchdarkly_feature_flag_environment_test.go +++ b/launchdarkly/resource_launchdarkly_feature_flag_environment_test.go @@ -120,6 +120,31 @@ resource "launchdarkly_feature_flag_environment" "basic" { bucket_by = "email" } } +` + testAccFeatureFlagEnvironmentJSONVariations = ` +resource "launchdarkly_feature_flag" "json" { + project_key = launchdarkly_project.test.key + key = "json-flag" + name = "json flag" + variation_type = "json" + variations { + value = jsonencode({ "foo" : "bar" }) + } + variations { + value = jsonencode({ "bar" : "foo", "bars" : "foos" }) + } +} + +resource "launchdarkly_feature_flag_environment" "json_variations" { + flag_id = launchdarkly_feature_flag.json.id + env_key = "test" + + flag_fallthrough { + variation = 1 + } + + off_variation = 0 +} ` testAccFeatureFlagEnvironmentPrereq = ` @@ -388,6 +413,34 @@ func TestAccFeatureFlagEnvironment_Update(t *testing.T) { }) } +func TestAccFeatureFlagEnvironment_JSON_variations(t *testing.T) { + projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + resourceName := "launchdarkly_feature_flag_environment.json_variations" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: withRandomProject(projectKey, testAccFeatureFlagEnvironmentJSONVariations), + Check: resource.ComposeTestCheckFunc( + testAccCheckFeatureFlagEnvironmentExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "targeting_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "flag_fallthrough.#", "1"), + resource.TestCheckResourceAttr(resourceName, "flag_fallthrough.0.variation", "1"), + resource.TestCheckResourceAttr(resourceName, "off_variation", "0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccFeatureFlagEnvironment_InvalidBucketBy(t *testing.T) { projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) // resourceName := "launchdarkly_feature_flag_environment.invalid_bucket_by" diff --git a/launchdarkly/resource_launchdarkly_feature_flag_test.go b/launchdarkly/resource_launchdarkly_feature_flag_test.go index 2a0ec0d0..ca224c06 100644 --- a/launchdarkly/resource_launchdarkly_feature_flag_test.go +++ b/launchdarkly/resource_launchdarkly_feature_flag_test.go @@ -767,7 +767,7 @@ func TestAccFeatureFlag_UpdateMultivariate(t *testing.T) { }) } -func TestAcccFeatureFlag_DefaultsInvalid(t *testing.T) { +func TestAccFeatureFlag_DefaultsInvalid(t *testing.T) { projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { diff --git a/launchdarkly/resource_launchdarkly_project.go b/launchdarkly/resource_launchdarkly_project.go index e02cc331..cabdb0ae 100644 --- a/launchdarkly/resource_launchdarkly_project.go +++ b/launchdarkly/resource_launchdarkly_project.go @@ -32,14 +32,17 @@ func resourceProject() *schema.Resource { Type: schema.TypeString, Required: true, }, + INCLUDE_IN_SNIPPET: { + Type: schema.TypeBool, + Optional: true, + }, TAGS: tagsSchema(), ENVIRONMENTS: { - Type: schema.TypeList, - Optional: true, - Computed: true, - Deprecated: "The 'environments' attribute is now deprecated. Please use the launchdarkly_environment resource to maintain future compatability.", + Type: schema.TypeList, + Optional: true, + Computed: false, Elem: &schema.Resource{ - Schema: environmentSchema(), + Schema: environmentSchema(true), }, }, }, @@ -78,35 +81,7 @@ func resourceProjectCreate(d *schema.ResourceData, metaRaw interface{}) error { } func resourceProjectRead(d *schema.ResourceData, metaRaw interface{}) error { - client := metaRaw.(*Client) - projectKey := d.Get(KEY).(string) - - rawProject, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { - return client.ld.ProjectsApi.GetProject(client.ctx, projectKey) - }) - project := rawProject.(ldapi.Project) - if isStatusNotFound(res) { - log.Printf("[WARN] failed to find project with key %q, removing from state", projectKey) - d.SetId("") - return nil - } - if err != nil { - return fmt.Errorf("failed to get project with key %q: %v", projectKey, err) - } - - _ = d.Set(KEY, project.Key) - _ = d.Set(NAME, project.Name) - - envsRaw := environmentsToResourceData(project.Environments) - err = d.Set(ENVIRONMENTS, envsRaw) - if err != nil { - return fmt.Errorf("could not set environments on project with key %q: %v", project.Key, err) - } - err = d.Set(TAGS, project.Tags) - if err != nil { - return fmt.Errorf("could not set tags on project with key %q: %v", project.Key, err) - } - return nil + return projectRead(d, metaRaw, false) } func resourceProjectUpdate(d *schema.ResourceData, metaRaw interface{}) error { @@ -114,10 +89,12 @@ func resourceProjectUpdate(d *schema.ResourceData, metaRaw interface{}) error { projectKey := d.Get(KEY).(string) projName := d.Get(NAME) projTags := stringsFromResourceData(d, TAGS) + includeInSnippet := d.Get(INCLUDE_IN_SNIPPET) patch := []ldapi.PatchOperation{ patchReplace("/name", &projName), patchReplace("/tags", &projTags), + patchReplace("/includeInSnippetByDefault", includeInSnippet), } _, _, err := handleRateLimit(func() (interface{}, *http.Response, error) { @@ -129,46 +106,43 @@ func resourceProjectUpdate(d *schema.ResourceData, metaRaw interface{}) error { return fmt.Errorf("failed to update project with key %q: %s", projectKey, handleLdapiErr(err)) } // Update environments if necessary - schemaEnvs := d.Get(ENVIRONMENTS).([]interface{}) - for _, env := range schemaEnvs { - envMap := env.(map[string]interface{}) - envKey := envMap[KEY].(string) - - // we already posted the projectKey, name, color, and default_ttl, so we skip patching those fields. - envName := envMap[NAME].(string) - envColor := envMap[COLOR].(string) - patch := []ldapi.PatchOperation{ - patchReplace("/name", envName), - patchReplace("/color", envColor), - } - - // optional fields: - if defaultTTL, ok := envMap[DEFAULT_TTL]; ok { - patch = append(patch, patchReplace("/defaultTtl", defaultTTL.(int))) - } - - if secureMode, ok := envMap[SECURE_MODE]; ok { - patch = append(patch, patchReplace("/secureMode", &secureMode)) - } - - if defaultTrackEvents, ok := envMap[DEFAULT_TRACK_EVENTS]; ok { - patch = append(patch, patchReplace("/defaultTrackEvents", &defaultTrackEvents)) - } - - if envTagsSet, ok := envMap[TAGS].(*schema.Set); ok { - envTags := stringsFromSchemaSet(envTagsSet) - patch = append(patch, patchReplace("/tags", &envTags)) + schemaEnvList, environmentsFound := d.GetOk(ENVIRONMENTS) + if environmentsFound { + // Get the project so we can see if we need to create any environments or just update existing environments + rawProject, _, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.ProjectsApi.GetProject(client.ctx, projectKey) + }) + if err != nil { + return fmt.Errorf("failed to load project %q before updating environments: %s", projectKey, handleLdapiErr(err)) } + project := rawProject.(ldapi.Project) + + environmentConfigs := schemaEnvList.([]interface{}) + for _, env := range environmentConfigs { + envConfig := env.(map[string]interface{}) + envKey := envConfig[KEY].(string) + // Check if the environment already exists. If it does not exist, create it + exists := environmentExistsInProject(project, envKey) + if !exists { + envPost := environmentPostFromResourceData(env) + _, _, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.EnvironmentsApi.PostEnvironment(client.ctx, projectKey, envPost) + }) + if err != nil { + return fmt.Errorf("failed to create environment %q in project %q: %s", envKey, projectKey, handleLdapiErr(err)) + } + } - if len(patch) > 0 { - _, _, err := handleRateLimit(func() (interface{}, *http.Response, error) { + patches := getEnvironmentUpdatePatches(envConfig) + _, _, err = handleRateLimit(func() (interface{}, *http.Response, error) { return handleNoConflict(func() (interface{}, *http.Response, error) { - return client.ld.EnvironmentsApi.PatchEnvironment(client.ctx, projectKey, envKey, patch) + return client.ld.EnvironmentsApi.PatchEnvironment(client.ctx, projectKey, envKey, patches) }) }) if err != nil { return fmt.Errorf("failed to update environment with key %q for project: %q: %+v", envKey, projectKey, err) } + } } diff --git a/launchdarkly/resource_launchdarkly_project_test.go b/launchdarkly/resource_launchdarkly_project_test.go index fbbbfac6..823d9711 100644 --- a/launchdarkly/resource_launchdarkly_project_test.go +++ b/launchdarkly/resource_launchdarkly_project_test.go @@ -23,6 +23,7 @@ resource "launchdarkly_project" "test" { resource "launchdarkly_project" "test" { key = "%s" name = "awesome test project" + include_in_snippet = true tags = [] } ` @@ -47,8 +48,20 @@ resource "launchdarkly_project" "env_test" { environments { key = "test-env" name = "test environment updated" - color = "FFFFFF" - tags = ["updated"] + color = "AAAAAA" + tags = ["terraform", "test", "updated"] + default_ttl = 30 + secure_mode = true + default_track_events = true + require_comments = true + confirm_changes = true + } + + environments { + key = "new-env" + name = "New test environment" + color = "EEEEEE" + tags = ["new"] } } ` @@ -110,13 +123,14 @@ func TestAccProject_Update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "key", projectKey), resource.TestCheckResourceAttr(resourceName, "name", "awesome test project"), resource.TestCheckResourceAttr(resourceName, "tags.#", "0"), + resource.TestCheckResourceAttr(resourceName, "include_in_snippet", "true"), ), }, }, }) } -func TestAccProject_WithEnvironment(t *testing.T) { +func TestAccProject_WithEnvironments(t *testing.T) { projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) resourceName := "launchdarkly_project.env_test" resource.ParallelTest(t, resource.TestCase{ @@ -134,19 +148,53 @@ func TestAccProject_WithEnvironment(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "environments.#", "1"), resource.TestCheckResourceAttr(resourceName, "environments.0.name", "test environment"), resource.TestCheckResourceAttr(resourceName, "environments.0.tags.#", "2"), + resource.TestCheckResourceAttr(resourceName, "environments.0.color", "000000"), + + // default environment values + resource.TestCheckResourceAttr(resourceName, "environments.0.default_ttl", "0"), + resource.TestCheckResourceAttr(resourceName, "environments.0.secure_mode", "false"), + resource.TestCheckResourceAttr(resourceName, "environments.0.default_track_events", "false"), + resource.TestCheckResourceAttr(resourceName, "environments.0.require_comments", "false"), + resource.TestCheckResourceAttr(resourceName, "environments.0.confirm_changes", "false"), ), }, + { + ResourceName: resourceName, + ImportState: true, + }, { Config: fmt.Sprintf(testAccProjectWithEnvironmentUpdate, projectKey), Check: resource.ComposeTestCheckFunc( testAccCheckProjectExists(resourceName), resource.TestCheckResourceAttr(resourceName, "key", projectKey), resource.TestCheckResourceAttr(resourceName, "name", "test project"), - resource.TestCheckResourceAttr(resourceName, "environments.#", "1"), + resource.TestCheckResourceAttr(resourceName, "environments.#", "2"), + + // Check environment 0 was updated resource.TestCheckResourceAttr(resourceName, "environments.0.name", "test environment updated"), - resource.TestCheckResourceAttr(resourceName, "environments.0.tags.#", "1"), + resource.TestCheckResourceAttr(resourceName, "environments.0.tags.#", "3"), + resource.TestCheckResourceAttr(resourceName, "environments.0.color", "AAAAAA"), + resource.TestCheckResourceAttr(resourceName, "environments.0.default_ttl", "30"), + resource.TestCheckResourceAttr(resourceName, "environments.0.secure_mode", "true"), + resource.TestCheckResourceAttr(resourceName, "environments.0.default_track_events", "true"), + resource.TestCheckResourceAttr(resourceName, "environments.0.require_comments", "true"), + resource.TestCheckResourceAttr(resourceName, "environments.0.confirm_changes", "true"), + + // Check environment 1 is created + resource.TestCheckResourceAttr(resourceName, "environments.1.name", "New test environment"), + resource.TestCheckResourceAttr(resourceName, "environments.1.tags.#", "1"), + resource.TestCheckResourceAttr(resourceName, "environments.1.color", "EEEEEE"), + resource.TestCheckResourceAttr(resourceName, "environments.1.default_ttl", "0"), + resource.TestCheckResourceAttr(resourceName, "environments.1.secure_mode", "false"), + resource.TestCheckResourceAttr(resourceName, "environments.1.default_track_events", "false"), + resource.TestCheckResourceAttr(resourceName, "environments.1.require_comments", "false"), + resource.TestCheckResourceAttr(resourceName, "environments.1.confirm_changes", "false"), ), }, + { + ResourceName: resourceName, + ImportState: true, + }, }, }) } diff --git a/launchdarkly/resource_launchdarkly_segment.go b/launchdarkly/resource_launchdarkly_segment.go index cbe35282..9059376a 100644 --- a/launchdarkly/resource_launchdarkly_segment.go +++ b/launchdarkly/resource_launchdarkly_segment.go @@ -2,7 +2,6 @@ package launchdarkly import ( "fmt" - "log" "net/http" "strings" @@ -11,6 +10,29 @@ import ( ) func resourceSegment() *schema.Resource { + schemaMap := baseSegmentSchema() + schemaMap[PROJECT_KEY] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateKey(), + } + schemaMap[ENV_KEY] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateKey(), + } + schemaMap[KEY] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateKey(), + } + schemaMap[NAME] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + } return &schema.Resource{ Create: resourceSegmentCreate, Read: resourceSegmentRead, @@ -22,46 +44,7 @@ func resourceSegment() *schema.Resource { State: resourceSegmentImport, }, - Schema: map[string]*schema.Schema{ - PROJECT_KEY: { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validateKey(), - }, - ENV_KEY: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validateKey(), - }, - KEY: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validateKey(), - }, - NAME: { - Type: schema.TypeString, - Required: true, - }, - DESCRIPTION: { - Type: schema.TypeString, - Optional: true, - }, - TAGS: tagsSchema(), - INCLUDED: { - Type: schema.TypeList, - Elem: &schema.Schema{Type: schema.TypeString}, - Optional: true, - }, - EXCLUDED: { - Type: schema.TypeList, - Elem: &schema.Schema{Type: schema.TypeString}, - Optional: true, - }, - RULES: segmentRulesSchema(), - }, + Schema: schemaMap, } } @@ -117,48 +100,7 @@ func resourceSegmentCreate(d *schema.ResourceData, metaRaw interface{}) error { } func resourceSegmentRead(d *schema.ResourceData, metaRaw interface{}) error { - client := metaRaw.(*Client) - projectKey := d.Get(PROJECT_KEY).(string) - envKey := d.Get(ENV_KEY).(string) - segmentKey := d.Get(KEY).(string) - - segmentRaw, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { - return client.ld.UserSegmentsApi.GetUserSegment(client.ctx, projectKey, envKey, segmentKey) - }) - segment := segmentRaw.(ldapi.UserSegment) - if isStatusNotFound(res) { - log.Printf("[WARN] failed to find segment %q in project %q, environment %q, removing from state", segmentKey, projectKey, envKey) - d.SetId("") - return nil - } - - if err != nil { - return fmt.Errorf("failed to get segment %q of project %q: %s", segmentKey, projectKey, handleLdapiErr(err)) - } - - _ = d.Set(NAME, segment.Name) - _ = d.Set(DESCRIPTION, segment.Description) - - err = d.Set(TAGS, segment.Tags) - if err != nil { - return fmt.Errorf("failed to set tags on segment with key %q: %v", segmentKey, err) - } - - err = d.Set(INCLUDED, segment.Included) - if err != nil { - return fmt.Errorf("failed to set included on segment with key %q: %v", segmentKey, err) - } - - err = d.Set(EXCLUDED, segment.Excluded) - if err != nil { - return fmt.Errorf("failed to set excluded on segment with key %q: %v", segmentKey, err) - } - - err = d.Set(RULES, segmentRulesToResourceData(segment.Rules)) - if err != nil { - return fmt.Errorf("failed to set excluded on segment with key %q: %v", segmentKey, err) - } - return nil + return segmentRead(d, metaRaw, false) } func resourceSegmentUpdate(d *schema.ResourceData, metaRaw interface{}) error { diff --git a/launchdarkly/resource_launchdarkly_team_member_test.go b/launchdarkly/resource_launchdarkly_team_member_test.go index dd2d9e87..b3e8708e 100644 --- a/launchdarkly/resource_launchdarkly_team_member_test.go +++ b/launchdarkly/resource_launchdarkly_team_member_test.go @@ -89,7 +89,7 @@ func testAccTeamMemberCustomRoleUpdate(roleKey1, roleKey2, rName string) string `, roleKey1, roleKey1, roleKey2, roleKey2, rName) } -func TestAccTeamMember_Create(t *testing.T) { +func TestAccTeamMember_CreateGeneric(t *testing.T) { randomName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) resourceName := "launchdarkly_team_member.test" resource.ParallelTest(t, resource.TestCase{ @@ -118,7 +118,7 @@ func TestAccTeamMember_Create(t *testing.T) { }) } -func TestAccTeamMember_Update(t *testing.T) { +func TestAccTeamMember_UpdateGeneric(t *testing.T) { randomName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) resourceName := "launchdarkly_team_member.test" resource.ParallelTest(t, resource.TestCase{ diff --git a/launchdarkly/resource_launchdarkly_webhook.go b/launchdarkly/resource_launchdarkly_webhook.go index 7379c2ce..8910db4f 100644 --- a/launchdarkly/resource_launchdarkly_webhook.go +++ b/launchdarkly/resource_launchdarkly_webhook.go @@ -2,7 +2,6 @@ package launchdarkly import ( "fmt" - "log" "net/http" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -10,6 +9,15 @@ import ( ) func resourceWebhook() *schema.Resource { + schemaMap := baseWebhookSchema() + schemaMap[URL] = &schema.Schema{ + Type: schema.TypeString, + Required: true, + } + schemaMap[ENABLED] = &schema.Schema{ + Type: schema.TypeBool, + Required: true, + } return &schema.Resource{ Create: resourceWebhookCreate, Read: resourceWebhookRead, @@ -21,27 +29,7 @@ func resourceWebhook() *schema.Resource { State: schema.ImportStatePassthrough, }, - Schema: map[string]*schema.Schema{ - URL: { - Type: schema.TypeString, - Required: true, - }, - SECRET: { - Type: schema.TypeString, - Optional: true, - Sensitive: true, - }, - ENABLED: { - Type: schema.TypeBool, - Required: true, - }, - NAME: { - Type: schema.TypeString, - Optional: true, - }, - POLICY_STATEMENTS: policyStatementsSchema(), - TAGS: tagsSchema(), - }, + Schema: schemaMap, } } @@ -90,37 +78,7 @@ func resourceWebhookCreate(d *schema.ResourceData, metaRaw interface{}) error { } func resourceWebhookRead(d *schema.ResourceData, metaRaw interface{}) error { - client := metaRaw.(*Client) - webhookID := d.Id() - - webhookRaw, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { - return client.ld.WebhooksApi.GetWebhook(client.ctx, webhookID) - }) - webhook := webhookRaw.(ldapi.Webhook) - if isStatusNotFound(res) { - log.Printf("[WARN] failed to find webhook with id %q, removing from state", webhookID) - d.SetId("") - return nil - } - if err != nil { - return fmt.Errorf("failed to get webhook with id %q: %s", webhookID, handleLdapiErr(err)) - } - statements := policyStatementsToResourceData(webhook.Statements) - - _ = d.Set(URL, webhook.Url) - _ = d.Set(SECRET, webhook.Secret) - _ = d.Set(ENABLED, webhook.On) - _ = d.Set(NAME, webhook.Name) - err = d.Set(POLICY_STATEMENTS, statements) - if err != nil { - return fmt.Errorf("failed to set policy_statements on webhook with id %q: %v", webhookID, err) - } - - err = d.Set(TAGS, webhook.Tags) - if err != nil { - return fmt.Errorf("failed to set tags on webhook with id %q: %v", webhookID, err) - } - return nil + return webhookRead(d, metaRaw, false) } func resourceWebhookUpdate(d *schema.ResourceData, metaRaw interface{}) error { diff --git a/launchdarkly/segment_rule_helper.go b/launchdarkly/segment_rule_helper.go index 8cea89b5..b0383ded 100644 --- a/launchdarkly/segment_rule_helper.go +++ b/launchdarkly/segment_rule_helper.go @@ -12,14 +12,14 @@ func segmentRulesSchema() *schema.Schema { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "clauses": clauseSchema(), - "weight": &schema.Schema{ + CLAUSES: clauseSchema(), + WEIGHT: { Type: schema.TypeInt, Elem: &schema.Schema{Type: schema.TypeInt}, Optional: true, ValidateFunc: validation.IntBetween(1, 100000), }, - "bucket_by": &schema.Schema{ + BUCKET_BY: { Type: schema.TypeString, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, diff --git a/launchdarkly/segments_helper.go b/launchdarkly/segments_helper.go new file mode 100644 index 00000000..17cd0cb2 --- /dev/null +++ b/launchdarkly/segments_helper.go @@ -0,0 +1,78 @@ +package launchdarkly + +import ( + "fmt" + "log" + "net/http" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ldapi "github.com/launchdarkly/api-client-go" +) + +func baseSegmentSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + DESCRIPTION: { + Type: schema.TypeString, + Optional: true, + }, + TAGS: tagsSchema(), + INCLUDED: { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + EXCLUDED: { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + RULES: segmentRulesSchema(), + } +} + +func segmentRead(d *schema.ResourceData, raw interface{}, isDataSource bool) error { + client := raw.(*Client) + projectKey := d.Get(PROJECT_KEY).(string) + envKey := d.Get(ENV_KEY).(string) + segmentKey := d.Get(KEY).(string) + + segmentRaw, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.UserSegmentsApi.GetUserSegment(client.ctx, projectKey, envKey, segmentKey) + }) + segment := segmentRaw.(ldapi.UserSegment) + if isStatusNotFound(res) && !isDataSource { + log.Printf("[WARN] failed to find segment %q in project %q, environment %q, removing from state", segmentKey, projectKey, envKey) + d.SetId("") + return nil + } + if err != nil { + return fmt.Errorf("failed to get segment %q of project %q: %s", segmentKey, projectKey, handleLdapiErr(err)) + } + + if isDataSource { + d.SetId(projectKey + "/" + envKey + "/" + segmentKey) + } + _ = d.Set(NAME, segment.Name) + _ = d.Set(DESCRIPTION, segment.Description) + + err = d.Set(TAGS, segment.Tags) + if err != nil { + return fmt.Errorf("failed to set tags on segment with key %q: %v", segmentKey, err) + } + + err = d.Set(INCLUDED, segment.Included) + if err != nil { + return fmt.Errorf("failed to set included on segment with key %q: %v", segmentKey, err) + } + + err = d.Set(EXCLUDED, segment.Excluded) + if err != nil { + return fmt.Errorf("failed to set excluded on segment with key %q: %v", segmentKey, err) + } + + err = d.Set(RULES, segmentRulesToResourceData(segment.Rules)) + if err != nil { + return fmt.Errorf("failed to set excluded on segment with key %q: %v", segmentKey, err) + } + return nil +} diff --git a/launchdarkly/test_utils.go b/launchdarkly/test_utils.go new file mode 100644 index 00000000..17cd73cb --- /dev/null +++ b/launchdarkly/test_utils.go @@ -0,0 +1,57 @@ +package launchdarkly + +import ( + "fmt" + "net/http" + + ldapi "github.com/launchdarkly/api-client-go" +) + +// testAccDataSourceProjectCreate creates a project with the given project parameters +func testAccDataSourceProjectCreate(client *Client, projectBody ldapi.ProjectBody) (*ldapi.Project, error) { + project, _, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.ProjectsApi.PostProject(client.ctx, projectBody) + }) + if err != nil { + return nil, err + } + if project, ok := project.(ldapi.Project); ok { + return &project, nil + } + return nil, fmt.Errorf("failed to create project") +} + +func testAccDataSourceProjectDelete(client *Client, projectKey string) error { + _, err := client.ld.ProjectsApi.DeleteProject(client.ctx, projectKey) + if err != nil { + return err + } + return nil +} + +func testAccDataSourceFeatureFlagScaffold(client *Client, projectKey string, flagBody ldapi.FeatureFlagBody) (*ldapi.FeatureFlag, error) { + projectBody := ldapi.ProjectBody{ + Name: "Flag Test Project", + Key: projectKey, + } + project, err := testAccDataSourceProjectCreate(client, projectBody) + if err != nil { + return nil, err + } + + flag, _, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.FeatureFlagsApi.PostFeatureFlag(client.ctx, project.Key, flagBody, nil) + }) + if err != nil { + return nil, err + } + if flag, ok := flag.(ldapi.FeatureFlag); ok { + return &flag, nil + } + return nil, fmt.Errorf("failed to create flag") + +} + +func intfPtr(i interface{}) *interface{} { + return &i +} diff --git a/launchdarkly/webhooks_helper.go b/launchdarkly/webhooks_helper.go new file mode 100644 index 00000000..ea7340ba --- /dev/null +++ b/launchdarkly/webhooks_helper.go @@ -0,0 +1,68 @@ +package launchdarkly + +import ( + "fmt" + "log" + "net/http" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ldapi "github.com/launchdarkly/api-client-go" +) + +func baseWebhookSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + SECRET: { + Type: schema.TypeString, + Optional: true, + Sensitive: true, + }, + NAME: { + Type: schema.TypeString, + Optional: true, + }, + POLICY_STATEMENTS: policyStatementsSchema(), + TAGS: tagsSchema(), + } +} + +func webhookRead(d *schema.ResourceData, meta interface{}, isDataSource bool) error { + client := meta.(*Client) + var webhookID string + if isDataSource { + webhookID = d.Get(ID).(string) + } else { + webhookID = d.Id() + } + + webhookRaw, res, err := handleRateLimit(func() (interface{}, *http.Response, error) { + return client.ld.WebhooksApi.GetWebhook(client.ctx, webhookID) + }) + webhook := webhookRaw.(ldapi.Webhook) + if isStatusNotFound(res) && !isDataSource { + log.Printf("[WARN] failed to find webhook with id %q, removing from state", webhookID) + d.SetId("") + return nil + } + if err != nil { + return fmt.Errorf("failed to get webhook with id %q: %s", webhookID, handleLdapiErr(err)) + } + statements := policyStatementsToResourceData(webhook.Statements) + + if isDataSource { + d.SetId(webhook.Id) + } + _ = d.Set(URL, webhook.Url) + _ = d.Set(SECRET, webhook.Secret) + _ = d.Set(ENABLED, webhook.On) + _ = d.Set(NAME, webhook.Name) + err = d.Set(POLICY_STATEMENTS, statements) + if err != nil { + return fmt.Errorf("failed to set policy_statements on webhook with id %q: %v", webhookID, err) + } + + err = d.Set(TAGS, webhook.Tags) + if err != nil { + return fmt.Errorf("failed to set tags on webhook with id %q: %v", webhookID, err) + } + return nil +} diff --git a/vendor/github.com/launchdarkly/api-client-go/README.md b/vendor/github.com/launchdarkly/api-client-go/README.md index 9b98cbfa..b5e41155 100644 --- a/vendor/github.com/launchdarkly/api-client-go/README.md +++ b/vendor/github.com/launchdarkly/api-client-go/README.md @@ -10,7 +10,7 @@ Build custom integrations with the LaunchDarkly REST API ## Overview This API client was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the [swagger-spec](https://github.com/swagger-api/swagger-spec) from a remote server, you can easily generate an API client. -- API version: 3.4.0 +- API version: 3.5.0 - Package version: 1.0.0 - Build package: io.swagger.codegen.languages.GoClientCodegen For more information, please visit [https://support.launchdarkly.com](https://support.launchdarkly.com) @@ -111,6 +111,7 @@ Class | Method | HTTP request | Description - [AuditLogEntry](docs/AuditLogEntry.md) - [AuditLogEntryTarget](docs/AuditLogEntryTarget.md) - [Clause](docs/Clause.md) + - [ClientSideAvailability](docs/ClientSideAvailability.md) - [CopyActions](docs/CopyActions.md) - [CustomProperty](docs/CustomProperty.md) - [CustomPropertyValues](docs/CustomPropertyValues.md) diff --git a/vendor/github.com/launchdarkly/api-client-go/api_access_tokens.go b/vendor/github.com/launchdarkly/api-client-go/api_access_tokens.go index af87f5d9..553f64ac 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_access_tokens.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_access_tokens.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_audit_log.go b/vendor/github.com/launchdarkly/api-client-go/api_audit_log.go index c3eade78..dc2ed0e1 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_audit_log.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_audit_log.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_custom_roles.go b/vendor/github.com/launchdarkly/api-client-go/api_custom_roles.go index 711c80ed..214f83db 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_custom_roles.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_custom_roles.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_customer_metrics.go b/vendor/github.com/launchdarkly/api-client-go/api_customer_metrics.go index 47c9f5fd..f66bd8da 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_customer_metrics.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_customer_metrics.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_data_export_destinations.go b/vendor/github.com/launchdarkly/api-client-go/api_data_export_destinations.go index 2f37c34f..79d16d7a 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_data_export_destinations.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_data_export_destinations.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_environments.go b/vendor/github.com/launchdarkly/api-client-go/api_environments.go index 8ed218f3..ea547098 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_environments.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_environments.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_feature_flags.go b/vendor/github.com/launchdarkly/api-client-go/api_feature_flags.go index c111536a..1c24a91a 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_feature_flags.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_feature_flags.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_projects.go b/vendor/github.com/launchdarkly/api-client-go/api_projects.go index 84145833..752d1b42 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_projects.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_projects.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_root.go b/vendor/github.com/launchdarkly/api-client-go/api_root.go index 1afb9f60..0e583313 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_root.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_root.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_team_members.go b/vendor/github.com/launchdarkly/api-client-go/api_team_members.go index 90167d39..823d4b0b 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_team_members.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_team_members.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_user_segments.go b/vendor/github.com/launchdarkly/api-client-go/api_user_segments.go index b5973b04..276a8a3f 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_user_segments.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_user_segments.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_user_settings.go b/vendor/github.com/launchdarkly/api-client-go/api_user_settings.go index 3c330877..d434bdff 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_user_settings.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_user_settings.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_users.go b/vendor/github.com/launchdarkly/api-client-go/api_users.go index 85dab1df..72c3f10d 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_users.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_users.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/api_webhooks.go b/vendor/github.com/launchdarkly/api-client-go/api_webhooks.go index 6144bb13..c6911a61 100644 --- a/vendor/github.com/launchdarkly/api-client-go/api_webhooks.go +++ b/vendor/github.com/launchdarkly/api-client-go/api_webhooks.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/client.go b/vendor/github.com/launchdarkly/api-client-go/client.go index 5e0ae6a4..cc23bfbf 100644 --- a/vendor/github.com/launchdarkly/api-client-go/client.go +++ b/vendor/github.com/launchdarkly/api-client-go/client.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ @@ -38,7 +38,7 @@ var ( xmlCheck = regexp.MustCompile("(?i:[application|text]/xml)") ) -// APIClient manages communication with the LaunchDarkly REST API API v3.4.0 +// APIClient manages communication with the LaunchDarkly REST API API v3.5.0 // In most cases there should be only one, shared, APIClient. type APIClient struct { cfg *Configuration diff --git a/vendor/github.com/launchdarkly/api-client-go/configuration.go b/vendor/github.com/launchdarkly/api-client-go/configuration.go index 6fa372fb..76d07967 100644 --- a/vendor/github.com/launchdarkly/api-client-go/configuration.go +++ b/vendor/github.com/launchdarkly/api-client-go/configuration.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_audit_log_entries.go b/vendor/github.com/launchdarkly/api-client-go/model_audit_log_entries.go index e1290677..41b0d525 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_audit_log_entries.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_audit_log_entries.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_audit_log_entry.go b/vendor/github.com/launchdarkly/api-client-go/model_audit_log_entry.go index f412c0d6..ba15e067 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_audit_log_entry.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_audit_log_entry.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_audit_log_entry_target.go b/vendor/github.com/launchdarkly/api-client-go/model_audit_log_entry_target.go index 85adb57f..cd230643 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_audit_log_entry_target.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_audit_log_entry_target.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_clause.go b/vendor/github.com/launchdarkly/api-client-go/model_clause.go index 655ff4e8..a944b850 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_clause.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_clause.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_client_side_availability.go b/vendor/github.com/launchdarkly/api-client-go/model_client_side_availability.go new file mode 100644 index 00000000..d93670ad --- /dev/null +++ b/vendor/github.com/launchdarkly/api-client-go/model_client_side_availability.go @@ -0,0 +1,18 @@ +/* + * LaunchDarkly REST API + * + * Build custom integrations with the LaunchDarkly REST API + * + * API version: 3.5.0 + * Contact: support@launchdarkly.com + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package ldapi + +type ClientSideAvailability struct { + // When set to true, this flag will be available to SDKs using the client-side id. + UsingEnvironmentId bool `json:"usingEnvironmentId,omitempty"` + // When set to true, this flag will be available to SDKS using a mobile key. + UsingMobileKey bool `json:"usingMobileKey,omitempty"` +} diff --git a/vendor/github.com/launchdarkly/api-client-go/model_copy_actions.go b/vendor/github.com/launchdarkly/api-client-go/model_copy_actions.go index 9c5ca0c2..445d2595 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_copy_actions.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_copy_actions.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_custom_property.go b/vendor/github.com/launchdarkly/api-client-go/model_custom_property.go index 14c3ad2c..9552ab77 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_custom_property.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_custom_property.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_custom_property_values.go b/vendor/github.com/launchdarkly/api-client-go/model_custom_property_values.go index ec21a955..9f017fd4 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_custom_property_values.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_custom_property_values.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_custom_role.go b/vendor/github.com/launchdarkly/api-client-go/model_custom_role.go index aa119218..8606a834 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_custom_role.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_custom_role.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_custom_role_body.go b/vendor/github.com/launchdarkly/api-client-go/model_custom_role_body.go index df298cad..7fe9f5c9 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_custom_role_body.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_custom_role_body.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_custom_roles.go b/vendor/github.com/launchdarkly/api-client-go/model_custom_roles.go index add4261c..0c3e7542 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_custom_roles.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_custom_roles.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_defaults.go b/vendor/github.com/launchdarkly/api-client-go/model_defaults.go index afc2d9d2..3918e46a 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_defaults.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_defaults.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_destination.go b/vendor/github.com/launchdarkly/api-client-go/model_destination.go index 0eab2e8d..4c72d8ab 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_destination.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_destination.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_destination_amazon_kinesis.go b/vendor/github.com/launchdarkly/api-client-go/model_destination_amazon_kinesis.go index 0b8cbeca..894165bd 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_destination_amazon_kinesis.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_destination_amazon_kinesis.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_destination_body.go b/vendor/github.com/launchdarkly/api-client-go/model_destination_body.go index cc6a4070..e2645ab3 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_destination_body.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_destination_body.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_destination_google_pub_sub.go b/vendor/github.com/launchdarkly/api-client-go/model_destination_google_pub_sub.go index ed42dcec..f92472df 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_destination_google_pub_sub.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_destination_google_pub_sub.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_destination_m_particle.go b/vendor/github.com/launchdarkly/api-client-go/model_destination_m_particle.go index e5018804..ba5664d1 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_destination_m_particle.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_destination_m_particle.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_destination_segment.go b/vendor/github.com/launchdarkly/api-client-go/model_destination_segment.go index c0edd963..deb741f2 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_destination_segment.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_destination_segment.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_destinations.go b/vendor/github.com/launchdarkly/api-client-go/model_destinations.go index dfe3ab70..6a0dcfc3 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_destinations.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_destinations.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_environment.go b/vendor/github.com/launchdarkly/api-client-go/model_environment.go index 9dace42b..3853d928 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_environment.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_environment.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_environment_post.go b/vendor/github.com/launchdarkly/api-client-go/model_environment_post.go index 77fe0319..e6828c44 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_environment_post.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_environment_post.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_evaluation_usage_error.go b/vendor/github.com/launchdarkly/api-client-go/model_evaluation_usage_error.go index 238f2d7a..ad433756 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_evaluation_usage_error.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_evaluation_usage_error.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_events.go b/vendor/github.com/launchdarkly/api-client-go/model_events.go index 8e57c17b..786e19f3 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_events.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_events.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_fallthrough.go b/vendor/github.com/launchdarkly/api-client-go/model_fallthrough.go index 761eaa42..e72b1f8c 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_fallthrough.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_fallthrough.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag.go b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag.go index be3fb155..35a04b20 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ @@ -41,5 +41,6 @@ type FeatureFlag struct { ArchivedDate int64 `json:"archivedDate,omitempty"` // Whether or not this flag is archived. Archived bool `json:"archived,omitempty"` + ClientSideAvailability *ClientSideAvailability `json:"clientSideAvailability,omitempty"` Defaults *Defaults `json:"defaults,omitempty"` } diff --git a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_body.go b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_body.go index 1ff71605..80f5c1e6 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_body.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_body.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ @@ -25,5 +25,6 @@ type FeatureFlagBody struct { Tags []string `json:"tags,omitempty"` // Whether or not this flag should be made available to the client-side JavaScript SDK. IncludeInSnippet bool `json:"includeInSnippet,omitempty"` + ClientSideAvailability *ClientSideAvailability `json:"clientSideAvailability,omitempty"` Defaults *Defaults `json:"defaults,omitempty"` } diff --git a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_config.go b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_config.go index b4e19040..598803b0 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_config.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_config.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_copy_body.go b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_copy_body.go index db338fc0..e3fb84e3 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_copy_body.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_copy_body.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_copy_object.go b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_copy_object.go index 6d59814b..afd69595 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_copy_object.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_copy_object.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_status.go b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_status.go index 69048611..915008f8 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_status.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_status.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_status_across_environments.go b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_status_across_environments.go index d03c9f25..629f8741 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_status_across_environments.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_status_across_environments.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_status_for_queried_environment.go b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_status_for_queried_environment.go index 7d15585c..582d4c48 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_status_for_queried_environment.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_status_for_queried_environment.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_statuses.go b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_statuses.go index 3f239919..d6443076 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_statuses.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_feature_flag_statuses.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_feature_flags.go b/vendor/github.com/launchdarkly/api-client-go/model_feature_flags.go index e74d81d0..0cf7750e 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_feature_flags.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_feature_flags.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_flag_list_item.go b/vendor/github.com/launchdarkly/api-client-go/model_flag_list_item.go index a66e718e..3eba586f 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_flag_list_item.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_flag_list_item.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_id.go b/vendor/github.com/launchdarkly/api-client-go/model_id.go index 8ccca985..2a649f89 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_id.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_id.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_link.go b/vendor/github.com/launchdarkly/api-client-go/model_link.go index f3782995..8473dc18 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_link.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_link.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_links.go b/vendor/github.com/launchdarkly/api-client-go/model_links.go index 8274ca5a..bb19c322 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_links.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_links.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_ma_uby_category.go b/vendor/github.com/launchdarkly/api-client-go/model_ma_uby_category.go index 98d8896e..838cb74c 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_ma_uby_category.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_ma_uby_category.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_mau.go b/vendor/github.com/launchdarkly/api-client-go/model_mau.go index 1d020153..0d919a6d 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_mau.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_mau.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_mau_metadata.go b/vendor/github.com/launchdarkly/api-client-go/model_mau_metadata.go index c9a39c02..d339fd1c 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_mau_metadata.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_mau_metadata.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_member.go b/vendor/github.com/launchdarkly/api-client-go/model_member.go index e5fa945c..7eda9137 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_member.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_member.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_members.go b/vendor/github.com/launchdarkly/api-client-go/model_members.go index 9130645d..f4d6d901 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_members.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_members.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_members_body.go b/vendor/github.com/launchdarkly/api-client-go/model_members_body.go index ef1c2aa6..41a9a246 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_members_body.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_members_body.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_patch_comment.go b/vendor/github.com/launchdarkly/api-client-go/model_patch_comment.go index e7140061..21542855 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_patch_comment.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_patch_comment.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_patch_operation.go b/vendor/github.com/launchdarkly/api-client-go/model_patch_operation.go index 0ae0d373..67d12d82 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_patch_operation.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_patch_operation.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_policy.go b/vendor/github.com/launchdarkly/api-client-go/model_policy.go index feb4be6e..6bc327e7 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_policy.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_policy.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_prerequisite.go b/vendor/github.com/launchdarkly/api-client-go/model_prerequisite.go index 63511cc5..f9b6031a 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_prerequisite.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_prerequisite.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_project.go b/vendor/github.com/launchdarkly/api-client-go/model_project.go index 52ab3307..51b2e92d 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_project.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_project.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ @@ -20,4 +20,5 @@ type Project struct { Environments []Environment `json:"environments,omitempty"` // An array of tags for this project. Tags []string `json:"tags,omitempty"` + DefaultClientSideAvailability *ClientSideAvailability `json:"defaultClientSideAvailability,omitempty"` } diff --git a/vendor/github.com/launchdarkly/api-client-go/model_project_body.go b/vendor/github.com/launchdarkly/api-client-go/model_project_body.go index 19760c19..f64a3a0f 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_project_body.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_project_body.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ @@ -16,4 +16,5 @@ type ProjectBody struct { IncludeInSnippetByDefault bool `json:"includeInSnippetByDefault,omitempty"` Tags []string `json:"tags,omitempty"` Environments []EnvironmentPost `json:"environments,omitempty"` + DefaultClientSideAvailability *ClientSideAvailability `json:"defaultClientSideAvailability,omitempty"` } diff --git a/vendor/github.com/launchdarkly/api-client-go/model_projects.go b/vendor/github.com/launchdarkly/api-client-go/model_projects.go index 2f38b664..2a009cba 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_projects.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_projects.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_role.go b/vendor/github.com/launchdarkly/api-client-go/model_role.go index e4ca4fd8..48c1ac76 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_role.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_role.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_rollout.go b/vendor/github.com/launchdarkly/api-client-go/model_rollout.go index 9b1bb50c..17cdf38f 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_rollout.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_rollout.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_rule.go b/vendor/github.com/launchdarkly/api-client-go/model_rule.go index f3df7748..d3277ab0 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_rule.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_rule.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_semantic_patch_operation.go b/vendor/github.com/launchdarkly/api-client-go/model_semantic_patch_operation.go index cf691039..fd4f6f9c 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_semantic_patch_operation.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_semantic_patch_operation.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_semantic_patch_operation_instructions.go b/vendor/github.com/launchdarkly/api-client-go/model_semantic_patch_operation_instructions.go index 2122eb3d..6cb65d86 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_semantic_patch_operation_instructions.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_semantic_patch_operation_instructions.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_site.go b/vendor/github.com/launchdarkly/api-client-go/model_site.go index 0b3138b4..845e01ca 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_site.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_site.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_statement.go b/vendor/github.com/launchdarkly/api-client-go/model_statement.go index d9179e45..396f9ef0 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_statement.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_statement.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_stream.go b/vendor/github.com/launchdarkly/api-client-go/model_stream.go index ca790604..b55edc42 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_stream.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_stream.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_stream_by_sdk.go b/vendor/github.com/launchdarkly/api-client-go/model_stream_by_sdk.go index 09e570a1..b3f2bc4e 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_stream_by_sdk.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_stream_by_sdk.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_stream_by_sdk_links.go b/vendor/github.com/launchdarkly/api-client-go/model_stream_by_sdk_links.go index d94ea22a..25a9fd1d 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_stream_by_sdk_links.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_stream_by_sdk_links.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_stream_by_sdk_links_metadata.go b/vendor/github.com/launchdarkly/api-client-go/model_stream_by_sdk_links_metadata.go index 8dd74087..bb9dd816 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_stream_by_sdk_links_metadata.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_stream_by_sdk_links_metadata.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_stream_links.go b/vendor/github.com/launchdarkly/api-client-go/model_stream_links.go index 30d0e1de..8443dbe9 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_stream_links.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_stream_links.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_stream_sdk_version.go b/vendor/github.com/launchdarkly/api-client-go/model_stream_sdk_version.go index 987f86f1..90f40c76 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_stream_sdk_version.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_stream_sdk_version.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_stream_sdk_version_data.go b/vendor/github.com/launchdarkly/api-client-go/model_stream_sdk_version_data.go index b32baaa1..54436556 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_stream_sdk_version_data.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_stream_sdk_version_data.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_error.go b/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_error.go index ba3cd534..38bad483 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_error.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_error.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_links.go b/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_links.go index 848ab346..5d0e1e12 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_links.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_links.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_metadata.go b/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_metadata.go index f5c536e7..288125a9 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_metadata.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_metadata.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_series.go b/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_series.go index 0ba447e6..74945eea 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_series.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_stream_usage_series.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_streams.go b/vendor/github.com/launchdarkly/api-client-go/model_streams.go index e2aae713..1002a59a 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_streams.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_streams.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_target.go b/vendor/github.com/launchdarkly/api-client-go/model_target.go index 1d58c117..283f537f 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_target.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_target.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_token.go b/vendor/github.com/launchdarkly/api-client-go/model_token.go index ab40cc3c..86d37b9d 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_token.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_token.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_token_body.go b/vendor/github.com/launchdarkly/api-client-go/model_token_body.go index 8d84b48b..29b5cbb1 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_token_body.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_token_body.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_tokens.go b/vendor/github.com/launchdarkly/api-client-go/model_tokens.go index aec2914f..502e658f 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_tokens.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_tokens.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_usage.go b/vendor/github.com/launchdarkly/api-client-go/model_usage.go index 80aa4b20..fcc23c12 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_usage.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_usage.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_usage_error.go b/vendor/github.com/launchdarkly/api-client-go/model_usage_error.go index b2cb81f5..c05b9c35 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_usage_error.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_usage_error.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_usage_links.go b/vendor/github.com/launchdarkly/api-client-go/model_usage_links.go index 1d4fed88..1bd376e6 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_usage_links.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_usage_links.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user.go b/vendor/github.com/launchdarkly/api-client-go/model_user.go index f9e69e70..b67231fd 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_flag_setting.go b/vendor/github.com/launchdarkly/api-client-go/model_user_flag_setting.go index 98a3c64c..a5b2dbbe 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_flag_setting.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_flag_setting.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_flag_settings.go b/vendor/github.com/launchdarkly/api-client-go/model_user_flag_settings.go index 2eed95a0..21b7b95d 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_flag_settings.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_flag_settings.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_record.go b/vendor/github.com/launchdarkly/api-client-go/model_user_record.go index c93d07cb..8ea5bc3e 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_record.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_record.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_segment.go b/vendor/github.com/launchdarkly/api-client-go/model_user_segment.go index ac43d7a7..df054955 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_segment.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_segment.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_segment_body.go b/vendor/github.com/launchdarkly/api-client-go/model_user_segment_body.go index d0fb8e44..071122b8 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_segment_body.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_segment_body.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_segment_rule.go b/vendor/github.com/launchdarkly/api-client-go/model_user_segment_rule.go index 61ef6fd4..07199e30 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_segment_rule.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_segment_rule.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_segments.go b/vendor/github.com/launchdarkly/api-client-go/model_user_segments.go index a87a4bfa..6eaeb821 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_segments.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_segments.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_settings_body.go b/vendor/github.com/launchdarkly/api-client-go/model_user_settings_body.go index aaba4770..22fb038b 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_settings_body.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_settings_body.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_for_flag.go b/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_for_flag.go index 3b40e85b..44d6ab83 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_for_flag.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_for_flag.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_for_flags.go b/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_for_flags.go index 6632bd49..a3fa7aca 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_for_flags.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_for_flags.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_for_segment.go b/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_for_segment.go index 2679f211..eb81a33e 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_for_segment.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_for_segment.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_on_flags_for_user.go b/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_on_flags_for_user.go index b4291bea..31d2e541 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_on_flags_for_user.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_on_flags_for_user.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_resource_id_for_flag.go b/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_resource_id_for_flag.go index 3fd04a1b..3fd32f60 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_resource_id_for_flag.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_user_targeting_expiration_resource_id_for_flag.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_users.go b/vendor/github.com/launchdarkly/api-client-go/model_users.go index 40cab5bc..771f8de2 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_users.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_users.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_variation.go b/vendor/github.com/launchdarkly/api-client-go/model_variation.go index 84cd8eaa..3e70d491 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_variation.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_variation.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_webhook.go b/vendor/github.com/launchdarkly/api-client-go/model_webhook.go index 8f11c33f..f12ecb50 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_webhook.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_webhook.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_webhook_body.go b/vendor/github.com/launchdarkly/api-client-go/model_webhook_body.go index a9ca3dc4..32f1970f 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_webhook_body.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_webhook_body.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_webhooks.go b/vendor/github.com/launchdarkly/api-client-go/model_webhooks.go index 76bf9f0c..a0fa4daf 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_webhooks.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_webhooks.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/model_weighted_variation.go b/vendor/github.com/launchdarkly/api-client-go/model_weighted_variation.go index 732181bc..16358857 100644 --- a/vendor/github.com/launchdarkly/api-client-go/model_weighted_variation.go +++ b/vendor/github.com/launchdarkly/api-client-go/model_weighted_variation.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/github.com/launchdarkly/api-client-go/openapi.yml b/vendor/github.com/launchdarkly/api-client-go/openapi.yml index b51f26ab..52777244 100644 --- a/vendor/github.com/launchdarkly/api-client-go/openapi.yml +++ b/vendor/github.com/launchdarkly/api-client-go/openapi.yml @@ -10,7 +10,7 @@ info: license: name: Apache 2.0 url: 'http://www.apache.org/licenses/LICENSE-2.0.html' - version: 3.4.0 + version: 3.5.0 host: app.launchdarkly.com basePath: /api/v2 schemes: @@ -1521,6 +1521,8 @@ definitions: type: boolean description: Whether or not this flag is archived. example: false + clientSideAvailability: + $ref: '#/definitions/ClientSideAvailability' defaults: $ref: '#/definitions/Defaults' FeatureFlags: @@ -1727,6 +1729,19 @@ definitions: type: string variation: type: integer + ClientSideAvailability: + type: object + properties: + usingEnvironmentId: + type: boolean + description: >- + When set to true, this flag will be available to SDKs using the + client-side id. + usingMobileKey: + type: boolean + description: >- + When set to true, this flag will be available to SDKS using a mobile + key. FeatureFlagStatus: type: object properties: @@ -1999,6 +2014,8 @@ definitions: items: type: string description: An array of tags for this project. + defaultClientSideAvailability: + $ref: '#/definitions/ClientSideAvailability' Projects: type: object properties: @@ -3053,6 +3070,8 @@ parameters: description: >- Whether or not this flag should be made available to the client-side JavaScript SDK. + clientSideAvailability: + $ref: '#/definitions/ClientSideAvailability' defaults: $ref: '#/definitions/Defaults' required: @@ -3156,6 +3175,8 @@ parameters: items: $ref: '#/definitions/EnvironmentPost' minLength: 1 + defaultClientSideAvailability: + $ref: '#/definitions/ClientSideAvailability' required: - name - key diff --git a/vendor/github.com/launchdarkly/api-client-go/response.go b/vendor/github.com/launchdarkly/api-client-go/response.go index 963bbfc0..8c50366c 100644 --- a/vendor/github.com/launchdarkly/api-client-go/response.go +++ b/vendor/github.com/launchdarkly/api-client-go/response.go @@ -3,7 +3,7 @@ * * Build custom integrations with the LaunchDarkly REST API * - * API version: 3.4.0 + * API version: 3.5.0 * Contact: support@launchdarkly.com * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) */ diff --git a/vendor/modules.txt b/vendor/modules.txt index c874ea85..fc34ff27 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -191,7 +191,7 @@ github.com/hashicorp/terraform-svchost/disco github.com/hashicorp/yamux # github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af github.com/jmespath/go-jmespath -# github.com/launchdarkly/api-client-go v3.2.1-0.20200812163818-441cfcaaa92c+incompatible +# github.com/launchdarkly/api-client-go v3.5.0+incompatible ## explicit github.com/launchdarkly/api-client-go # github.com/mattn/go-colorable v0.1.1 diff --git a/website/docs/d/environment.html.markdown b/website/docs/d/environment.html.markdown new file mode 100644 index 00000000..da432340 --- /dev/null +++ b/website/docs/d/environment.html.markdown @@ -0,0 +1,55 @@ +--- +layout: "launchdarkly" +page_title: "LaunchDarkly: launchdarkly_environment" +description: |- + Get information about LaunchDarkly environments. +--- + +# launchdarkly_environment + +Provides a LaunchDarkly environment data source. + +This data source allows you to retrieve environment information from your LaunchDarkly organization. + +## Example Usage + +```hcl +data "launchdarkly_environment" "example" { + key = "example-env" + project_key = "example-project" +} +``` + +## Argument Reference + +- `key` - (Required) The environment's unique key. + +- `project_key` - (Required) The environment's project key. + +## Attributes Reference + +In addition to the arguments above, the resource exports the following attributes: + +- `id` - The unique environment ID in the format `project_key/environment_key`. + +- `name` - The name of the environment. + +- `color` - The color swatch as an RGB hex value with no leading `#`. For example: `000000`. + +- `tags` - Set of tags associated with the environment. + +- `secure_mode` - A value of true `true` ensures a user of the client-side SDK cannot impersonate another user. + +- `default_track_events` - A value of `true` enables data export for every flag created in this environment. To learn more, read [Data Export](https://docs.launchdarkly.com/docs/data-export). + +- `default_ttl` - The TTL for the environment. This will be a numeric value between 0 and 60 in minutes. The TTL setting only applies to environments using the PHP SDK. To learn more, read [TTL settings](https://docs.launchdarkly.com/docs/environments#section-ttl-settings). + +- `require_comments` - A value of `true` indicates that this environment requires comments for flag and segment changes. + +- `confirm_changes` - A value of `true` indicates that this environment requires confirmation for flag and segment changes. + +- `api_key` - The environment's SDK key. + +- `mobile_key` - The environment's mobile key. + +- `client_side_id` - The environment's client-side ID. diff --git a/website/docs/d/feature_flag.html.markdown b/website/docs/d/feature_flag.html.markdown new file mode 100644 index 00000000..e6c29a46 --- /dev/null +++ b/website/docs/d/feature_flag.html.markdown @@ -0,0 +1,84 @@ +--- +layout: "launchdarkly" +page_title: "LaunchDarkly: launchdarkly_feature_flag" +description: |- + Get information about LaunchDarkly feature flags. +--- + +# launchdarkly_feature_flag + +Provides a LaunchDarkly feature flag data source. + +This data source allows you to retrieve feature flag information from your LaunchDarkly organization. + +## Example Usage + +```hcl +data "launchdarkly_feature_flag" "example" { + key = "example-flag" + project_key = "example-project" +} +``` + +## Argument Reference + +- `project_key` - (Required) The feature flag's project key. + +- `key` - (Required) The unique feature flag key that references the flag in your application code. + +## Attributes Reference + +In addition to the arguments above, the resource exports the following attributes if set: + +- `id` - The unique feature flag ID in the format `project_key/flag_key`. + +- `name` - The human-readable name of the feature flag. + +- `variation_type` - The feature flag's variation type: `boolean`, `string`, `number` or `json`. + +- `variations` - List of nested blocks describing the variations associated with the feature flag. To learn more, read [Nested Variations Blocks](#nested-variations-blocks). + +- `default_on_variation` - The value of the variation served when the flag is on for new environments. + +- `default_off_variation` - The value of the variation served when the flag is off for new environments. + +- `description` - The feature flag's description. + +- `tags` - Set of feature flag tags. + +- `maintainer_id` - The feature flag maintainer's 24 character alphanumeric team member ID. + +- `temporary` - Whether the flag is a temporary flag. + +- `client_side_availability` - A map describing whether this flag has been made available to the client-side JavaScript SDK. To learn more, read [Nested Client-Side Availability Block](#nested-client-side-availability-block). + +- `custom_properties` - List of nested blocks describing the feature flag's [custom properties](https://docs.launchdarkly.com/docs/custom-properties). To learn more, read [Nested Custom Properties](#nested-custom-properties). + +### Nested Variations Blocks + +Nested `variations` blocks have the following attributes: + +- `value` - The variation value. + +- `name` - The name of the variation. + +- `description` - The variation's description. + +### Nested Client-Side Availibility Block + +The nested `client_side_availability` block has the following attributes: + +- `using_environment_id` - When set to true, this flag is available to SDKs using the client-side ID. + +- `using_mobile_key` - When set to true, this flag is available to SDKs using a mobile key. + +### Nested Custom Properties + +Nested `custom_properties` have the following attributes: + +- `key` - The unique custom property key. + +- `name` - The name of the custom property. + +- `value` - The list of custom property value strings. + diff --git a/website/docs/d/feature_flag_environment.html.markdown b/website/docs/d/feature_flag_environment.html.markdown new file mode 100644 index 00000000..f3b42d24 --- /dev/null +++ b/website/docs/d/feature_flag_environment.html.markdown @@ -0,0 +1,100 @@ +--- +layout: "launchdarkly" +page_title: "LaunchDarkly: launchdarkly_feature_flag_environment" +description: |- + Get information about LaunchDarkly environment-specific feature flag configurations. +--- + +# launchdarkly_feature_flag_environment + +Provides a LaunchDarkly environment-specific feature flag data source. + +This data source allows you to retrieve environment-specific feature flag information from your LaunchDarkly organization. + +## Example Usage + +```hcl +data "launchdarkly_feature_flag_environment" "example" { + flag_id = "example-project/example-flag" + env_key = "example-env" +} +``` + +## Argument Reference + +- `flag_id` - (Required) The feature flag's unique `id` in the format `project_key/flag_key`. + +- `env_key` - (Required) The environment key. + +## Attributes Reference + +In addition to the arguments above, the resource exports the following attributes: + +- `targeting_enabled` - Whether targeting is enabled. + +- `track_events` - Whether event data will be sent back to LaunchDarkly. + +- `off_variation` - The index of the variation served when targeting is disabled. + +- `prerequisites` - List of nested blocks describing prerequisite feature flags rules. To learn more, read [Nested Prequisites Blocks](#nested-prerequisites-blocks). + +- `user_targets` - List of nested blocks describing the individual user targets for each variation. The order of the `user_targets` blocks determines the index of the variation to serve if a `user_target` is matched. To learn more, read [Nested User Target Blocks](#nested-user-targets-blocks). + +- `rules` - List of logical targeting rules. To learn more, read [Nested Rules Blocks](#nested-rules-blocks). + +- `flag_fallthrough` - Nested block describing the default variation to serve if no `prerequisites`, `user_target`, or `rules` apply. To learn more, read [Nested Flag Fallthrough Block](#nested-flag-fallthrough-block). + +### Nested Prerequisites Blocks + +Nested `prerequisites` blocks have the following structure: + +- `flag_key` - The prerequisite feature flag's `key`. + +- `variation` - The index of the prerequisite feature flag's variation targeted. + +### Nested User Targets Blocks + +Nested `user_targets` blocks have the following structure: + +- `values` - List of `user` strings to target. + +### Nested Flag Fallthrough Block + +The nested `flag_fallthrough` block has the following structure: + +- `variation` - The default integer variation index served if no `prerequisites`, `user_target`, or `rules` apply. + +- `rollout_weights` - List of integer percentage rollout weights applied to each variation when no `prerequisites`, `user_target`, or `rules` apply. + +- `bucket_by` - Group percentage rollout by a custom attribute. + +### Nested Rules Blocks + +Nested `rules` blocks have the following structure: + +- `clauses` - List of nested blocks specifying the logical clauses evaluated. To learn more, read [Nested Clauses Blocks](#nested-clauses-blocks). + +- `variation` - The integer variation index served if the rule clauses evaluate to `true`. + +- `rollout_weights` - List of integer percentage rollout weights applied to each variation when the rule clauses evaluates to `true`. + +- `bucket_by` - Group percentage rollout by a custom attribute. + +### Nested Clauses Blocks + +Nested `clauses` blocks have the following structure: + +- `attribute` - The user attribute operated on. + +- `op` - The operator associated with the rule clause. This will be one of `in`, `endsWith`, `startsWith`, `matches`, `contains`, `lessThan`, `lessThanOrEqual`, `greaterThanOrEqual`, `before`, `after`, `segmentMatch`, `semVerEqual`, `semVerLessThan`, and `semVerGreaterThan`. + +- `values` - The list of values associated with the rule clause. + +- `negate` - Whether the rule clause is negated. + +Nested `flag_fallthrough` blocks have the following structure: + +- `variation` - The integer variation index served when the rule clauses evaluate to `true`. + +- `rollout_weights` - List of integer percentage rollout weights applied to each variation when the rule clauses evaluates to `true`. + diff --git a/website/docs/d/project.html.markdown b/website/docs/d/project.html.markdown new file mode 100644 index 00000000..b7c4dc94 --- /dev/null +++ b/website/docs/d/project.html.markdown @@ -0,0 +1,42 @@ +--- +layout: "launchdarkly" +page_title: "LaunchDarkly: launchdarkly_project" +description: |- + Get information about LaunchDarkly projects. +--- + +# launchdarkly_project + +Provides a LaunchDarkly project data source. + +This data source allows you to retrieve project information from your LaunchDarkly organization. + +## Example Usage + +```hcl +data "launchdarkly_project" "example" { + key = "example-project" +} +``` + +## Argument Reference + +- `key` - (Required) The project's unique key. + +## Attributes Reference + +In addition to the arguments above, the resource exports the following attributes: + +- `name` - The project's name. + +- `client_side_availability` - A map describing whether flags in this project are available to the client-side JavaScript SDK by default. To learn more, read [Nested Client-Side Availability Block](#nested-client-side-availability-block). + +- `tags` - The project's set of tags. + +### Nested Client-Side Availibility Block + +The nested `client_side_availability` block has the following attributes: + +- `using_environment_id` - When set to true, the flags in this project are available to SDKs using the client-side ID by default. + +- `using_mobile_key` - When set to true, the flags in this project are available to SDKs using a mobile key by default. diff --git a/website/docs/d/segment.html.markdown b/website/docs/d/segment.html.markdown new file mode 100644 index 00000000..6968bd57 --- /dev/null +++ b/website/docs/d/segment.html.markdown @@ -0,0 +1,72 @@ +--- +layout: "launchdarkly" +page_title: "LaunchDarkly: launchdarkly_segment" +description: |- + Get information about LaunchDarkly segments. +--- + +# launchdarkly_segment + +Provides a LaunchDarkly segment data source. + +This data source allows you to retrieve segment information from your LaunchDarkly organization. + +## Example Usage + +```hcl +data "launchdarkly_segment" "example" { + key = "example-segment" + project_key = "example-project" + env_key = "example-env" +} +``` + +## Argument Reference + +- `key` - (Required) The unique key that references the segment. + +- `project_key` - (Required) The segment's project key. + +- `env_key` - (Required) The segment's environment key. + +## Attributes Reference + +In addition to the arguments above, the resource exports the following attribute: + +- `id` - The unique environment ID in the format `project_key/env_key/segment_key`. + +- `name` - The human-friendly name for the segment. + +- `description` - The description of the segment's purpose. + +- `tags` - Set of tags for the segment. + +- `included` - List of users included in the segment. + +- `excluded` - List of user excluded from the segment. + +- `rules` - List of nested custom rule blocks to apply to the segment. To learn more, read [Nested Rules Blocks](#nested-rules-blocks). + +### Nested Rules Blocks + +Nested `rules` blocks have the following structure: + +- `weight` - The integer weight of the rule (between 1 and 100000). + +- `bucket_by` - The attribute by which to group users together. + +- `clauses` - List of nested custom rule clause blocks. To learn more, read [Nested Clauses Blocks](#nested-clauses-blocks). + +### Nested Clauses Blocks + +Nested `clauses` blocks have the following structure: + +- `attribute` - The user attribute operated on. + +- `op` - The operator associated with the rule clause. This will be one of `in`, `endsWith`, `startsWith`, `matches`, `contains`, `lessThan`, `lessThanOrEqual`, `greaterThanOrEqual`, `before`, `after`, `segmentMatch`, `semVerEqual`, `semVerLessThan`, and `semVerGreaterThan`. + +- `values` - The list of values associated with the rule clause. + +- `negate` - Whether the rule clause is negated. + + diff --git a/website/docs/d/team_member.html.markdown b/website/docs/d/team_member.html.markdown index 62f092db..abd969dc 100644 --- a/website/docs/d/team_member.html.markdown +++ b/website/docs/d/team_member.html.markdown @@ -9,7 +9,7 @@ description: |- Provides a LaunchDarkly team member data source. -This resource allows you to retrieve team member information from your LaunchDarkly organization. +This data source allows you to retrieve team member information from your LaunchDarkly organization. ## Example Usage diff --git a/website/docs/d/webhook.html.markdown b/website/docs/d/webhook.html.markdown new file mode 100644 index 00000000..6678dfff --- /dev/null +++ b/website/docs/d/webhook.html.markdown @@ -0,0 +1,53 @@ +--- +layout: "launchdarkly" +page_title: "LaunchDarkly: launchdarkly_webhook" +description: |- + Get information about LaunchDarkly webhooks. +--- + +# launchdarkly_webhook + +Provides a LaunchDarkly webhook data source. + +This data source allows you to retrieve webhook information from your LaunchDarkly organization. + +## Example Usage + +```hcl +data "launchdarkly_webhook" "example" { + id = "57c0af6099690907435299" +} +``` + +## Argument Reference +- `id` - (Required) The unique webhook ID. + +## Attributes Reference + +In addition to the arguments above, the resource exports following attributes: + +- `url` - The URL of the remote webhook. + +- `enabled` - Whether the webhook is enabled. + +- `name` - The webhook's human-readable name. + +- `secret` - The secret used to sign the webhook. + +- `tags` - Set of tags associated with the webhook. + +- `policy_statements` - List of policy statement blocks used to filter webhook events. For more information on webhook policy filters read [Adding a policy filter](https://docs.launchdarkly.com/integrations/webhooks#adding-a-policy-filter). To learn more, read [Policy Statement Blocks](#policy-statement-blocks). + +### Policy Statement Blocks + +Webhook `policy_statements` blocks are composed of the following arguments: + +- `effect` - Either `allow` or `deny`. This argument defines whether the statement allows or denies access to the named resources and actions. + +- `resources` - The list of resource specifiers defining the resources to which the statement applies. For a list of available resources read [Understanding resource types and scopes](https://docs.launchdarkly.com/home/account-security/custom-roles/resources#understanding-resource-types-and-scopes). + +- `not_resources` - The list of resource specifiers defining the resources to which the statement does not apply. For a list of available resources read [Understanding resource types and scopes](https://docs.launchdarkly.com/home/account-security/custom-roles/resources#understanding-resource-types-and-scopes). + +- `actions` The list of action specifiers defining the actions to which the statement applies. For a list of available actions read [Actions reference](https://docs.launchdarkly.com/home/account-security/custom-roles/actions#actions-reference). + +- `not_actions` The list of action specifiers defining the actions to which the statement does not apply. For a list of available actions read [Actions reference](https://docs.launchdarkly.com/home/account-security/custom-roles/actions#actions-reference). \ No newline at end of file diff --git a/website/docs/r/environment.html.markdown b/website/docs/r/environment.html.markdown index 7ac82439..9e60e6a3 100644 --- a/website/docs/r/environment.html.markdown +++ b/website/docs/r/environment.html.markdown @@ -11,6 +11,8 @@ Provides a LaunchDarkly environment resource. This resource allows you to create and manage environments in your LaunchDarkly organization. +-> **Note:** Mixing the use of nested `environments` blocks in the [`launchdarkly_project`](/docs/providers/launchdarkly/r/project.html) resource and `launchdarkly_environment` resources is not recommended. + ## Example Usage ```hcl @@ -42,11 +44,10 @@ resource "launchdarkly_environment" "staging" { - `default_ttl` - (Optional) The TTL for the environment. This must be between 0 and 60 minutes. The TTL setting only applies to environments using the PHP SDK. To learn more, read [TTL settings](https://docs.launchdarkly.com/docs/environments#section-ttl-settings). -- `require_comments` - (Optional) Set to `true` if this environment requires comments for flag and segment changes. +- `require_comments` - (Optional) Set to `true` if this environment requires comments for flag and segment changes. - `confirm_changes` - (Optional) Set to `true` if this environment requires confirmation for flag and segment changes. - ## Attribute Reference In addition to the arguments above, the resource exports the following attributes: diff --git a/website/docs/r/feature_flag.html.markdown b/website/docs/r/feature_flag.html.markdown index 4f409b56..1508a5b2 100644 --- a/website/docs/r/feature_flag.html.markdown +++ b/website/docs/r/feature_flag.html.markdown @@ -49,6 +49,27 @@ resource "launchdarkly_feature_flag" "building_materials" { } ``` +```hcl +resource "launchdarkly_feature_flag" "json_example" { + project_key = "example-project" + key = "json-example" + name = "JSON example flag" + + variation_type = "json" + variations { + name = "Single foo" + value = jsonencode({ "foo" : "bar" }) + } + variations { + name = "Multiple foos" + value = jsonencode({ "foos" : ["bar1", "bar2"] }) + } + + default_on_variation = jsonencode({ "foos" : ["bar1", "bar2"] }) + default_off_variation = jsonencode({ "foo" : "bar" }) +} +``` + ## Argument Reference - `project_key` - (Required) The feature flag's project key. @@ -61,9 +82,9 @@ resource "launchdarkly_feature_flag" "building_materials" { - `variations` - (Required) List of nested blocks describing the variations associated with the feature flag. You must specify at least two variations. To learn more, read [Nested Variations Blocks](#nested-variations-blocks). -- `default_on_variation` - (Optional) The value of the variation served when the flag is on for new environments. Required if `default_off_variation` is set. Flag configurations in existing environments will not be changed. +- `default_on_variation` - (Optional) The value of the variation served when the flag is on for new environments. Required if `default_off_variation` is set. Flag configurations in existing environments will not be changed. The value used here must be an exact match (including whitespace) to the `value` set in the `variations` list. -- `default_off_variation` - (Optional) The value of the variation served when the flag is off for new environments. Required if `default_on_variation` is set. Flag configurations in existing environments will not be changed. +- `default_off_variation` - (Optional) The value of the variation served when the flag is off for new environments. Required if `default_on_variation` is set. Flag configurations in existing environments will not be changed. The value used here must be an exact match (including whitespace) to the `value` set in the `variations` list. - `description` - (Optional) The feature flag's description. diff --git a/website/docs/r/project.html.markdown b/website/docs/r/project.html.markdown index d405f723..2725d8d9 100644 --- a/website/docs/r/project.html.markdown +++ b/website/docs/r/project.html.markdown @@ -21,6 +21,20 @@ resource "launchdarkly_project" "example" { tags = [ "terraform", ] + + environments { + key = "production" + name = "Production" + color = "EEEEEE" + tags = ["terraform"] + } + + environments { + key = "staging" + name = "Staging" + color = "000000" + tags = ["terraform"] + } } ``` @@ -32,6 +46,32 @@ resource "launchdarkly_project" "example" { - `tags` - (Optional) The project's set of tags. +- `environments` - (Optional) List of nested `environments` blocks describing LaunchDarkly environments that belong to the project. Use the nested `environments` blocks instead of the `launchdarkly_environment` resource when you wish to override the default behavior of creating `Test` and `Production` environments during project creation. To learn more, read [Nested Environments Blocks](#nested-environments-blocks). + +-> **Note:** Mixing the use of nested `environments` blocks and [`launchdarkly_environment`](/docs/providers/launchdarkly/r/environment.html) resources is not recommended. + +### Nested Environments Blocks + +Nested `environments` blocks have the following structure: + +- `name` - (Required) The name of the environment. + +- `key` - (Required) The project-unique key for the environment. + +- `color` - (Required) The color swatch as an RGB hex value with no leading `#`. For example: `000000`. + +- `tags` - (Optional) Set of tags associated with the environment. + +- `secure_mode` - (Optional) Set to `true` to ensure a user of the client-side SDK cannot impersonate another user. + +- `default_track_events` - (Optional) Set to `true` to enable data export for every flag created in this environment after you configure this argument. To learn more, read [Data Export](https://docs.launchdarkly.com/docs/data-export). + +- `default_ttl` - (Optional) The TTL for the environment. This must be between 0 and 60 minutes. The TTL setting only applies to environments using the PHP SDK. To learn more, read [TTL settings](https://docs.launchdarkly.com/docs/environments#section-ttl-settings). + +- `require_comments` - (Optional) Set to `true` if this environment requires comments for flag and segment changes. + +- `confirm_changes` - (Optional) Set to `true` if this environment requires confirmation for flag and segment changes. + ## Import LaunchDarkly projects can be imported using the project's key, e.g. diff --git a/website/docs/r/segment.html.markdown b/website/docs/r/segment.html.markdown index 2b1a51b4..9466fc42 100644 --- a/website/docs/r/segment.html.markdown +++ b/website/docs/r/segment.html.markdown @@ -61,7 +61,7 @@ Nested `rules` blocks have the following structure: - `weight` - (Optional) The integer weight of the rule (between 1 and 100000). -- `bucket_by` - (Optional) The operator used to group users together. Available options are `in`, `endsWith`, `startsWith`, `matches`, `contains`, `lessThan`, `lessThanOrEqual`, `greaterThanOrEqual`, `before`, `after`, `segmentMatch`, `semVerEqual`, `semVerLessThan`, and `semVerGreaterThan`. +- `bucket_by` - (Optional) The attribute by which to group users together. - `clauses` - (Optional) List of nested custom rule clause blocks. To learn more, read [Nested Clauses Blocks](#nested-clauses-blocks). diff --git a/website/docs/r/webhook.html.markdown b/website/docs/r/webhook.html.markdown index 077d9921..9b54c42b 100644 --- a/website/docs/r/webhook.html.markdown +++ b/website/docs/r/webhook.html.markdown @@ -35,25 +35,25 @@ resource "launchdarkly_webhook" "example" { ## Argument Reference -- `url` - (Required) - The URL of the remote webhook. +- `url` - (Required) The URL of the remote webhook. -- `enabled` - (Required) - Specifies whether the webhook is enabled. +- `enabled` - (Required) Specifies whether the webhook is enabled. -- `name` - (Optional) - The webhook's human-readable name. +- `name` - (Optional) The webhook's human-readable name. -- `secret` - (Optional) - The secret used to sign the webhook. +- `secret` - (Optional) The secret used to sign the webhook. -- `tags` - (Optional) - Set of tags associated with the webhook. +- `tags` - (Optional) Set of tags associated with the webhook. -- `policy_statements` - (Optional) - List of policy statement blocks used to filter webhook events. For mor information on webhook policy filters read [Adding a policy filter](https://docs.launchdarkly.com/integrations/webhooks#adding-a-policy-filter) +- `policy_statements` - (Optional) List of policy statement blocks used to filter webhook events. For more information on webhook policy filters read [Adding a policy filter](https://docs.launchdarkly.com/integrations/webhooks#adding-a-policy-filter) Webhook `policy_statements` blocks are composed of the following arguments: -- `effect` - (Required) - Either `allow` or `deny`. This argument defines whether the statement allows or denies access to the named resources and actions. +- `effect` - (Required) Either `allow` or `deny`. This argument defines whether the statement allows or denies access to the named resources and actions. -- `resources` - (Optional) - The list of resource specifiers defining the resources to which the statement applies. Either `resources` or `not_resources` must be specified. For a list of available resources read [Understanding resource types and scopes](https://docs.launchdarkly.com/home/account-security/custom-roles/resources#understanding-resource-types-and-scopes). +- `resources` - (Optional) The list of resource specifiers defining the resources to which the statement applies. Either `resources` or `not_resources` must be specified. For a list of available resources read [Understanding resource types and scopes](https://docs.launchdarkly.com/home/account-security/custom-roles/resources#understanding-resource-types-and-scopes). -- `not_resources` - (Optional) - The list of resource specifiers defining the resources to which the statement does not apply. Either `resources` or `not_resources` must be specified. For a list of available resources read [Understanding resource types and scopes](https://docs.launchdarkly.com/home/account-security/custom-roles/resources#understanding-resource-types-and-scopes). +- `not_resources` - (Optional) The list of resource specifiers defining the resources to which the statement does not apply. Either `resources` or `not_resources` must be specified. For a list of available resources read [Understanding resource types and scopes](https://docs.launchdarkly.com/home/account-security/custom-roles/resources#understanding-resource-types-and-scopes). - `actions` - (Optional) The list of action specifiers defining the actions to which the statement applies. Either `actions` or `not_actions` must be specified. For a list of available actions read [Actions reference](https://docs.launchdarkly.com/home/account-security/custom-roles/actions#actions-reference). diff --git a/website/launchdarkly.erb b/website/launchdarkly.erb index f07b5535..5065c875 100644 --- a/website/launchdarkly.erb +++ b/website/launchdarkly.erb @@ -11,6 +11,24 @@