Skip to content

Commit 6a11d70

Browse files
committed
Add support for enumerated tag values
1 parent fedbbdb commit 6a11d70

9 files changed

+218
-18
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
- Support DBaaS VM DB Fast Provisioning
55
- Support for required default tags
66
- Support for moving `oci_core_drg` resources across compartments
7+
- Support for enumerated tag values
78

89
### Fixed
10+
911
- Fix compositeId parsing for pre-authenticated requests in object storage [Issue #867](https://github.com/terraform-providers/terraform-provider-oci/issues/867)
1012
- Fixed ssl_configuration is optional only in `oci_load_balancer_backend_set` resource
1113

examples/identity/tags.tf

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ resource "oci_identity_tag" "tag1" {
1616
tag_namespace_id = "${oci_identity_tag_namespace.tag-namespace1.id}"
1717

1818
#Optional
19-
is_cost_tracking = false // default is "false". The value "true" is only permitted if the associated tag namespace is part of the root compartment.
19+
is_cost_tracking = false // default is "false". The value "true" is only permitted if the associated tag namespace is part of the root compartment.
2020
is_retired = false
21+
22+
validator {
23+
validator_type = "ENUM"
24+
values = ["test_value", "value1", "value2"]
25+
}
2126
}
2227

2328
resource "oci_identity_tag_default" "tag_default" {

oci/identity_cost_tracking_tags_data_source.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,32 @@ func IdentityCostTrackingTagsDataSource() *schema.Resource {
7878
Type: schema.TypeString,
7979
Computed: true,
8080
},
81+
"validator": {
82+
Type: schema.TypeList,
83+
Computed: true,
84+
MaxItems: 1,
85+
MinItems: 1,
86+
Elem: &schema.Resource{
87+
Schema: map[string]*schema.Schema{
88+
// Required
89+
90+
// Optional
91+
92+
// Computed
93+
"validator_type": {
94+
Type: schema.TypeString,
95+
Computed: true,
96+
},
97+
"values": {
98+
Type: schema.TypeList,
99+
Computed: true,
100+
Elem: &schema.Schema{
101+
Type: schema.TypeString,
102+
},
103+
},
104+
},
105+
},
106+
},
81107
},
82108
},
83109
},
@@ -198,6 +224,16 @@ func (s *IdentityCostTrackingTagsDataSourceCrud) SetData() error {
198224
costTrackingTag["time_created"] = r.TimeCreated.String()
199225
}
200226

227+
if r.Validator != nil {
228+
validatorArray := []interface{}{}
229+
if validatorMap := BaseTagDefinitionValidatorToMap(&r.Validator); validatorMap != nil {
230+
validatorArray = append(validatorArray, validatorMap)
231+
}
232+
costTrackingTag["validator"] = validatorArray
233+
} else {
234+
costTrackingTag["validator"] = nil
235+
}
236+
201237
resources = append(resources, costTrackingTag)
202238
}
203239

oci/identity_tag_resource.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ package provider
55
import (
66
"context"
77
"fmt"
8+
"log"
89
"regexp"
910
"strconv"
1011
"strings"
1112

1213
"github.com/hashicorp/terraform/helper/schema"
14+
"github.com/hashicorp/terraform/helper/validation"
1315
oci_identity "github.com/oracle/oci-go-sdk/identity"
1416
)
1517

@@ -69,6 +71,35 @@ func IdentityTagResource() *schema.Resource {
6971
Optional: true,
7072
Computed: true,
7173
},
74+
"validator": {
75+
Type: schema.TypeList,
76+
Optional: true,
77+
MaxItems: 1,
78+
MinItems: 1,
79+
Elem: &schema.Resource{
80+
Schema: map[string]*schema.Schema{
81+
// Required
82+
"validator_type": {
83+
Type: schema.TypeString,
84+
Required: true,
85+
DiffSuppressFunc: EqualIgnoreCaseSuppressDiff,
86+
ValidateFunc: validation.StringInSlice([]string{
87+
"ENUM",
88+
}, true),
89+
},
90+
91+
"values": {
92+
Type: schema.TypeList,
93+
Required: true,
94+
Elem: &schema.Schema{
95+
Type: schema.TypeString,
96+
},
97+
},
98+
99+
// Computed
100+
},
101+
},
102+
},
72103

