Skip to content

Commit

Permalink
Merge pull request #6 from jmorissette/fix-made-provider-backward-com…
Browse files Browse the repository at this point in the history
…patible-with-configuration-made-with-version-1.0.8

Fix made provider backward compatible with configuration made with version 1.0.8
  • Loading branch information
jmorissette authored Oct 31, 2019
2 parents e0a155d + bdd62c6 commit f7af966
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 48 deletions.
6 changes: 6 additions & 0 deletions launchdarkly/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ type JsonVariations struct {
Description string `json:"description"`
}

type DefaultVariations struct {
Value string `json:"value"`
Environment string `json:"environment"`
}

type JsonCustomProperty struct {
Name string `json:"name"`
Value []string `json:"value"`
Expand All @@ -31,6 +36,7 @@ type JsonFeatureFlag struct {
Description string `json:"description"`
Temporary bool `json:"temporary"`
IncludeInSnippet bool `json:"includeInSnippet"`
VariationsKind string `json:"kind"`
Variations []JsonVariations `json:"variations"`
Tags []string `json:"tags"`
CustomProperties map[string]JsonCustomProperty `json:"customProperties"`
Expand Down
168 changes: 120 additions & 48 deletions launchdarkly/resource_feature_flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,45 @@ func resourceFeatureFlag() *schema.Resource {
ForceNew: true,
},
"default_targeting_rule": {
Type: schema.TypeString,
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"value": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateVariationValue,
},
"environment": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateKey ,
},
},
},
},
"default_off_targeting_rule": {
Type: schema.TypeString,
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"value": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateVariationValue,
},
"environment": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateKey ,
},
},
},
},
"variations": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MinItems: 2,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -136,10 +165,10 @@ func resourceFeatureFlagCreate(d *schema.ResourceData, m interface{}) error {
temporary := d.Get("temporary").(bool)
includeInSnippet := d.Get("include_in_snippet").(bool)
tags := d.Get("tags").([]interface{})
variationsKind := d.Get("variations_kind").(string)
variationsKind := validateOrDefaultToBoolean(d.Get("variations_kind").(string))
variations := d.Get("variations").([]interface{})
defaultTargetingRule := d.Get("default_targeting_rule").(string)
defaultOffTargetingRule := d.Get("default_off_targeting_rule").(string)
defaultTargetingRule := d.Get("default_targeting_rule").([]interface{})
defaultOffTargetingRule := d.Get("default_off_targeting_rule").([]interface{})
customProperties := d.Get("custom_properties").([]interface{})

transformedVariations, err := transformVariationsFromTerraformFormat(variations, variationsKind)
Expand All @@ -152,16 +181,6 @@ func resourceFeatureFlagCreate(d *schema.ResourceData, m interface{}) error {
return err
}

transformedDefaultTargetingRule, err := getDefaultVariationIndex(variations, defaultTargetingRule)
if err != nil {
return err
}

transformedDefaultOffTargetingRule, err := getDefaultOffVariationIndex(variations, defaultOffTargetingRule)
if err != nil {
return err
}

payload := JsonFeatureFlag{
Name: name,
Key: key,
Expand All @@ -179,21 +198,24 @@ func resourceFeatureFlagCreate(d *schema.ResourceData, m interface{}) error {
return err
}

patchPayload := []map[string]interface{}{{
"op": "replace",
"path": "/environments/dev/fallthrough/variation",
"value": transformedDefaultTargetingRule,
}, {
"op": "replace",
"path": "/environments/dev/offVariation",
"value": transformedDefaultOffTargetingRule,
}}

_, err = client.Patch(getFlagUrl(project, key), patchPayload, []int{200})
defaultTargetinRulePayload, err := createPayloadForDefaultTargeting(defaultTargetingRule, variations)
if err != nil {
return err
}
offOffTargetingRulePayload, err := createPayloadForDefaultOffTargeting(defaultOffTargetingRule, variations)
if err != nil {
return err
}

patchPayload := append(defaultTargetinRulePayload, offOffTargetingRulePayload...)

if len(patchPayload) > 0 {
_, err = client.Patch(getFlagUrl(project, key), patchPayload, []int{200})
if err != nil {
return err
}
}

d.SetId(key)
d.Set("name", name)
d.Set("key", key)
Expand Down Expand Up @@ -232,6 +254,11 @@ func resourceFeatureFlagRead(d *schema.ResourceData, m interface{}) error {
d.Set("temporary", response.Temporary)
d.Set("include_in_snippet", response.IncludeInSnippet)
d.Set("tags", response.Tags)
// This is a hack to prevent recreating a feature flag when it was created with an older
// version of the provider that didn't supported specifying the variations kind
if response.VariationsKind == VARIATIONS_BOOLEAN_KIND {
d.Set("variations_kind", response.VariationsKind)
}
if err := d.Set("variations", transformedVariations); err != nil {
return err
}
Expand All @@ -244,16 +271,16 @@ func resourceFeatureFlagRead(d *schema.ResourceData, m interface{}) error {

func resourceFeatureFlagUpdate(resourceData *schema.ResourceData, m interface{}) error {
client := m.(Client)

project := resourceData.Get("project_key").(string)
name := resourceData.Get("name").(string)
description := resourceData.Get("description").(string)
temporary := resourceData.Get("temporary").(bool)
includeInSnippet := resourceData.Get("include_in_snippet").(bool)
tags := resourceData.Get("tags").([]interface{})
customProperties := resourceData.Get("custom_properties").([]interface{})
defaultTargetingRule := resourceData.Get("default_targeting_rule").(string)
defaultOffTargetingRule := resourceData.Get("default_off_targeting_rule").(string)
variations := resourceData.Get("variations").([]interface{})
defaultTargetingRule := resourceData.Get("default_targeting_rule").([]interface{})
defaultOffTargetingRule := resourceData.Get("default_off_targeting_rule").([]interface{})

transformedCustomProperties, err := transformCustomPropertiesFromTerraformFormat(customProperties)
if err != nil {
Expand All @@ -263,19 +290,19 @@ func resourceFeatureFlagUpdate(resourceData *schema.ResourceData, m interface{})
if err := applyChangesToVariations(resourceData, client); err != nil {
return err
}

transformedDefaultTargetingRule, err := getDefaultVariationIndex(resourceData.Get("variations").([]interface{}), defaultTargetingRule)
defaultTargetingRulePayload, err := createPayloadForDefaultTargeting(defaultTargetingRule, variations)
if err != nil {
return err
}

transformedDefaultOffTargetingRule, err := getDefaultOffVariationIndex(resourceData.Get("variations").([]interface{}), defaultOffTargetingRule)
defaultOffTargetingRulePayload, err := createPayloadForDefaultOffTargeting(defaultOffTargetingRule, variations)
if err != nil {
return err
}


payload := []map[string]interface{}{{
targetingPayload := append(defaultTargetingRulePayload, defaultOffTargetingRulePayload...)

mainPayload := []map[string]interface{}{{
"op": "replace",
"path": "/name",
"value": name,
Expand All @@ -299,16 +326,10 @@ func resourceFeatureFlagUpdate(resourceData *schema.ResourceData, m interface{})
"op": "replace",
"path": "/customProperties",
"value": transformedCustomProperties,
},{
"op": "replace",
"path": "/environments/dev/fallthrough/variation",
"value": transformedDefaultTargetingRule,
}, {
"op": "replace",
"path": "/environments/dev/offVariation",
"value": transformedDefaultOffTargetingRule,
}}

payload := append(mainPayload, targetingPayload...)

_, err = client.Patch(getFlagUrl(project, resourceData.Id()), payload, []int{200})
if err != nil {
return err
Expand Down Expand Up @@ -340,16 +361,59 @@ func transformTagsFromTerraformFormat(tags []interface{}) []string {
return transformed
}

func createPayloadForDefaultTargeting(defaultTargetingRules []interface{}, variations []interface{}) ([]map[string]interface{}, error) {
patchPayload := make([]map[string]interface{}, len(defaultTargetingRules))
for index, defaultTargetingRule := range defaultTargetingRules {
targetingRule := defaultTargetingRule.(map[string]interface{})

variationIndex, err := getDefaultVariationIndex(variations, targetingRule["value"].(string))
if err != nil {
return nil, err
}

patchPayload[index] = map[string]interface{}{
"op": "replace",
"path": fmt.Sprintf("/environments/%s/fallthrough/variation", targetingRule["environment"].(string)),
"value": variationIndex,
}
}
return patchPayload, nil
}

func createPayloadForDefaultOffTargeting(defaultOffTargetingRules []interface{}, variations []interface{}) ([]map[string]interface{}, error) {
patchPayload := make([]map[string]interface{}, len(defaultOffTargetingRules))
for index, defaultOffTargetingRule := range defaultOffTargetingRules {
targetingRule := defaultOffTargetingRule.(map[string]interface{})

variationIndex, err := getDefaultOffVariationIndex(variations, targetingRule["value"].(string))
if err != nil {
return nil, err
}
patchPayload[index] = map[string]interface{}{
"op": "replace",
"path": fmt.Sprintf("/environments/%s/offVariation", targetingRule["environment"].(string)),
"value": variationIndex,
}
}
return patchPayload, nil
}


func getDefaultVariationIndex(variations []interface{}, variationValue string) (int, error) {
if len(variationValue) > 0 {
return getVariationIndex(variations, variationValue)
if len(variations) > 0 {
if len(variationValue) > 0 {
return getVariationIndex(variations, variationValue)
}
return len(variations) - 1, nil
}
return len(variations) - 1, nil
return 1, nil
}

func getDefaultOffVariationIndex(variations []interface{}, variationValue string) (int, error) {
if len(variationValue) > 0 {
return getVariationIndex(variations, variationValue)
if len(variations) > 0 {
if len(variationValue) > 0 {
return getVariationIndex(variations, variationValue)
}
}
return 0, nil
}
Expand Down Expand Up @@ -525,3 +589,11 @@ func transformCustomPropertiesFromLaunchDarklyFormat(properties map[string]JsonC

return transformed
}

func validateOrDefaultToBoolean(variationsKind string) string {
if len(variationsKind) > 0 {
return variationsKind
}

return DEFAULT_VARIATIONS_KIND
}

0 comments on commit f7af966

Please sign in to comment.