terraform-provider-google/google/resource_google_organization_policy.go
The Magician f34848f974 Document that a policy must be defined. (#3611)
Signed-off-by: Modular Magician <magic-modules@google.com>
2019-05-16 13:10:44 -07:00

406 lines
11 KiB
Go

package google
import (
"fmt"
"strings"
"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/cloudresourcemanager/v1"
)
var schemaOrganizationPolicy = map[string]*schema.Schema{
"constraint": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: linkDiffSuppress,
},
"boolean_policy": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
ConflictsWith: []string{"list_policy", "restore_policy"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enforced": {
Type: schema.TypeBool,
Required: true,
},
},
},
},
"list_policy": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
ConflictsWith: []string{"boolean_policy", "restore_policy"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"allow": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
ConflictsWith: []string{"list_policy.0.deny"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"all": {
Type: schema.TypeBool,
Optional: true,
Default: false,
ConflictsWith: []string{"list_policy.0.allow.0.values"},
},
"values": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
},
},
},
"deny": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"all": {
Type: schema.TypeBool,
Optional: true,
Default: false,
ConflictsWith: []string{"list_policy.0.deny.0.values"},
},
"values": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
},
},
},
"suggested_value": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"inherit_from_parent": {
Type: schema.TypeBool,
Optional: true,
},
},
},
},
"version": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"etag": {
Type: schema.TypeString,
Computed: true,
},
"update_time": {
Type: schema.TypeString,
Computed: true,
},
"restore_policy": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
ConflictsWith: []string{"boolean_policy", "list_policy"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"default": {
Type: schema.TypeBool,
Required: true,
},
},
},
},
}
func resourceGoogleOrganizationPolicy() *schema.Resource {
return &schema.Resource{
Create: resourceGoogleOrganizationPolicyCreate,
Read: resourceGoogleOrganizationPolicyRead,
Update: resourceGoogleOrganizationPolicyUpdate,
Delete: resourceGoogleOrganizationPolicyDelete,
Importer: &schema.ResourceImporter{
State: resourceGoogleOrganizationPolicyImportState,
},
Schema: mergeSchemas(
schemaOrganizationPolicy,
map[string]*schema.Schema{
"org_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
}),
}
}
func resourceGoogleOrganizationPolicyCreate(d *schema.ResourceData, meta interface{}) error {
d.SetId(fmt.Sprintf("%s:%s", d.Get("org_id"), d.Get("constraint").(string)))
if isOrganizationPolicyUnset(d) {
return resourceGoogleOrganizationPolicyDelete(d, meta)
}
if err := setOrganizationPolicy(d, meta); err != nil {
return err
}
return resourceGoogleOrganizationPolicyRead(d, meta)
}
func resourceGoogleOrganizationPolicyRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
org := "organizations/" + d.Get("org_id").(string)
policy, err := config.clientResourceManager.Organizations.GetOrgPolicy(org, &cloudresourcemanager.GetOrgPolicyRequest{
Constraint: canonicalOrgPolicyConstraint(d.Get("constraint").(string)),
}).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Organization policy for %s", org))
}
d.Set("constraint", policy.Constraint)
d.Set("boolean_policy", flattenBooleanOrganizationPolicy(policy.BooleanPolicy))
d.Set("list_policy", flattenListOrganizationPolicy(policy.ListPolicy))
d.Set("version", policy.Version)
d.Set("etag", policy.Etag)
d.Set("update_time", policy.UpdateTime)
d.Set("restore_policy", flattenRestoreOrganizationPolicy(policy.RestoreDefault))
return nil
}
func resourceGoogleOrganizationPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
if isOrganizationPolicyUnset(d) {
return resourceGoogleOrganizationPolicyDelete(d, meta)
}
if err := setOrganizationPolicy(d, meta); err != nil {
return err
}
return resourceGoogleOrganizationPolicyRead(d, meta)
}
func resourceGoogleOrganizationPolicyDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
org := "organizations/" + d.Get("org_id").(string)
_, err := config.clientResourceManager.Organizations.ClearOrgPolicy(org, &cloudresourcemanager.ClearOrgPolicyRequest{
Constraint: canonicalOrgPolicyConstraint(d.Get("constraint").(string)),
}).Do()
if err != nil {
return err
}
return nil
}
func resourceGoogleOrganizationPolicyImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
parts := strings.Split(d.Id(), ":")
if len(parts) != 2 {
return nil, fmt.Errorf("Invalid id format. Expecting {org_id}:{constraint}, got '%s' instead.", d.Id())
}
d.Set("org_id", parts[0])
d.Set("constraint", parts[1])
return []*schema.ResourceData{d}, nil
}
// Organization policies can be "inherited from parent" the UI, and this is the default
// state of the resource without any policy set. In order to revert to this state the current
// resource cannot be updated it must instead be Deleted. This allows Terraform to assert that
// no policy has been set even if previously one had.
// See https://github.com/terraform-providers/terraform-provider-google/issues/3607
func isOrganizationPolicyUnset(d *schema.ResourceData) bool {
listPolicy := d.Get("list_policy").([]interface{})
booleanPolicy := d.Get("boolean_policy").([]interface{})
restorePolicy := d.Get("restore_policy").([]interface{})
return len(listPolicy)+len(booleanPolicy)+len(restorePolicy) == 0
}
func setOrganizationPolicy(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
org := "organizations/" + d.Get("org_id").(string)
listPolicy, err := expandListOrganizationPolicy(d.Get("list_policy").([]interface{}))
if err != nil {
return err
}
restoreDefault, err := expandRestoreOrganizationPolicy(d.Get("restore_policy").([]interface{}))
if err != nil {
return err
}
_, err = config.clientResourceManager.Organizations.SetOrgPolicy(org, &cloudresourcemanager.SetOrgPolicyRequest{
Policy: &cloudresourcemanager.OrgPolicy{
Constraint: canonicalOrgPolicyConstraint(d.Get("constraint").(string)),
BooleanPolicy: expandBooleanOrganizationPolicy(d.Get("boolean_policy").([]interface{})),
ListPolicy: listPolicy,
RestoreDefault: restoreDefault,
Version: int64(d.Get("version").(int)),
Etag: d.Get("etag").(string),
},
}).Do()
return err
}
func flattenBooleanOrganizationPolicy(policy *cloudresourcemanager.BooleanPolicy) []map[string]interface{} {
bPolicies := make([]map[string]interface{}, 0, 1)
if policy == nil {
return bPolicies
}
bPolicies = append(bPolicies, map[string]interface{}{
"enforced": policy.Enforced,
})
return bPolicies
}
func flattenRestoreOrganizationPolicy(restore_policy *cloudresourcemanager.RestoreDefault) []map[string]interface{} {
rp := make([]map[string]interface{}, 0, 1)
if restore_policy == nil {
return rp
}
rp = append(rp, map[string]interface{}{
"default": true,
})
return rp
}
func expandBooleanOrganizationPolicy(configured []interface{}) *cloudresourcemanager.BooleanPolicy {
if len(configured) == 0 || configured[0] == nil {
return nil
}
booleanPolicy := configured[0].(map[string]interface{})
return &cloudresourcemanager.BooleanPolicy{
Enforced: booleanPolicy["enforced"].(bool),
}
}
func expandRestoreOrganizationPolicy(configured []interface{}) (*cloudresourcemanager.RestoreDefault, error) {
if len(configured) == 0 || configured[0] == nil {
return nil, nil
}
restoreDefaultMap := configured[0].(map[string]interface{})
default_value := restoreDefaultMap["default"].(bool)
if default_value {
return &cloudresourcemanager.RestoreDefault{}, nil
}
return nil, fmt.Errorf("Invalid value for restore_policy. Expecting default = true")
}
func flattenListOrganizationPolicy(policy *cloudresourcemanager.ListPolicy) []map[string]interface{} {
lPolicies := make([]map[string]interface{}, 0, 1)
if policy == nil {
return lPolicies
}
listPolicy := map[string]interface{}{
"suggested_value": policy.SuggestedValue,
"inherit_from_parent": policy.InheritFromParent,
}
switch {
case policy.AllValues == "ALLOW":
listPolicy["allow"] = []interface{}{map[string]interface{}{
"all": true,
}}
case policy.AllValues == "DENY":
listPolicy["deny"] = []interface{}{map[string]interface{}{
"all": true,
}}
case len(policy.AllowedValues) > 0:
listPolicy["allow"] = []interface{}{map[string]interface{}{
"values": schema.NewSet(schema.HashString, convertStringArrToInterface(policy.AllowedValues)),
}}
case len(policy.DeniedValues) > 0:
listPolicy["deny"] = []interface{}{map[string]interface{}{
"values": schema.NewSet(schema.HashString, convertStringArrToInterface(policy.DeniedValues)),
}}
}
lPolicies = append(lPolicies, listPolicy)
return lPolicies
}
func expandListOrganizationPolicy(configured []interface{}) (*cloudresourcemanager.ListPolicy, error) {
if len(configured) == 0 || configured[0] == nil {
return nil, nil
}
listPolicyMap := configured[0].(map[string]interface{})
allow := listPolicyMap["allow"].([]interface{})
deny := listPolicyMap["deny"].([]interface{})
var allValues string
var allowedValues []string
var deniedValues []string
if len(allow) > 0 {
allowMap := allow[0].(map[string]interface{})
all := allowMap["all"].(bool)
values := allowMap["values"].(*schema.Set)
if all {
allValues = "ALLOW"
} else {
allowedValues = convertStringArr(values.List())
}
}
if len(deny) > 0 {
denyMap := deny[0].(map[string]interface{})
all := denyMap["all"].(bool)
values := denyMap["values"].(*schema.Set)
if all {
allValues = "DENY"
} else {
deniedValues = convertStringArr(values.List())
}
}
listPolicy := configured[0].(map[string]interface{})
return &cloudresourcemanager.ListPolicy{
AllValues: allValues,
AllowedValues: allowedValues,
DeniedValues: deniedValues,
SuggestedValue: listPolicy["suggested_value"].(string),
InheritFromParent: listPolicy["inherit_from_parent"].(bool),
ForceSendFields: []string{"InheritFromParent"},
}, nil
}
func canonicalOrgPolicyConstraint(constraint string) string {
if strings.HasPrefix(constraint, "constraints/") {
return constraint
}
return "constraints/" + constraint
}