73104
// Computed
74105
"state": {
@@ -190,6 +221,17 @@ func (s *IdentityTagResourceCrud) Create() error {
190221
request.TagNamespaceId = &tmp
191222
}
192223

224+
if validator, ok := s.D.GetOkExists("validator"); ok {
225+
if tmpList := validator.([]interface{}); len(tmpList) > 0 {
226+
fieldKeyFormat := fmt.Sprintf("%s.%d.%%s", "validator", 0)
227+
tmp, err := s.mapToBaseTagDefinitionValidator(fieldKeyFormat)
228+
if err != nil {
229+
return err
230+
}
231+
request.Validator = tmp
232+
}
233+
}
234+
193235
request.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "identity")
194236

195237
contextToUse := context.Background()
@@ -315,6 +357,23 @@ func (s *IdentityTagResourceCrud) Update() error {
315357
request.TagNamespaceId = &tmp
316358
}
317359

360+
if validator, ok := s.D.GetOkExists("validator"); ok {
361+
if tmpList := validator.([]interface{}); len(tmpList) > 0 {
362+
fieldKeyFormat := fmt.Sprintf("%s.%d.%%s", "validator", 0)
363+
tmp, err := s.mapToBaseTagDefinitionValidator(fieldKeyFormat)
364+
if err != nil {
365+
return err
366+
}
367+
request.Validator = tmp
368+
} else {
369+
// For case when updating ENUM type to DEFAULT: validator absent in config but s.D.GetOkExists("validator") returns true
370+
var baseObject oci_identity.BaseTagDefinitionValidator
371+
details := oci_identity.DefaultTagDefinitionValidator{}
372+
baseObject = details
373+
request.Validator = baseObject
374+
}
375+
}
376+
318377
request.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "identity")
319378

320379
response, err := s.Client.UpdateTag(context.Background(), request)
@@ -407,9 +466,70 @@ func (s *IdentityTagResourceCrud) SetData() error {
407466
s.D.Set("time_created", s.Res.TimeCreated.String())
408467
}
409468

469+
if s.Res.Validator != nil {
470+
validatorArray := []interface{}{}
471+
if validatorMap := BaseTagDefinitionValidatorToMap(&s.Res.Validator); validatorMap != nil {
472+
validatorArray = append(validatorArray, validatorMap)
473+
}
474+
s.D.Set("validator", validatorArray)
475+
} else {
476+
s.D.Set("validator", nil)
477+
}
478+
410479
return nil
411480
}
412481

