terraform-provider-google/google/resource_google_project_iam_binding.go

184 lines
4.5 KiB
Go
Raw Normal View History

package google
import (
"fmt"
"log"
"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/cloudresourcemanager/v1"
)
func resourceGoogleProjectIamBinding() *schema.Resource {
return &schema.Resource{
Create: resourceGoogleProjectIamBindingCreate,
Read: resourceGoogleProjectIamBindingRead,
Update: resourceGoogleProjectIamBindingUpdate,
Delete: resourceGoogleProjectIamBindingDelete,
Schema: map[string]*schema.Schema{
"project": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"role": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"members": {
Type: schema.TypeSet,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"etag": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceGoogleProjectIamBindingCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
pid, err := getProject(d, config)
if err != nil {
return err
}
// Get the binding in the template
log.Println("[DEBUG]: Reading google_project_iam_binding")
p := getResourceIamBinding(d)
mutexKV.Lock(projectIamBindingMutexKey(pid, p.Role))
defer mutexKV.Unlock(projectIamBindingMutexKey(pid, p.Role))
err = projectIamPolicyReadModifyWrite(d, config, pid, func(ep *cloudresourcemanager.Policy) error {
// Merge the bindings together
ep.Bindings = mergeBindings(append(ep.Bindings, p))
return nil
})
if err != nil {
return err
}
d.SetId(pid + "/" + p.Role)
return resourceGoogleProjectIamBindingRead(d, meta)
}
func resourceGoogleProjectIamBindingRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
pid, err := getProject(d, config)
if err != nil {
return err
}
eBinding := getResourceIamBinding(d)
log.Println("[DEBUG]: Retrieving policy for project", pid)
p, err := getProjectIamPolicy(pid, config)
if err != nil {
return err
}
log.Printf("[DEBUG]: Retrieved policy for project %q: %+v\n", pid, p)
var binding *cloudresourcemanager.Binding
for _, b := range p.Bindings {
if b.Role != eBinding.Role {
continue
}
binding = b
break
}
if binding == nil {
log.Printf("[DEBUG]: Binding for role %q not found in policy for %q, removing from state file.\n", eBinding.Role, pid)
d.SetId("")
return nil
}
d.Set("etag", p.Etag)
d.Set("members", binding.Members)
d.Set("role", binding.Role)
return nil
}
func resourceGoogleProjectIamBindingUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
pid, err := getProject(d, config)
if err != nil {
return err
}
binding := getResourceIamBinding(d)
mutexKV.Lock(projectIamBindingMutexKey(pid, binding.Role))
defer mutexKV.Unlock(projectIamBindingMutexKey(pid, binding.Role))
err = projectIamPolicyReadModifyWrite(d, config, pid, func(p *cloudresourcemanager.Policy) error {
var found bool
for pos, b := range p.Bindings {
if b.Role != binding.Role {
continue
}
found = true
p.Bindings[pos] = binding
break
}
if !found {
p.Bindings = append(p.Bindings, binding)
}
return nil
})
if err != nil {
return err
}
return resourceGoogleProjectIamBindingRead(d, meta)
}
func resourceGoogleProjectIamBindingDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
pid, err := getProject(d, config)
if err != nil {
return err
}
binding := getResourceIamBinding(d)
mutexKV.Lock(projectIamBindingMutexKey(pid, binding.Role))
defer mutexKV.Unlock(projectIamBindingMutexKey(pid, binding.Role))
err = projectIamPolicyReadModifyWrite(d, config, pid, func(p *cloudresourcemanager.Policy) error {
toRemove := -1
for pos, b := range p.Bindings {
if b.Role != binding.Role {
continue
}
toRemove = pos
break
}
if toRemove < 0 {
log.Printf("[DEBUG]: Policy bindings for project %q did not include a binding for role %q", pid, binding.Role)
return nil
}
p.Bindings = append(p.Bindings[:toRemove], p.Bindings[toRemove+1:]...)
return nil
})
if err != nil {
return err
}
return resourceGoogleProjectIamBindingRead(d, meta)
}
// Get a cloudresourcemanager.Binding from a schema.ResourceData
func getResourceIamBinding(d *schema.ResourceData) *cloudresourcemanager.Binding {
members := d.Get("members").(*schema.Set).List()
return &cloudresourcemanager.Binding{
2017-07-25 18:52:38 +00:00
Members: convertStringArr(members),
Role: d.Get("role").(string),
}
}
func projectIamBindingMutexKey(pid, role string) string {
return fmt.Sprintf("google-project-iam-binding-%s-%s", pid, role)
}