diff --git a/README.md b/README.md index 16b8e8e..a724b7c 100644 --- a/README.md +++ b/README.md @@ -23,20 +23,16 @@ users: - username: superadmin github_users: - github_user_1 - - github_user_2 - - github_user_3 github_teams: # Specify teams by Org name and team name, separated by a / - - MyOrg/Team Name 1 - - MyOrg/Team Name 2 + - MyOrg/Team 1 + - MyOrg/Team 2 - username: admin github_users: - - github_user_3 - - github_user_4 + - github_user_1 + - github_user_2 github_teams: - - MyOrg/Team Name 2 - - MyOtherOrg/Team Name 1 - - MyOtherOrg/Team Name 2 + - MyOtherOrg/Team 3 ``` ## Execute diff --git a/config.example.yml b/config.example.yml index 31546f5..f0e35bb 100644 --- a/config.example.yml +++ b/config.example.yml @@ -6,17 +6,13 @@ users: - username: superadmin github_users: - github_user_1 - - github_user_2 - - github_user_3 github_teams: # Specify teams by Org name and team name, separated by a / - - MyOrg/Team Name 1 - - MyOrg/Team Name 2 + - MyOrg/Team 1 + - MyOrg/Team 2 - username: admin github_users: - - github_user_3 - - github_user_4 + - github_user_1 + - github_user_2 github_teams: - - MyOrg/Team Name 2 - - MyOtherOrg/Team Name 1 - - MyOtherOrg/Team Name 2 + - MyOtherOrg/Team 3 diff --git a/github.go b/github.go index 7309fbb..544d00a 100644 --- a/github.go +++ b/github.go @@ -16,13 +16,11 @@ func (t *tokenSource) Token() (*oauth2.Token, error) { return t.token, nil } -// Github holds github token and client -type Github struct { - token string - client *github.Client +type githubClient struct { + *github.Client } -func newGithub(token string) Github { +func newGithubClient(token string) *githubClient { // TODO: https://github.com/sourcegraph/apiproxy client := github.NewClient(oauth2.NewClient(oauth2.NoContext, &tokenSource{ &oauth2.Token{ @@ -42,14 +40,14 @@ func newGithub(token string) Github { fmt.Println("") // END DEBUG. */ - return Github{client: client, token: token} + return &githubClient{client} } -func (g *Github) getTeamID(orgName string) (int, error) { +func (gc *githubClient) getTeamID(orgName string) (int, error) { orgNameArray := strings.Split(orgName, "/") org := orgNameArray[0] name := orgNameArray[1] - teams, _, err := g.client.Organizations.ListTeams(org, nil) + teams, _, err := gc.Organizations.ListTeams(org, nil) if err != nil { return 0, err } @@ -63,16 +61,16 @@ func (g *Github) getTeamID(orgName string) (int, error) { var githubTeamMembers = map[string][]string{} -func (g *Github) getMembersOfTeam(orgName string) ([]string, error) { +func (gc *githubClient) getMembersOfTeam(orgName string) ([]string, error) { members, ok := githubTeamMembers[orgName] if ok { return members, nil } - teamID, err := g.getTeamID(orgName) + teamID, err := gc.getTeamID(orgName) if err != nil { return members, err } - githubUsers, _, err := g.client.Organizations.ListTeamMembers(teamID, nil) + githubUsers, _, err := gc.Organizations.ListTeamMembers(teamID, nil) if err != nil { return members, err } @@ -85,12 +83,12 @@ func (g *Github) getMembersOfTeam(orgName string) ([]string, error) { var githubUserKeys = map[string][]string{} -func (g *Github) getKeysOfUser(user string) ([]string, error) { +func (gc *githubClient) getKeysOfUser(user string) ([]string, error) { keys, ok := githubUserKeys[user] if ok { return keys, nil } - githubKeys, _, err := g.client.Users.ListKeys(user, nil) + githubKeys, _, err := gc.Users.ListKeys(user, nil) if err != nil { return keys, err } @@ -110,13 +108,13 @@ func appendUserIfMissing(users []string, newUser string) []string { return append(users, newUser) } -func (g *Github) getKeys(users, teams []string) []string { +func (gc *githubClient) getKeys(users, teams []string) []string { var keys []string // add members of teams to array of users teamMembersChan := make(chan []string) for _, orgName := range teams { go func(orgName string) { - members, _ := g.getMembersOfTeam(orgName) + members, _ := gc.getMembersOfTeam(orgName) // TODO: handle error teamMembersChan <- members }(orgName) @@ -131,7 +129,7 @@ func (g *Github) getKeys(users, teams []string) []string { userKeysChan := make(chan []string) for _, user := range users { go func(user string) { - userKeys, _ := g.getKeysOfUser(user) + userKeys, _ := gc.getKeysOfUser(user) // TODO: handle error userKeysChan <- userKeys }(user) diff --git a/main.go b/main.go index 8e7d9fc..c70cbdc 100644 --- a/main.go +++ b/main.go @@ -49,7 +49,7 @@ func main() { // TODO: validate config, including that usernames exist on server. - github := newGithub(config.GithubToken) + gc := newGithubClient(config.GithubToken) usernameCount := 0 usernameKeysChan := make(chan usernameKeys) @@ -57,7 +57,7 @@ func main() { if singleUsername == "" || singleUsername == user.Username { usernameCount++ go func(username string, users, teams []string) { - keys := github.getKeys(users, teams) + keys := gc.getKeys(users, teams) usernameKeysChan <- usernameKeys{username: username, keys: keys} }(user.Username, user.GithubUsers, user.GithubTeams) } diff --git a/main_test.go b/main_test.go index 3cb25ef..7084530 100644 --- a/main_test.go +++ b/main_test.go @@ -1,41 +1,112 @@ package main import ( - "io/ioutil" - "os" + "fmt" + "net/http" + "net/http/httptest" + "net/url" "testing" "github.com/stretchr/testify/assert" ) +var ( + server *httptest.Server + client *githubClient +) + +func setup() { + server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + response := "Not Found" + switch r.URL.Path { + case "/orgs/MyOrg/teams": + response = `[{"id":1, "name":"Team 1"},{"id":2, "name":"Team 2"}]` + case "/orgs/MyOtherOrg/teams": + response = `[{"id":3, "name":"Team 3"}]` + case "/teams/1/members": + response = `[{"login":"github_user_1"},{"login":"github_user_2"}]` + case "/teams/2/members": + response = `[{"login":"github_user_3"}]` + case "/teams/3/members": + response = `[{"login":"github_user_4"}]` + case "/users/github_user_1/keys": + response = `[{"key":"github_user_1_key_1"},{"key":"github_user_1_key_2"}]` + case "/users/github_user_2/keys": + response = `[{"key":"github_user_2_key_1"}]` + case "/users/github_user_3/keys": + response = `[{"key":"github_user_3_key_1"}]` + case "/users/github_user_4/keys": + response = `[{"key":"github_user_4_key_1"}]` + } + fmt.Fprint(w, response) + })) + client = newGithubClient("token") + url, _ := url.Parse(server.URL) + client.BaseURL = url +} + +func teardown() { + server.Close() +} + func TestConfig(t *testing.T) { - configFile, _ := ioutil.TempFile("", "ghkeys") - defer os.RemoveAll(configFile.Name()) - - configContent := `--- -github_token: github_token_value -users: - - username: user_1 - github_users: - - github_user_1 - - github_user_2 - - username: user_2 - github_teams: - - MyOrg/Team 1 - - MyOrg/Team 2 -` - ioutil.WriteFile(configFile.Name(), []byte(configContent), os.ModePerm) - - testConfig, err := newConfig(configFile.Name()) + testConfig, err := newConfig("config.example.yml") + assert.Nil(t, err) - assert.Equal(t, "github_token_value", testConfig.GithubToken) + assert.Equal(t, "my_github_token", testConfig.GithubToken) assert.Len(t, testConfig.Users, 2) - assert.Equal(t, "user_1", testConfig.Users[0].Username) - assert.Len(t, testConfig.Users[0].GithubUsers, 2) + assert.Equal(t, "superadmin", testConfig.Users[0].Username) + assert.Len(t, testConfig.Users[0].GithubUsers, 1) assert.Equal(t, "github_user_1", testConfig.Users[0].GithubUsers[0]) - assert.Nil(t, testConfig.Users[0].GithubTeams) - assert.Nil(t, testConfig.Users[1].GithubUsers) - assert.Len(t, testConfig.Users[1].GithubTeams, 2) - assert.Equal(t, "MyOrg/Team 1", testConfig.Users[1].GithubTeams[0]) + assert.Len(t, testConfig.Users[0].GithubTeams, 2) + assert.Equal(t, "MyOrg/Team 1", testConfig.Users[0].GithubTeams[0]) +} + +func TestGetTeamID(t *testing.T) { + setup() + defer teardown() + + teamID, err := client.getTeamID("MyOrg/Team 2") + + assert.Nil(t, err) + assert.Equal(t, 2, teamID) +} + +func TestGetMembersOfTeam(t *testing.T) { + setup() + defer teardown() + + membersOfTeam, err := client.getMembersOfTeam("MyOrg/Team 2") + + assert.Nil(t, err) + assert.Len(t, membersOfTeam, 1) + assert.Equal(t, "github_user_3", membersOfTeam[0]) +} + +func TestGetKeysOfUser(t *testing.T) { + setup() + defer teardown() + + keysOfUser, err := client.getKeysOfUser("github_user_1") + + assert.Nil(t, err) + assert.Len(t, keysOfUser, 2) + assert.Equal(t, "github_user_1_key_2", keysOfUser[1]) +} + +func TestGetKeys(t *testing.T) { + setup() + defer teardown() + + users := []string{"github_user_1"} + teams := []string{"MyOrg/Team 1", "MyOrg/Team 2"} + expectedKeys := []string{"github_user_1_key_1", "github_user_1_key_2", "github_user_2_key_1", "github_user_3_key_1"} + + keys := client.getKeys(users, teams) + // TODO: Better way to do this? + assert.Len(t, keys, len(expectedKeys)) + for _, expectedKey := range expectedKeys { + assert.Contains(t, keys, expectedKey) + } }