482+
func (s *IdentityTagResourceCrud) mapToBaseTagDefinitionValidator(fieldKeyFormat string) (oci_identity.BaseTagDefinitionValidator, error) {
483+
var baseObject oci_identity.BaseTagDefinitionValidator
484+
//discriminator
485+
validatorTypeRaw, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "validator_type"))
486+
var validatorType string
487+
if ok {
488+
validatorType = validatorTypeRaw.(string)
489+
} else {
490+
validatorType = "" // default value
491+
}
492+
switch strings.ToLower(validatorType) {
493+
case strings.ToLower("DEFAULT"):
494+
details := oci_identity.DefaultTagDefinitionValidator{}
495+
baseObject = details
496+
case strings.ToLower("ENUM"):
497+
details := oci_identity.EnumTagDefinitionValidator{}
498+
details.Values = []string{}
499+
if values, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "values")); ok {
500+
interfaces := values.([]interface{})
501+
tmp := make([]string, len(interfaces))
502+
for i := range interfaces {
503+
if interfaces[i] != nil {
504+
tmp[i] = interfaces[i].(string)
505+
}
506+
}
507+
details.Values = tmp
508+
}
509+
baseObject = details
510+
default:
511+
return nil, fmt.Errorf("unknown validator_type '%v' was specified", validatorType)
512+
}
513+
return baseObject, nil
514+
}
515+
516+
func BaseTagDefinitionValidatorToMap(obj *oci_identity.BaseTagDefinitionValidator) map[string]interface{} {
517+
result := map[string]interface{}{}
518+
switch v := (*obj).(type) {
519+
case oci_identity.DefaultTagDefinitionValidator:
520+
result["validator_type"] = "DEFAULT"
521+
case oci_identity.EnumTagDefinitionValidator:
522+
result["validator_type"] = "ENUM"
523+
524+
result["values"] = v.Values
525+
default:
526+
log.Printf("[WARN] Received 'validator_type' of unknown type %v", *obj)
527+
return nil
528+
}
529+
530+
return result
531+
}
532+
413533
func parseTagCompositeId(compositeId string) (tagName string, tagNamespaceId string, err error) {
414534
parts := strings.Split(compositeId, "/")
415535
match, _ := regexp.MatchString("tagNamespaces/.*/tags/.*", compositeId)

oci/identity_tag_test.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,16 @@ var (
5757

5858
tagRepresentation = map[string]interface{}{
5959
"description": Representation{repType: Required, create: `This tag will show the cost center that will be used for billing of associated resources.`, update: `description2`},
60-
"name": Representation{repType: Required, create: `CostCenter`},
60+
"name": Representation{repType: Required, create: `TFTestTag`},
6161
"tag_namespace_id": Representation{repType: Required, create: `${oci_identity_tag_namespace.tag-namespace1.id}`},
6262
"defined_tags": Representation{repType: Optional, create: `${map("${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "value")}`, update: `${map("${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "updatedValue")}`},
6363
"freeform_tags": Representation{repType: Optional, create: map[string]string{"Department": "Finance"}, update: map[string]string{"Department": "Accounting"}},
6464
"is_cost_tracking": Representation{repType: Optional, create: `false`, update: `true`},
65+
"validator": RepresentationGroup{Optional, tagValidatorRepresentation},
66+
}
67+
tagValidatorRepresentation = map[string]interface{}{
68+
"validator_type": Representation{repType: Required, create: `ENUM`},
69+
"values": Representation{repType: Required, create: []string{`value1`, `value2`}},
6570
}
6671

6772
TagResourceDependencies = DefinedTagsDependencies
@@ -95,7 +100,7 @@ func TestIdentityTagResource_basic(t *testing.T) {
95100
generateResourceFromRepresentationMap("oci_identity_tag", "test_tag", Required, Create, tagRepresentation),
96101
Check: resource.ComposeAggregateTestCheckFunc(
97102
resource.TestCheckResourceAttr(resourceName, "description", "This tag will show the cost center that will be used for billing of associated resources."),
98-
resource.TestCheckResourceAttr(resourceName, "name", "CostCenter"),
103+
resource.TestCheckResourceAttr(resourceName, "name", "TFTestTag"),
99104
resource.TestCheckResourceAttrSet(resourceName, "tag_namespace_id"),
100105

101106
func(s *terraform.State) (err error) {
@@ -120,9 +125,12 @@ func TestIdentityTagResource_basic(t *testing.T) {
120125
resource.TestCheckResourceAttrSet(resourceName, "id"),
121126
resource.TestCheckResourceAttr(resourceName, "is_cost_tracking", "false"),
122127
resource.TestCheckResourceAttr(resourceName, "is_retired", "false"),
123-
resource.TestCheckResourceAttr(resourceName, "name", "CostCenter"),
128+
resource.TestCheckResourceAttr(resourceName, "name", "TFTestTag"),
124129
resource.TestCheckResourceAttrSet(resourceName, "tag_namespace_id"),
125130
resource.TestCheckResourceAttrSet(resourceName, "time_created"),
131+
resource.TestCheckResourceAttr(resourceName, "validator.#", "1"),
132+
resource.TestCheckResourceAttr(resourceName, "validator.0.validator_type", "ENUM"),
133+
resource.TestCheckResourceAttr(resourceName, "validator.0.values.#", "2"),
126134

127135
func(s *terraform.State) (err error) {
128136
resId, err = fromInstanceState(s, resourceName, "id")
@@ -134,15 +142,15 @@ func TestIdentityTagResource_basic(t *testing.T) {
134142
// verify updates to updatable parameters
135143
{
136144
Config: config + compartmentIdVariableStr + TagResourceDependencies +
137-
generateResourceFromRepresentationMap("oci_identity_tag", "test_tag", Optional, Update, tagRepresentation),
145+
generateResourceFromRepresentationMap("oci_identity_tag", "test_tag", Optional, Update, representationCopyWithRemovedProperties(tagRepresentation, []string{"validator"})),
138146
Check: resource.ComposeAggregateTestCheckFunc(
139147
resource.TestCheckResourceAttr(resourceName, "defined_tags.%", "1"),
140148
resource.TestCheckResourceAttr(resourceName, "description", "description2"),
141149
resource.TestCheckResourceAttr(resourceName, "freeform_tags.%", "1"),
142150
resource.TestCheckResourceAttrSet(resourceName, "id"),
143151
resource.TestCheckResourceAttr(resourceName, "is_cost_tracking", "true"),
144152
resource.TestCheckResourceAttr(resourceName, "is_retired", "false"),
145-
resource.TestCheckResourceAttr(resourceName, "name", "CostCenter"),
153+
resource.TestCheckResourceAttr(resourceName, "name", "TFTestTag"),
146154
resource.TestCheckResourceAttrSet(resourceName, "tag_namespace_id"),
147155
resource.TestCheckResourceAttrSet(resourceName, "time_created"),
148156

@@ -172,7 +180,7 @@ func TestIdentityTagResource_basic(t *testing.T) {
172180
resource.TestCheckResourceAttrSet(datasourceName, "tags.0.id"),
173181
resource.TestCheckResourceAttr(datasourceName, "tags.0.is_cost_tracking", "true"),
174182
resource.TestCheckResourceAttr(datasourceName, "tags.0.is_retired", "false"),
175-
resource.TestCheckResourceAttr(datasourceName, "tags.0.name", "CostCenter"),
183+
resource.TestCheckResourceAttr(datasourceName, "tags.0.name", "TFTestTag"),
176184
resource.TestCheckResourceAttrSet(datasourceName, "tags.0.state"),
177185
resource.TestCheckResourceAttrSet(datasourceName, "tags.0.time_created"),
178186
),

website/docs/d/identity_cost_tracking_tags.html.markdown

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,13 @@ The following attributes are exported:
4646
* `id` - The OCID of the tag definition.
4747
* `is_cost_tracking` - Indicates whether the tag is enabled for cost tracking.
4848
* `is_retired` - Indicates whether the tag is retired. See [Retiring Key Definitions and Namespace Definitions](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/taggingoverview.htm#Retiring).
49-
* `name` - The name of the tag. The name must be unique across all tags in the namespace and can't be changed.
49+
* `name` - The name assigned to the tag during creation. This is the tag key definition. The name must be unique within the tag namespace and cannot be changed.
5050
* `state` - The tag's current state. After creating a tag, make sure its `lifecycleState` is ACTIVE before using it. After retiring a tag, make sure its `lifecycleState` is INACTIVE before using it. If you delete a tag, you cannot delete another tag until the deleted tag's `lifecycleState` changes from DELETING to DELETED.
5151
* `tag_namespace_id` - The OCID of the namespace that contains the tag definition.
5252
* `tag_namespace_name` - The name of the tag namespace that contains the tag definition.
5353
* `time_created` - Date and time the tag was created, in the format defined by RFC3339. Example: `2016-08-25T21:10:29.600Z`
54+
* `validator` - Additional validation rule for values specified for the tag definition.
55+
56+
* `validator_type` - The primitive that any value set for this definedTag must be parseable as.
57+
* `values` - The list of allowed values for a definedTag value.
5458

website/docs/d/identity_regions.html.markdown

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ The following attributes are exported:
4747
* `name` - The name of the region.
4848

4949
Allowed values are:
50-
* `ap-seoul-1`
51-
* `ap-tokyo-1`
52-
* `ca-toronto-1`
53-
* `eu-frankurt-1`
54-
* `uk-london-1`
50+
* `us-phoenix-1`
5551
* `us-ashburn-1`
56-
* `us-phoenix-1`
57-
52+
* `eu-frankfurt-1`
53+
* `uk-london-1`
54+
* `ca-toronto-1`
55+
* `ap-tokyo-1`
56+
* `ap-seoul-1`
57+

website/docs/d/identity_tags.html.markdown

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,12 @@ The following attributes are exported:
4848
* `id` - The OCID of the tag definition.
4949
* `is_cost_tracking` - Indicates whether the tag is enabled for cost tracking.
5050
* `is_retired` - Indicates whether the tag is retired. See [Retiring Key Definitions and Namespace Definitions](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/taggingoverview.htm#Retiring).
51-
* `name` - The name of the tag. The name must be unique across all tags in the tag namespace and can't be changed.
51+
* `name` - The name assigned to the tag during creation. This is the tag key definition. The name must be unique within the tag namespace and cannot be changed.
5252
* `state` - The tag's current state. After creating a tag, make sure its `lifecycleState` is ACTIVE before using it. After retiring a tag, make sure its `lifecycleState` is INACTIVE before using it. If you delete a tag, you cannot delete another tag until the deleted tag's `lifecycleState` changes from DELETING to DELETED.
5353
* `tag_namespace_id` - The OCID of the namespace that contains the tag definition.
5454
* `time_created` - Date and time the tag was created, in the format defined by RFC3339. Example: `2016-08-25T21:10:29.600Z`
55+
* `validator` - Additional validation rule for values specified for the tag definition.
56+
57+
* `validator_type` - The primitive that any value set for this definedTag must be parseable as.
58+
* `values` - The list of allowed values for a definedTag value.
5559

0 commit comments

Comments
 (0)