github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/builtin/providers/github/resource_github_repository_collaborator.go (about)

     1  package github
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/google/go-github/github"
     7  	"github.com/hashicorp/terraform/helper/schema"
     8  )
     9  
    10  func resourceGithubRepositoryCollaborator() *schema.Resource {
    11  	return &schema.Resource{
    12  		Create: resourceGithubRepositoryCollaboratorCreate,
    13  		Read:   resourceGithubRepositoryCollaboratorRead,
    14  		// editing repository collaborators are not supported by github api so forcing new on any changes
    15  		Delete: resourceGithubRepositoryCollaboratorDelete,
    16  		Importer: &schema.ResourceImporter{
    17  			State: schema.ImportStatePassthrough,
    18  		},
    19  
    20  		Schema: map[string]*schema.Schema{
    21  			"username": {
    22  				Type:     schema.TypeString,
    23  				Required: true,
    24  				ForceNew: true,
    25  			},
    26  			"repository": {
    27  				Type:     schema.TypeString,
    28  				Required: true,
    29  				ForceNew: true,
    30  			},
    31  			"permission": {
    32  				Type:         schema.TypeString,
    33  				Optional:     true,
    34  				ForceNew:     true,
    35  				Default:      "push",
    36  				ValidateFunc: validateValueFunc([]string{"pull", "push", "admin"}),
    37  			},
    38  		},
    39  	}
    40  }
    41  
    42  func resourceGithubRepositoryCollaboratorCreate(d *schema.ResourceData, meta interface{}) error {
    43  	client := meta.(*Organization).client
    44  	u := d.Get("username").(string)
    45  	r := d.Get("repository").(string)
    46  	p := d.Get("permission").(string)
    47  
    48  	_, err := client.Repositories.AddCollaborator(context.TODO(), meta.(*Organization).name, r, u,
    49  		&github.RepositoryAddCollaboratorOptions{Permission: p})
    50  
    51  	if err != nil {
    52  		return err
    53  	}
    54  
    55  	d.SetId(buildTwoPartID(&r, &u))
    56  
    57  	return resourceGithubRepositoryCollaboratorRead(d, meta)
    58  }
    59  
    60  func resourceGithubRepositoryCollaboratorRead(d *schema.ResourceData, meta interface{}) error {
    61  	client := meta.(*Organization).client
    62  	r, u := parseTwoPartID(d.Id())
    63  
    64  	// First, check if the user has been invited but has not yet accepted
    65  	invitation, err := findRepoInvitation(client, meta.(*Organization).name, r, u)
    66  	if err != nil {
    67  		return err
    68  	} else if invitation != nil {
    69  		permName, err := getInvitationPermission(invitation)
    70  		if err != nil {
    71  			return err
    72  		}
    73  
    74  		d.Set("repository", r)
    75  		d.Set("username", u)
    76  		d.Set("permission", permName)
    77  		return nil
    78  	}
    79  
    80  	// Next, check if the user has accepted the invite and is a full collaborator
    81  	opt := &github.ListOptions{PerPage: maxPerPage}
    82  	for {
    83  		collaborators, resp, err := client.Repositories.ListCollaborators(context.TODO(), meta.(*Organization).name, r, opt)
    84  		if err != nil {
    85  			return err
    86  		}
    87  
    88  		for _, c := range collaborators {
    89  			if *c.Login == u {
    90  				permName, err := getRepoPermission(c.Permissions)
    91  				if err != nil {
    92  					return err
    93  				}
    94  
    95  				d.Set("repository", r)
    96  				d.Set("username", u)
    97  				d.Set("permission", permName)
    98  				return nil
    99  			}
   100  		}
   101  
   102  		if resp.NextPage == 0 {
   103  			break
   104  		}
   105  		opt.Page = resp.NextPage
   106  	}
   107  
   108  	// The user is neither invited nor a collaborator
   109  	d.SetId("")
   110  	return nil
   111  }
   112  
   113  func resourceGithubRepositoryCollaboratorDelete(d *schema.ResourceData, meta interface{}) error {
   114  	client := meta.(*Organization).client
   115  	u := d.Get("username").(string)
   116  	r := d.Get("repository").(string)
   117  
   118  	// Delete any pending invitations
   119  	invitation, err := findRepoInvitation(client, meta.(*Organization).name, r, u)
   120  	if err != nil {
   121  		return err
   122  	} else if invitation != nil {
   123  		_, err = client.Repositories.DeleteInvitation(context.TODO(), meta.(*Organization).name, r, *invitation.ID)
   124  		return err
   125  	}
   126  
   127  	_, err = client.Repositories.RemoveCollaborator(context.TODO(), meta.(*Organization).name, r, u)
   128  	return err
   129  }
   130  
   131  func findRepoInvitation(client *github.Client, owner string, repo string, collaborator string) (*github.RepositoryInvitation, error) {
   132  	opt := &github.ListOptions{PerPage: maxPerPage}
   133  	for {
   134  		invitations, resp, err := client.Repositories.ListInvitations(context.TODO(), owner, repo, opt)
   135  		if err != nil {
   136  			return nil, err
   137  		}
   138  
   139  		for _, i := range invitations {
   140  			if *i.Invitee.Login == collaborator {
   141  				return i, nil
   142  			}
   143  		}
   144  
   145  		if resp.NextPage == 0 {
   146  			break
   147  		}
   148  		opt.Page = resp.NextPage
   149  	}
   150  	return nil, nil
   151  }