From 801288b5e73e758f404b6af1ceb584e91a6380f5 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Sat, 28 Mar 2020 10:33:42 +0100 Subject: [PATCH 01/14] Add changes from dahendel & co --- awx.go | 6 + credentials.go | 103 +++++++++++++ credentials_test.go | 283 ++++++++++++++++++++++++++++++++++ examples/credentials.md | 97 ++++++++++++ examples/organizations.md | 133 ++++++++++++++++ examples/teams.md | 136 +++++++++++++++++ groups.go | 25 +++ job.go | 28 ++++ job_template.go | 104 ++++++++++++- organizations.go | 103 +++++++++++++ organizations_test.go | 48 ++++++ teams.go | 152 +++++++++++++++++++ teams_test.go | 312 ++++++++++++++++++++++++++++++++++++++ types.go | 164 +++++++++++++++++++- users.go | 48 ++++++ 15 files changed, 1729 insertions(+), 13 deletions(-) create mode 100644 credentials.go create mode 100644 credentials_test.go create mode 100644 examples/credentials.md create mode 100644 examples/organizations.md create mode 100644 examples/teams.md create mode 100644 organizations.go create mode 100644 organizations_test.go create mode 100644 teams.go create mode 100644 teams_test.go diff --git a/awx.go b/awx.go index c43b64e..8b11db5 100644 --- a/awx.go +++ b/awx.go @@ -25,6 +25,8 @@ type AWX struct { UserService *UserService GroupService *GroupService HostService *HostService + OrganizationService *OrganizationService + TeamService *TeamService } // Client implement http client. @@ -106,5 +108,9 @@ func NewAWX(baseURL, userName, passwd string, client *http.Client) *AWX { HostService: &HostService{ client: awxClient, }, + OrganizationService: &OrganizationService{ + client: awxClient, + }, + TeamService: &TeamService{client: awxClient}, } } diff --git a/credentials.go b/credentials.go new file mode 100644 index 0000000..f1fe428 --- /dev/null +++ b/credentials.go @@ -0,0 +1,103 @@ +package awx + +import ( + "bytes" + "encoding/json" + "fmt" +) + +// CredentialService implements awx Credentials apis. +type CredentialService struct { + client *Client +} + +// ListCredentialsResponse represents `ListCredentials` endpoint response. +type ListCredentialsResponse struct { + Pagination + Results []*Credential `json:"results"` +} + +// ListCredentials shows list of awx Credentials. +func (t *CredentialService) ListCredentials(params map[string]string) ([]*Credential, *ListCredentialsResponse, error) { + result := new(ListCredentialsResponse) + endpoint := "/api/v2/credentials/" + resp, err := t.client.Requester.GetJSON(endpoint, result, params) + if err != nil { + return nil, result, err + } + + if err := CheckResponse(resp); err != nil { + return nil, result, err + } + + return result.Results, result, nil +} + +// CreateCredential creates an awx Credential. +func (t *CredentialService) CreateCredential(data map[string]interface{}, params map[string]string) (*Credential, error) { + mandatoryFields = []string{"name", "credential_type"} + validate, status := ValidateParams(data, mandatoryFields) + + if !status { + err := fmt.Errorf("Mandatory input arguments are absent: %s", validate) + return nil, err + } + + result := new(Credential) + endpoint := "/api/v2/credentials/" + payload, err := json.Marshal(data) + if err != nil { + return nil, err + } + + // Add check if Credential exists and return proper error + + resp, err := t.client.Requester.PostJSON(endpoint, bytes.NewReader(payload), result, params) + if err != nil { + return nil, err + } + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return result, nil +} + +// UpdateCredential update an awx user. +func (t *CredentialService) UpdateCredential(id int, data map[string]interface{}, params map[string]string) (*Credential, error) { + result := new(Credential) + endpoint := fmt.Sprintf("/api/v2/credentials/%d", id) + payload, err := json.Marshal(data) + if err != nil { + return nil, err + } + + resp, err := t.client.Requester.PutJSON(endpoint, bytes.NewReader(payload), result, nil) + if err != nil { + return nil, err + } + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return result, nil +} + +// DeleteCredential delete an awx Credential. +func (t *CredentialService) DeleteCredential(id int) (*Credential, error) { + result := new(Credential) + endpoint := fmt.Sprintf("/api/v2/credentials/%d", id) + + resp, err := t.client.Requester.Delete(endpoint, result, nil) + if err != nil { + return nil, err + } + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return result, nil +} diff --git a/credentials_test.go b/credentials_test.go new file mode 100644 index 0000000..7543297 --- /dev/null +++ b/credentials_test.go @@ -0,0 +1,283 @@ +package awx + +// +//import ( +// "testing" +// "time" +//) +// +//func TestListCredentials(t *testing.T) { +// var ( +// expectListCredentialsResponse = []*Credential{ +// { +// ID: 1, +// Type: "credential", +// URL: "/api/v2/credentials/1/", +// Related: &Related{ +// ObjectRoles: "/api/v2/credentials/1/object_roles/", +// AccessList: "/api/v2/credentials/1/access_list/", +// CredentialType: "/api/v2/credential_types/1/", +// ModifiedBy: "/api/v2/users/4/", +// OwnerUsers: "/api/v2/credentials/1/owner_users/", +// OwnerTeams: "/api/v2/credentials/1/owner_teams/", +// Organization: "/api/v2/organizations/1/", +// Copy: "/api/v2/credentials/1/copy/", +// ActivityStream: "/api/v2/credentials/1/activity_stream/", +// }, +// SummaryFields: &Summary{ +// Organization: &OrgnizationSummary{ +// ID: 1, +// Name: "Default", +// Description: "", +// }, +// Project: &Project{}, +// ModifiedBy: &ByUserSummary{ +// ID: 4, +// Username: "admin", +// FirstName: "", +// LastName: "", +// }, +// ObjectRoles: &ObjectRoles{ +// AdminRole: &ApplyRole{ +// ID: 18, +// Description: "Can manage all aspects of the credential", +// Name: "Admin", +// }, +// UseRole: &ApplyRole{ +// ID: 20, +// Description: "Can use the credential in a job template", +// Name: "Use", +// }, +// ReadRole: &ApplyRole{ +// ID: 19, +// Description: "May view settings for the credential", +// Name: "Read", +// }, +// }, +// UserCapabilities: &UserCapabilities{ +// Edit: true, +// Delete: true, +// Copy: true, +// }, +// }, +// Created: func() time.Time { +// t, _ := time.Parse(time.RFC3339, "2018-12-01T12:10:00.496424Z") +// return t +// }(), +// Modified: func() time.Time { +// t, _ := time.Parse(time.RFC3339, "2018-12-07T16:17:48.131210Z") +// return t +// }(), +// Name: "Demo Credential", +// Description: "", +// Organization: 1, +// CredentialType: 1, +// Inputs: map[string]interface{}{ +// "username": "admin", +// }, +// }, +// } +// ) +// +// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) +// result, _, err := awx.CredentialService.ListCredentials(map[string]string{ +// "name": "Default", +// }) +// +// if err != nil { +// t.Fatalf("ListCredentials err: %s", err) +// } else { +// checkAPICallResult(t, expectListCredentialsResponse, result) +// t.Log("ListCredentials passed!") +// } +//} +// +//func TestCreateCredentials(t *testing.T) { +// var ( +// expectCreateCredentialsResponse = &Credential{ +// ID: 1, +// Type: "credential", +// URL: "/api/v2/credentials/1/", +// Related: &Related{ +// ObjectRoles: "/api/v2/credentials/1/object_roles/", +// AccessList: "/api/v2/credentials/1/access_list/", +// CredentialType: "/api/v2/credential_types/1/", +// ModifiedBy: "/api/v2/users/4/", +// OwnerUsers: "/api/v2/credentials/1/owner_users/", +// OwnerTeams: "/api/v2/credentials/1/owner_teams/", +// Organization: "/api/v2/organizations/1/", +// Copy: "/api/v2/credentials/1/copy/", +// ActivityStream: "/api/v2/credentials/1/activity_stream/", +// }, +// SummaryFields: &Summary{ +// Organization: &OrgnizationSummary{ +// ID: 1, +// Name: "Default", +// Description: "", +// }, +// Project: &Project{}, +// ModifiedBy: &ByUserSummary{ +// ID: 4, +// Username: "admin", +// FirstName: "", +// LastName: "", +// }, +// ObjectRoles: &ObjectRoles{ +// AdminRole: &ApplyRole{ +// ID: 18, +// Description: "Can manage all aspects of the credential", +// Name: "Admin", +// }, +// UseRole: &ApplyRole{ +// ID: 20, +// Description: "Can use the credential in a job template", +// Name: "Use", +// }, +// ReadRole: &ApplyRole{ +// ID: 19, +// Description: "May view settings for the credential", +// Name: "Read", +// }, +// }, +// UserCapabilities: &UserCapabilities{ +// Edit: true, +// Delete: true, +// Copy: true, +// }, +// }, +// Created: func() time.Time { +// t, _ := time.Parse(time.RFC3339, "2018-12-01T12:10:00.496424Z") +// return t +// }(), +// Modified: func() time.Time { +// t, _ := time.Parse(time.RFC3339, "2018-12-07T16:17:48.131210Z") +// return t +// }(), +// Name: "Demo Credential", +// Description: "", +// Organization: 1, +// CredentialType: 1, +// Inputs: map[string]interface{}{ +// "username": "admin", +// }, +// } +// ) +// +// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) +// result, err := awx.CredentialService.CreateCredential(map[string]interface{}{ +// "name": "Demo Credential", +// "organization": 1, +// "credential_type": 1, +// }, map[string]string{}) +// if err != nil { +// t.Fatalf("CreateCredentials err: %s", err) +// } else { +// checkAPICallResult(t, expectCreateCredentialsResponse, result) +// t.Log("CreateCredentials passed!") +// } +//} +// +//func TestUpdateCredentials(t *testing.T) { +// var ( +// expectUpdateCredentialsResponse = &Credential{ +// ID: 1, +// Type: "credential", +// URL: "/api/v2/credentials/1/", +// Related: &Related{ +// ObjectRoles: "/api/v2/credentials/1/object_roles/", +// AccessList: "/api/v2/credentials/1/access_list/", +// CredentialType: "/api/v2/credential_types/1/", +// ModifiedBy: "/api/v2/users/4/", +// OwnerUsers: "/api/v2/credentials/1/owner_users/", +// OwnerTeams: "/api/v2/credentials/1/owner_teams/", +// Organization: "/api/v2/organizations/1/", +// Copy: "/api/v2/credentials/1/copy/", +// ActivityStream: "/api/v2/credentials/1/activity_stream/", +// }, +// SummaryFields: &Summary{ +// Organization: &OrgnizationSummary{ +// ID: 1, +// Name: "Default", +// Description: "", +// }, +// Project: &Project{}, +// ModifiedBy: &ByUserSummary{ +// ID: 4, +// Username: "admin", +// FirstName: "", +// LastName: "", +// }, +// ObjectRoles: &ObjectRoles{ +// AdminRole: &ApplyRole{ +// ID: 18, +// Description: "Can manage all aspects of the credential", +// Name: "Admin", +// }, +// UseRole: &ApplyRole{ +// ID: 20, +// Description: "Can use the credential in a job template", +// Name: "Use", +// }, +// ReadRole: &ApplyRole{ +// ID: 19, +// Description: "May view settings for the credential", +// Name: "Read", +// }, +// }, +// UserCapabilities: &UserCapabilities{ +// Edit: true, +// Delete: true, +// Copy: true, +// }, +// }, +// Created: func() time.Time { +// t, _ := time.Parse(time.RFC3339, "2018-12-01T12:10:00.496424Z") +// return t +// }(), +// Modified: func() time.Time { +// t, _ := time.Parse(time.RFC3339, "2018-12-07T16:17:48.131210Z") +// return t +// }(), +// Name: "Demo Credential", +// Description: "Demo Credential", +// Organization: 1, +// CredentialType: 1, +// Inputs: map[string]interface{}{ +// "username": "admin", +// }, +// } +// ) +// +// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) +// result, err := awx.CredentialService.UpdateCredential(1, map[string]interface{}{ +// "name": "Demo Credential", +// "description": "Demo credential", +// "organization": 1, +// "credential_type": 1, +// "inputs": map[string]interface{}{ +// "username": "admin", +// }, +// }, map[string]string{}) +// if err != nil { +// t.Fatalf("CreateCredentials err: %s", err) +// } else { +// checkAPICallResult(t, expectUpdateCredentialsResponse, result) +// t.Log("CreateCredentials passed!") +// } +//} +// +//func TestDeleteCredentials(t *testing.T) { +// var ( +// expectDeleteCredentialsResponse = &Credential{} +// ) +// +// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) +// result, err := awx.CredentialService.DeleteCredential(1) +// +// if err != nil { +// t.Fatalf("DeleteCredentials err: %s", err) +// } else { +// checkAPICallResult(t, expectDeleteCredentialsResponse, result) +// t.Log("DeleteCredentials passed!") +// } +//} diff --git a/examples/credentials.md b/examples/credentials.md new file mode 100644 index 0000000..e3da280 --- /dev/null +++ b/examples/credentials.md @@ -0,0 +1,97 @@ +# Credentiales API + +## Usage + +> List Credentiales + +```go +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + result, _, err := awx.CredentialService.ListCredentiales(map[string]string{ + "name": "Demo Credential", + }) + if err != nil { + log.Fatalf("List Credentiales err: %s", err) + } + + log.Println("List Credentiales: ", result) +} +``` + +> Create Credential + +```go +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +fun main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + result, err := awx.CredentialService.CreateCredential(map[string]interface{}{ + "name": "Demo Credential", + "organization": 1, + "credential_type": 1, + }, map[string]string{}) + + if err != nil { + log.Fatalf("Create Credentiales err: %s", err) + } + + log.Printf("Credential created. Credential ID: %d", result.Credential.ID") +} +``` + +> Update Credential + +```go +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +fun main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + result, err := awx.CredentialService.UpdateCredential(1, map[string]interface{}{ + "name": "Demo Credential", + "description": "Demo credential", + "organization": 1, + "credential_type": 1, + "inputs": map[string]interface{}{ + "username": "admin", + }, + }, nil) + + if err != nil { + log.Fatalf("Update Credentiales err: %s", err) + } + + log.Printf("Update result %v", result.Name) + +} +``` + +> Delete Credential + +```go +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + result, err := awx.CredentialService.DeleteCredential(5) + if err != nil { + log.Fatalf("Delete Credentiales err: %s", err) + } + + log.Println("Credential 5 Deleted") + +} +``` \ No newline at end of file diff --git a/examples/organizations.md b/examples/organizations.md new file mode 100644 index 0000000..3791f9c --- /dev/null +++ b/examples/organizations.md @@ -0,0 +1,133 @@ +# Organizations API + +## Usage + +> List Organizations + +```go +package main +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + result, _, err := awx.OrganizationService.ListOrganizations(map[string]string{ + "name": "test-organization", + }) + if err != nil { + log.Fatalf("List Organizations err: %s", err) + } + + log.Println("List Organization: ", result) +} +``` + +> Create Organization + +```go +package main +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + result, err := awx.OrganizationService.CreateOrganization(map[string]interface{}{ + "name": "test-organization", + "description": "test organization", + }, map[string]string{}) + if err != nil { + log.Fatalf("Create Organization err: %s", err) + } + + log.Printf("Organization created") +} +``` + +> Update Organization + +```go +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + result, err := awx.OrganizationService.UpdateOrganization(4, map[string]interface{}{ + "description": "Update test-organization", + }, map[string]string{}) + + if err != nil { + log.Fatalf("Update Organization err: %s", err) + } + + log.Printf("Update finised.") +} +``` + +> Delete Organization + +```go +package main +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + result, err := awx.OrganizationService.DeleteOrganization(1) + + if err != nil { + log.Fatalf("Delete Organization err: %s", err) + } + + log.Printf("Organization Deleted") +} +``` + +> Grant Organization Role + +```go +package main +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + err := awx.OrganizationService.GrantRole(1, 170) + + if err != nil { + log.Fatalf("Grant user role err: %s", err) + } + + log.Printf("User role granted") +} +``` + +> Revoke User Role + +```go +package main +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + err := awx.OrganizationService.GrantRole(1, 170) + + if err != nil { + log.Fatalf("Revoke user role err: %s", err) + } + + log.Printf("User role revoked") +} +``` diff --git a/examples/teams.md b/examples/teams.md new file mode 100644 index 0000000..058988c --- /dev/null +++ b/examples/teams.md @@ -0,0 +1,136 @@ +# Teams API + +## Usage + +> List Teams + +```go +package main +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + result, _, err := awx.TeamService.ListTeams(map[string]string{ + "name": "test-team", + }) + if err != nil { + log.Fatalf("List Teams err: %s", err) + } + + log.Println("List Team: ", result) +} +``` + +> Create Team + +```go +package main +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + result, err := awx.TeamService.CreateTeam(map[string]interface{}{ + "name": "test-team", + "organization": 1, + }, map[string]string{}) + if err != nil { + log.Fatalf("Create Team err: %s", err) + } + + log.Printf("Team created") +} +``` + +> Update Team + +```go +package main +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + result, err := awx.TeamService.UpdateTeam(4, map[string]interface{}{ + "name": "test-team", + "organization": 1, + "description": "Update test-team", + }, map[string]string{}) + + if err != nil { + log.Fatalf("Update Team err: %s", err) + } + + log.Printf("Update finised.") +} +``` + +> Delete Team + +```go +package main +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + result, err := awx.TeamService.DeleteTeam(1) + + if err != nil { + log.Fatalf("Delete Team err: %s", err) + } + + log.Printf("Team Deleted") +} +``` + +> Grant Team Role + +```go +package main +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + err := awx.TeamService.GrantRole(1, 170) + + if err != nil { + log.Fatalf("Grant user role err: %s", err) + } + + log.Printf("User role granted") +} +``` + +> Revoke User Role + +```go +package main +import ( + "log" + awxGo "github.com/Colstuwjx/awx-go" +) + +func main() { + awx := awxGo.NewAWX("http://awx.your_server_host.com", "your_awx_username", "your_awx_passwd", nil) + err := awx.TeamService.GrantRole(1, 170) + + if err != nil { + log.Fatalf("Revoke user role err: %s", err) + } + + log.Printf("User role revoked") +} +``` diff --git a/groups.go b/groups.go index b337846..6501d2b 100644 --- a/groups.go +++ b/groups.go @@ -100,3 +100,28 @@ func (g *GroupService) DeleteGroup(id int) (*Group, error) { return result, nil } + +func (g *GroupService) AddChildGroup(groupID, childID int) (*Group, error) { + result := new(Group) + endpoint := fmt.Sprintf("/api/v2/groups/%d/children/", groupID) + payload := map[string]int{ + "id": childID, + } + + jsonPayload, err := json.Marshal(payload) + + if err != nil { + return nil, err + } + + resp, err := g.client.Requester.PostJSON(endpoint, bytes.NewReader(jsonPayload), result, nil) + if err != nil { + return nil, err + } + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return result, nil +} diff --git a/job.go b/job.go index c53b1d5..f6ee4ad 100644 --- a/job.go +++ b/job.go @@ -23,6 +23,15 @@ type JobService struct { client *Client } +type JobStdoutResponse struct { + Range struct { + Start int `json:"start"` + End int `json:"end"` + AbsoluteEnd int `json:"absolute_end"` + } `json:"range"` + Content string `json:"content"` +} + // HostSummariesResponse represents `JobHostSummaries` endpoint response. type HostSummariesResponse struct { Pagination @@ -129,3 +138,22 @@ func (j *JobService) GetJobEvents(id int, params map[string]string) ([]JobEvent, return result.Results, result, nil } + +func (j *JobService) GetJobStdOut(id int) (*JobStdoutResponse, error) { + result := new(JobStdoutResponse) + endpoint := fmt.Sprintf("/api/v2/jobs/%d/stdout/", id) + + resp, err := j.client.Requester.GetJSON(endpoint, result, map[string]string{ + "format": "json", + }) + + if err != nil { + return result, err + } + + if err := CheckResponse(resp); err != nil { + return result, err + } + + return result, nil +} diff --git a/job_template.go b/job_template.go index 4f62133..4da58f3 100644 --- a/job_template.go +++ b/job_template.go @@ -5,6 +5,8 @@ import ( "encoding/json" "errors" "fmt" + "github.com/twinj/uuid" + "strconv" ) // JobTemplateService implements awx job template apis. @@ -34,8 +36,8 @@ func (jt *JobTemplateService) ListJobTemplates(params map[string]string) ([]*Job return result.Results, result, nil } -// Launch lauchs a job with the job template. -func (jt *JobTemplateService) Launch(id int, data map[string]interface{}, params map[string]string) (*JobLaunch, error) { +// Launch launches a job with the job template. +func (jt *JobTemplateService) Launch(id int, data *JobLaunchOpts, params map[string]string) (*JobLaunch, error) { result := new(JobLaunch) endpoint := fmt.Sprintf("/api/v2/job_templates/%d/launch/", id) payload, err := json.Marshal(data) @@ -52,18 +54,42 @@ func (jt *JobTemplateService) Launch(id int, data map[string]interface{}, params return nil, err } - // in case invalid job id return - if result.Job == 0 { - return nil, errors.New("invalid job id 0") + return result, nil +} + +// CreateJobTemplateCallBack executes a PATCH HTTP Request to create the callback url and the generated host_config_key +func (jt *JobTemplateService) CreateJobTemplateCallBack(template *JobTemplate) (*JobTemplate, error) { + if template.ID == 0 { + return nil, fmt.Errorf("Job template ID must be passed") } - return result, nil + endpoint := "/api/v2/job_templates/" + strconv.Itoa(template.ID) + template.AllowCallbacks = true + template.HostConfigKey = uuid.NewV4().String() + + jsonPayload, err := json.Marshal(template) + + if err != nil { + return nil, err + } + + resp, err := jt.client.Requester.PatchJSON(endpoint, bytes.NewReader(jsonPayload), template, map[string]string{}) + + if err != nil { + return nil, err + } + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return template, nil } // CreateJobTemplate creates a job template func (jt *JobTemplateService) CreateJobTemplate(data map[string]interface{}, params map[string]string) (*JobTemplate, error) { result := new(JobTemplate) - mandatoryFields = []string{"name", "job_type", "inventory", "project"} + mandatoryFields = []string{"name", "job_type", "inventory", "project", "playbook"} validate, status := ValidateParams(data, mandatoryFields) if !status { err := fmt.Errorf("Mandatory input arguments are absent: %s", validate) @@ -82,6 +108,11 @@ func (jt *JobTemplateService) CreateJobTemplate(data map[string]interface{}, par if err := CheckResponse(resp); err != nil { return nil, err } + + if result.AllowCallbacks { + return jt.CreateJobTemplateCallBack(result) + } + return result, nil } @@ -120,3 +151,62 @@ func (jt *JobTemplateService) DeleteJobTemplate(id int) (*JobTemplate, error) { return result, nil } + +// GetJobTemplate gets a job template +func (jt *JobTemplateService) GetJobTemplate(id int) (*JobTemplate, error) { + result := new(JobTemplate) + endpoint := fmt.Sprintf("/api/v2/job_templates/%d", id) + + resp, err := jt.client.Requester.Get(endpoint, result, map[string]string{}) + if err != nil { + return nil, err + }https://github.com/Colstuwjx/awx-go.git + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return result, nil +} + +func (jt *JobTemplateService) AddJobTemplateCredential(jobTemplateID int, credID int) (*JobTemplate, error) { + result := new(JobTemplate) + endpoint := fmt.Sprintf("/api/v2/job_templates/%d/credentials/", jobTemplateID) + + payload := map[string]int{ + "id": credID, + } + + jsonPayload, err := json.Marshal(payload) + + if err != nil { + return nil, err + } + + resp, err := jt.client.Requester.PostJSON(endpoint, bytes.NewReader(jsonPayload), result, map[string]string{}) + if err != nil { + return nil, err + } + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return result, nil +} + +func (jt *JobTemplateService) GetSurveySpec(jobTemplate *JobTemplate) ([]byte, error) { + endpoint := jobTemplate.Related.SurveySpec + spec := make(map[string]interface{}) + resp, err := jt.client.Requester.Get(endpoint, spec, map[string]string{}) + + if err != nil { + return nil, err + } + + if err = CheckResponse(resp); err != nil { + return nil, err + } + + return json.Marshal(spec) +} diff --git a/organizations.go b/organizations.go new file mode 100644 index 0000000..fe4d5ef --- /dev/null +++ b/organizations.go @@ -0,0 +1,103 @@ +package awx + +import ( + "bytes" + "encoding/json" + "fmt" +) + +// OrganizationService implements awx Organizations apis. +type OrganizationService struct { + client *Client +} + +// ListOrganizationsResponse represents `ListOrganizations` endpoint response. +type ListOrganizationsResponse struct { + Pagination + Results []*Organization `json:"results"` +} + +// ListOrganizations shows list of awx Organizations. +func (t *OrganizationService) ListOrganizations(params map[string]string) ([]*Organization, *ListOrganizationsResponse, error) { + result := new(ListOrganizationsResponse) + endpoint := "/api/v2/organizations/" + resp, err := t.client.Requester.GetJSON(endpoint, result, params) + if err != nil { + return nil, result, err + } + + if err := CheckResponse(resp); err != nil { + return nil, result, err + } + + return result.Results, result, nil +} + +// CreateOrganization creates an awx Organization. +func (t *OrganizationService) CreateOrganization(data map[string]interface{}, params map[string]string) (*Organization, error) { + mandatoryFields = []string{"name"} + validate, status := ValidateParams(data, mandatoryFields) + + if !status { + err := fmt.Errorf("Mandatory input arguments are absent: %s", validate) + return nil, err + } + + result := new(Organization) + endpoint := "/api/v2/organizations/" + payload, err := json.Marshal(data) + if err != nil { + return nil, err + } + + // Add check if Organization exists and return proper error + + resp, err := t.client.Requester.PostJSON(endpoint, bytes.NewReader(payload), result, params) + if err != nil { + return nil, err + } + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return result, nil +} + +// UpdateOrganization update an awx user. +func (t *OrganizationService) UpdateOrganization(id int, data map[string]interface{}, params map[string]string) (*Organization, error) { + result := new(Organization) + endpoint := fmt.Sprintf("/api/v2/organizations/%d", id) + payload, err := json.Marshal(data) + if err != nil { + return nil, err + } + + resp, err := t.client.Requester.PostJSON(endpoint, bytes.NewReader(payload), result, nil) + if err != nil { + return nil, err + } + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return result, nil +} + +// DeleteOrganization delete an awx Organization. +func (t *OrganizationService) DeleteOrganization(id int) (*Organization, error) { + result := new(Organization) + endpoint := fmt.Sprintf("/api/v2/organizations/%d", id) + + resp, err := t.client.Requester.Delete(endpoint, result, nil) + if err != nil { + return nil, err + } + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return result, nil +} diff --git a/organizations_test.go b/organizations_test.go new file mode 100644 index 0000000..9a44e7c --- /dev/null +++ b/organizations_test.go @@ -0,0 +1,48 @@ +package awx + +import ( + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "net/http" + "testing" +) + +type OrganizationsTestSuite struct { + suite.Suite + testOrg *Organization + client *AWX +} + +func TestProviders(t *testing.T) { + suite.Run(t, &OrganizationsTestSuite{}) +} + +func (o *OrganizationsTestSuite) SetupTest() { + awxUser := "admin" + awxPassword := "password" + c := &http.Client{} + o.client = NewAWX("http://localhost", awxUser, awxPassword, c) + o.T().Logf("AWX: %+v", o.client) +} + +func (o *OrganizationsTestSuite) TestCreateOrganization() { + oc := o.client.OrganizationService + + data := map[string]interface{}{"name": "Testing", "description": "A Test organization"} + + org, err := oc.CreateOrganization(data, map[string]string{}) + require.Nil(o.T(), err) + // Make sure that the org was created by making sure an ID was set + require.NotNil(o.T(), org.ID) + o.testOrg = org +} + +func (o *OrganizationsTestSuite) TestListOrganizations() { + oc := o.client.OrganizationService + + org, _, err := oc.ListOrganizations(map[string]string{}) + require.Nil(o.T(), err) + // Make sure we get a non nil list back + require.NotEmpty(o.T(), org) + o.T().Logf("%+v", org) +} diff --git a/teams.go b/teams.go new file mode 100644 index 0000000..2bea8db --- /dev/null +++ b/teams.go @@ -0,0 +1,152 @@ +package awx + +import ( + "bytes" + "encoding/json" + "fmt" +) + +// TeamService implements awx Teams apis. +type TeamService struct { + client *Client +} + +// ListTeamsResponse represents `ListTeams` endpoint response. +type ListTeamsResponse struct { + Pagination + Results []*Team `json:"results"` +} + +// ListTeams shows list of awx Teams. +func (t *TeamService) ListTeams(params map[string]string) ([]*Team, *ListTeamsResponse, error) { + result := new(ListTeamsResponse) + endpoint := "/api/v2/teams/" + resp, err := t.client.Requester.GetJSON(endpoint, result, params) + if err != nil { + return nil, result, err + } + + if err := CheckResponse(resp); err != nil { + return nil, result, err + } + + return result.Results, result, nil +} + +// CreateTeam creates an awx Team. +func (t *TeamService) CreateTeam(data map[string]interface{}, params map[string]string) (*Team, error) { + mandatoryFields = []string{"name", "organization"} + validate, status := ValidateParams(data, mandatoryFields) + + if !status { + err := fmt.Errorf("Mandatory input arguments are absent: %s", validate) + return nil, err + } + + result := new(Team) + endpoint := "/api/v2/teams/" + payload, err := json.Marshal(data) + if err != nil { + return nil, err + } + + // Add check if Team exists and return proper error + + resp, err := t.client.Requester.PostJSON(endpoint, bytes.NewReader(payload), result, params) + if err != nil { + return nil, err + } + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return result, nil +} + +// UpdateTeam update an awx user. +func (t *TeamService) UpdateTeam(id int, data map[string]interface{}, params map[string]string) (*Team, error) { + result := new(Team) + endpoint := fmt.Sprintf("/api/v2/teams/%d", id) + payload, err := json.Marshal(data) + if err != nil { + return nil, err + } + + resp, err := t.client.Requester.PutJSON(endpoint, bytes.NewReader(payload), result, nil) + if err != nil { + return nil, err + } + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return result, nil +} + +// DeleteTeam delete an awx Team. +func (t *TeamService) DeleteTeam(id int) (*Team, error) { + result := new(Team) + endpoint := fmt.Sprintf("/api/v2/teams/%d", id) + + resp, err := t.client.Requester.Delete(endpoint, result, nil) + if err != nil { + return nil, err + } + + if err := CheckResponse(resp); err != nil { + return nil, err + } + + return result, nil +} + +// GrantRole grant the provided role to the AWX Team +func (t *TeamService) GrantRole(id int, roleID int) error { + result := new(Team) + endpoint := fmt.Sprintf("/api/v2/teams/%d/roles/", id) + data := map[string]interface{}{ + "id": roleID, + } + payload, err := json.Marshal(data) + if err != nil { + return err + } + + resp, err := t.client.Requester.PostJSON(endpoint, bytes.NewReader(payload), result, nil) + if err != nil { + return err + } + + if err := CheckResponse(resp); err != nil { + return err + } + + return nil +} + +// RevokeRole revoke the provided role to the AWX Team +func (t *TeamService) RevokeRole(id int, roleID int) error { + result := new(Team) + endpoint := fmt.Sprintf("/api/v2/teams/%d/roles/", id) + data := map[string]interface{}{ + "id": roleID, + "disassociate": "true", + } + payload, err := json.Marshal(data) + if err != nil { + return err + } + + resp, err := t.client.Requester.PostJSON(endpoint, bytes.NewReader(payload), result, nil) + if err != nil { + return err + } + + if err := CheckResponse(resp); err != nil { + return err + } + + return nil +} diff --git a/teams_test.go b/teams_test.go new file mode 100644 index 0000000..57eb11d --- /dev/null +++ b/teams_test.go @@ -0,0 +1,312 @@ +package awx + +// +//import ( +// "testing" +// "time" +//) +// +//func TestListTeams(t *testing.T) { +// var ( +// expectListTeamsResponse = []*Team{ +// { +// ID: 1, +// Type: "team", +// URL: "/api/v2/teams/1/", +// Related: &Related{ +// CreatedBy: "/api/v2/users/4/", +// ModifiedBy: "/api/v2/users/4/", +// Users: "/api/v2/teams/1/users/", +// Roles: "/api/v2/teams/1/roles/", +// ObjectRoles: "/api/v2/teams/1/object_roles/", +// Credentials: "/api/v2/teams/1/credentials/", +// Projects: "/api/v2/teams/1/projects/", +// ActivityStream: "/api/v2/teams/1/activity_stream/", +// AccessList: "/api/v2/teams/1/access_list/", +// Organization: "/api/v2/organizations/1/", +// }, +// SummaryFields: &Summary{ +// UserCapabilities: &UserCapabilities{ +// Edit: true, +// Delete: true, +// }, +// Organization: &OrgnizationSummary{ +// ID: 1, +// Name: "Default", +// Description: "", +// }, +// ObjectRoles: &ObjectRoles{ +// AdminRole: &ApplyRole{ +// ID: 30, +// Description: "Can manage all aspects of the team", +// Name: "Admin", +// }, +// +// MemberRole: &ApplyRole{ +// ID: 29, +// Description: "User is a member of the team", +// Name: "Member", +// }, +// +// ReadRole: &ApplyRole{ +// ID: 31, +// Description: "May view settings for the team", +// Name: "Read", +// }, +// }, +// CreatedBy: &ByUserSummary{ +// ID: 4, +// Username: "admin", +// FirstName: "", +// LastName: "", +// }, +// ModifiedBy: &ByUserSummary{ +// ID: 4, +// Username: "admin", +// FirstName: "", +// LastName: "", +// }, +// }, +// Created: func() time.Time { +// t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") +// return t +// }(), +// Modified: func() time.Time { +// t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") +// return t +// }(), +// Name: "test-team", +// Organization: 1, +// Description: "", +// }, +// } +// ) +// +// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) +// result, _, err := awx.TeamService.ListTeams(map[string]string{ +// "name": "test-team", +// }) +// +// if err != nil { +// t.Fatalf("ListTeams err: %s", err) +// } else { +// checkAPICallResult(t, expectListTeamsResponse, result) +// t.Log("ListTeams passed!") +// } +//} +// +//func TestCreateTeam(t *testing.T) { +// var ( +// expectCreateTeamResponse = &Team{ +// ID: 1, +// Type: "team", +// URL: "/api/v2/teams/1/", +// Related: &Related{ +// CreatedBy: "/api/v2/users/4/", +// ModifiedBy: "/api/v2/users/4/", +// Users: "/api/v2/teams/1/users/", +// Roles: "/api/v2/teams/1/roles/", +// ObjectRoles: "/api/v2/teams/1/object_roles/", +// Credentials: "/api/v2/teams/1/credentials/", +// Projects: "/api/v2/teams/1/projects/", +// ActivityStream: "/api/v2/teams/1/activity_stream/", +// AccessList: "/api/v2/teams/1/access_list/", +// Organization: "/api/v2/organizations/1/", +// }, +// SummaryFields: &Summary{ +// UserCapabilities: &UserCapabilities{ +// Edit: true, +// Delete: true, +// }, +// Organization: &OrgnizationSummary{ +// ID: 1, +// Name: "Default", +// Description: "", +// }, +// ObjectRoles: &ObjectRoles{ +// AdminRole: &ApplyRole{ +// ID: 30, +// Description: "Can manage all aspects of the team", +// Name: "Admin", +// }, +// +// MemberRole: &ApplyRole{ +// ID: 29, +// Description: "User is a member of the team", +// Name: "Member", +// }, +// +// ReadRole: &ApplyRole{ +// ID: 31, +// Description: "May view settings for the team", +// Name: "Read", +// }, +// }, +// CreatedBy: &ByUserSummary{ +// ID: 4, +// Username: "admin", +// FirstName: "", +// LastName: "", +// }, +// ModifiedBy: &ByUserSummary{ +// ID: 4, +// Username: "admin", +// FirstName: "", +// LastName: "", +// }, +// }, +// Created: func() time.Time { +// t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") +// return t +// }(), +// Modified: func() time.Time { +// t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") +// return t +// }(), +// Name: "test-team", +// Organization: 1, +// Description: "", +// } +// ) +// +// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) +// result, err := awx.TeamService.CreateTeam(map[string]interface{}{ +// "name": "test-team", +// "organization": 1, +// }, map[string]string{}) +// if err != nil { +// t.Fatalf("CreateTeam err: %s", err) +// } else { +// checkAPICallResult(t, expectCreateTeamResponse, result) +// t.Log("CreateTeam passed!") +// } +//} +// +//func TestUpdateTeam(t *testing.T) { +// var ( +// expectUpdateTeamResponse = &Team{ +// ID: 1, +// Type: "team", +// URL: "/api/v2/teams/1/", +// Related: &Related{ +// CreatedBy: "/api/v2/users/4/", +// ModifiedBy: "/api/v2/users/4/", +// Users: "/api/v2/teams/1/users/", +// Roles: "/api/v2/teams/1/roles/", +// ObjectRoles: "/api/v2/teams/1/object_roles/", +// Credentials: "/api/v2/teams/1/credentials/", +// Projects: "/api/v2/teams/1/projects/", +// ActivityStream: "/api/v2/teams/1/activity_stream/", +// AccessList: "/api/v2/teams/1/access_list/", +// Organization: "/api/v2/organizations/1/", +// }, +// SummaryFields: &Summary{ +// UserCapabilities: &UserCapabilities{ +// Edit: true, +// Delete: true, +// }, +// Organization: &OrgnizationSummary{ +// ID: 1, +// Name: "Default", +// Description: "", +// }, +// ObjectRoles: &ObjectRoles{ +// AdminRole: &ApplyRole{ +// ID: 30, +// Description: "Can manage all aspects of the team", +// Name: "Admin", +// }, +// +// MemberRole: &ApplyRole{ +// ID: 29, +// Description: "User is a member of the team", +// Name: "Member", +// }, +// +// ReadRole: &ApplyRole{ +// ID: 31, +// Description: "May view settings for the team", +// Name: "Read", +// }, +// }, +// CreatedBy: &ByUserSummary{ +// ID: 4, +// Username: "admin", +// FirstName: "", +// LastName: "", +// }, +// ModifiedBy: &ByUserSummary{ +// ID: 4, +// Username: "admin", +// FirstName: "", +// LastName: "", +// }, +// }, +// Created: func() time.Time { +// t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") +// return t +// }(), +// Modified: func() time.Time { +// t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") +// return t +// }(), +// Name: "test-team", +// Organization: 1, +// Description: "Update test-team", +// } +// ) +// +// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) +// result, err := awx.TeamService.UpdateTeam(4, map[string]interface{}{ +// "name": "test-team", +// "organization": 1, +// "description": "Update test-team", +// }, map[string]string{}) +// if err != nil { +// t.Fatalf("CreateTeam err: %s", err) +// } else { +// checkAPICallResult(t, expectUpdateTeamResponse, result) +// t.Log("CreateTeam passed!") +// } +//} +//func TestDeleteTeam(t *testing.T) { +// var ( +// expectDeleteTeamResponse = &Team{} +// ) +// +// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) +// result, err := awx.TeamService.DeleteTeam(1) +// +// if err != nil { +// t.Fatalf("DeleteTeam err: %s", err) +// } else { +// checkAPICallResult(t, expectDeleteTeamResponse, result) +// t.Log("DeleteTeam passed!") +// } +//} +// +//func TestTeamGrantRole(t *testing.T) { +// +// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) +// err := awx.TeamService.GrantRole(4, 170) +// +// if err != nil { +// t.Fatalf("TestTeamGrantRole err: %s", err) +// } else { +// checkAPICallResult(t, nil, nil) +// t.Log("TestTeamGrantRole passed!") +// } +//} +// +//func TestTeamRevokeRole(t *testing.T) { +// +// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) +// err := awx.TeamService.RevokeRole(1, 170) +// +// if err != nil { +// t.Fatalf("TestTeamRevokeRole err: %s", err) +// } else { +// checkAPICallResult(t, nil, nil) +// t.Log("TestTeamRevokeRole passed!") +// } +//} diff --git a/types.go b/types.go index f5f9bbe..8dc8665 100644 --- a/types.go +++ b/types.go @@ -80,6 +80,7 @@ type Related struct { AdHocCommandEvents string `json:"ad_hoc_command_events"` Children string `json:"children"` AnsibleFacts string `json:"ansible_facts"` + Callback string `json:"callback"` } // OrgnizationSummary represents the awx api orgnization summary fields. @@ -120,12 +121,20 @@ type ApplyRole struct { // ObjectRoles represents the awx api object roles. type ObjectRoles struct { - UseRole *ApplyRole `json:"use_role"` - AdminRole *ApplyRole `json:"admin_role"` - AdhocRole *ApplyRole `json:"adhoc_role"` - UpdateRole *ApplyRole `json:"update_role"` - ReadRole *ApplyRole `json:"read_role"` - ExecuteRole *ApplyRole `json:"execute_role"` + UseRole *ApplyRole `json:"use_role"` + AdminRole *ApplyRole `json:"admin_role"` + AdhocRole *ApplyRole `json:"adhoc_role"` + UpdateRole *ApplyRole `json:"update_role"` + ReadRole *ApplyRole `json:"read_role"` + ExecuteRole *ApplyRole `json:"execute_role"` + MemberRole *MemberRole `json:"member_role"` + NotificationAdminRole *NotificationAdminRole `json:"notification_admin_role"` + WorkflowAdminRole *WorkflowAdminRole `json:"workflow_admin_role"` + CredentialAdminRole *CredentialAdminRole `json:"credential_admin_role"` + JobTemplateAdminRole *JobTemplateAdminRole `json:"job_template_admin_role"` + ProjectAdminRole *ProjectAdminRole `json:"project_admin_role"` + AuditorRole *AuditorRole `json:"auditor_role"` + InventoryAdminRole *InventoryAdminRole `json:"inventory_admin_role"` } // UserCapabilities represents the awx api user capabilities. @@ -336,6 +345,7 @@ type JobTemplate struct { CustomVirtualenv interface{} `json:"custom_virtualenv"` Credential int `json:"credential"` VaultCredential interface{} `json:"vault_credential"` + AllowCallbacks bool `json:"allow_callbacks"` } // JobLaunch represents the awx api job launch. @@ -399,6 +409,19 @@ type JobLaunch struct { VaultCredential interface{} `json:"vault_credential"` } +type JobLaunchOpts struct { + ExtraVars map[string]interface{} `json:"extra_vars,omitempty"` + Inventory int `json:"inventory,omitempty"` + Limit string `json:"limit,omitempty"` + JobTags string `json:"job_tags,omitempty"` + SkipTags string `json:"skip_tags,omitempty"` + JobType string `json:"job_type,omitempty"` + Verbosity int `json:"verbosity,omitempty"` + DiffMode interface{} `json:"diff_mode,omitempty"` + Credentials []int `json:"credentials,omitempty"` + CredentialPasswords []string `json:"credential_passwords,omitempty"` +} + // Job represents the awx api job. type Job struct { ID int `json:"id"` @@ -659,3 +682,132 @@ type Host struct { InsightsSystemID interface{} `json:"insights_system_id"` AnsibleFactsModified interface{} `json:"ansible_facts_modified"` } + +type Organization struct { + ID int `json:"id"` + Type string `json:"type"` + URL string `json:"url"` + Related Related `json:"related"` + SummaryFields SummaryFields `json:"summary_fields"` + Created time.Time `json:"created"` + Modified time.Time `json:"modified"` + Name string `json:"name"` + Description string `json:"description"` + CustomVirtualEnv interface{} `json:"custom_virtualenv"` +} + +type Team struct { + ID int `json:"id"` + Type string `json:"type"` + URL string `json:"url"` + Related Related `json:"related"` + SummaryFields SummaryFields `json:"summary_fields"` + Created time.Time `json:"created"` + Modified time.Time `json:"modified"` + Name string `json:"name"` + Description string `json:"description"` + Organization int `json:"organization"` +} + +type CreatedBy struct { + ID int `json:"id"` + Username string `json:"username"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` +} +type ModifiedBy struct { + ID int `json:"id"` + Username string `json:"username"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` +} +type AdminRole struct { + ID int `json:"id"` + Description string `json:"description"` + Name string `json:"name"` +} +type ReadRole struct { + ID int `json:"id"` + Description string `json:"description"` + Name string `json:"name"` +} +type MemberRole struct { + ID int `json:"id"` + Description string `json:"description"` + Name string `json:"name"` +} +type ExecuteRole struct { + ID int `json:"id"` + Description string `json:"description"` + Name string `json:"name"` +} +type NotificationAdminRole struct { + ID int `json:"id"` + Description string `json:"description"` + Name string `json:"name"` +} +type WorkflowAdminRole struct { + ID int `json:"id"` + Description string `json:"description"` + Name string `json:"name"` +} +type CredentialAdminRole struct { + ID int `json:"id"` + Description string `json:"description"` + Name string `json:"name"` +} +type JobTemplateAdminRole struct { + ID int `json:"id"` + Description string `json:"description"` + Name string `json:"name"` +} +type ProjectAdminRole struct { + ID int `json:"id"` + Description string `json:"description"` + Name string `json:"name"` +} +type AuditorRole struct { + ID int `json:"id"` + Description string `json:"description"` + Name string `json:"name"` +} +type InventoryAdminRole struct { + ID int `json:"id"` + Description string `json:"description"` + Name string `json:"name"` +} + +type RelatedFieldCounts struct { + JobTemplates int `json:"job_templates"` + Users int `json:"users"` + Teams int `json:"teams"` + Admins int `json:"admins"` + Inventories int `json:"inventories"` + Projects int `json:"projects"` +} +type SummaryFields struct { + CreatedBy CreatedBy `json:"created_by"` + ModifiedBy ModifiedBy `json:"modified_by"` + ObjectRoles ObjectRoles `json:"object_roles"` + UserCapabilities UserCapabilities `json:"user_capabilities"` + RelatedFieldCounts RelatedFieldCounts `json:"related_field_counts"` +} + +type SurveySpec struct { + Name string `json:"name"` + Description string `json:"description"` + Spec []Spec `json:"spec"` +} + +type Spec struct { + QuestionName string `json:"question_name"` + QuestionDescription string `json:"question_description"` + Required bool `json:"required"` + Type string `json:"type"` + Variable string `json:"variable"` + Min int `json:"min"` + Max int `json:"max"` + Default string `json:"default"` + Choices string `json:"choices"` + NewQuestion bool `json:"new_question"` +} diff --git a/users.go b/users.go index e06a94f..b81c982 100644 --- a/users.go +++ b/users.go @@ -101,3 +101,51 @@ func (u *UserService) DeleteUser(id int) (*User, error) { return result, nil } + +func (u *UserService) RevokeRole(id, roleID string) error { + result := new(User) + endpoint := fmt.Sprintf("/api/v2/users/%s", id) + jsonPayload := map[string]string{ + "disassociate": roleID, + } + + j, err := json.Marshal(jsonPayload) + + if err != nil { + return err + } + + resp, err := u.client.Requester.PostJSON(endpoint, bytes.NewReader(j), result, jsonPayload) + if err != nil { + return err + } + + if err := CheckResponse(resp); err != nil { + return err + } + return nil +} + +func (u *UserService) GrantRole(id, roleID string) error { + result := new(User) + endpoint := fmt.Sprintf("/api/v2/users/%s", id) + jsonPayload := map[string]string{ + "id": roleID, + } + + j, err := json.Marshal(jsonPayload) + + if err != nil { + return err + } + + resp, err := u.client.Requester.PostJSON(endpoint, bytes.NewReader(j), result, jsonPayload) + if err != nil { + return err + } + + if err := CheckResponse(resp); err != nil { + return err + } + return nil +} From 5c1e59f70fdee37559320f107b9f7ea799065d94 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Sat, 28 Mar 2020 17:12:36 +0100 Subject: [PATCH 02/14] Follow Go import style Co-Authored-By: Jacky Wu --- job_template.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/job_template.go b/job_template.go index 4da58f3..7f5964a 100644 --- a/job_template.go +++ b/job_template.go @@ -5,8 +5,9 @@ import ( "encoding/json" "errors" "fmt" - "github.com/twinj/uuid" "strconv" + + "github.com/twinj/uuid" ) // JobTemplateService implements awx job template apis. From 01201b813689128a3e52e69405fc8a6d822f8901 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Sat, 28 Mar 2020 17:16:03 +0100 Subject: [PATCH 03/14] Fix copy-pasting issue --- job_template.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/job_template.go b/job_template.go index 7f5964a..58d392f 100644 --- a/job_template.go +++ b/job_template.go @@ -161,7 +161,7 @@ func (jt *JobTemplateService) GetJobTemplate(id int) (*JobTemplate, error) { resp, err := jt.client.Requester.Get(endpoint, result, map[string]string{}) if err != nil { return nil, err - }https://github.com/Colstuwjx/awx-go.git + } if err := CheckResponse(resp); err != nil { return nil, err From 169387757e5c5eacf6fad9ead4e87ce4a7fae8b0 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Sat, 28 Mar 2020 17:20:56 +0100 Subject: [PATCH 04/14] Apply suggestion from @Colstuwjx --- job_template.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/job_template.go b/job_template.go index 58d392f..4665ff2 100644 --- a/job_template.go +++ b/job_template.go @@ -64,7 +64,7 @@ func (jt *JobTemplateService) CreateJobTemplateCallBack(template *JobTemplate) ( return nil, fmt.Errorf("Job template ID must be passed") } - endpoint := "/api/v2/job_templates/" + strconv.Itoa(template.ID) + endpoint := fmt.Sprintf("/api/v2/job_templates/%d", template.ID) template.AllowCallbacks = true template.HostConfigKey = uuid.NewV4().String() From 370f65d79a771fb2f280c8bf8ddd91b92324b6c8 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Sat, 28 Mar 2020 17:26:50 +0100 Subject: [PATCH 05/14] Enable tests --- credentials_test.go | 561 ++++++++++++++++++++------------------- teams_test.go | 619 ++++++++++++++++++++++---------------------- 2 files changed, 589 insertions(+), 591 deletions(-) diff --git a/credentials_test.go b/credentials_test.go index 7543297..a165670 100644 --- a/credentials_test.go +++ b/credentials_test.go @@ -1,283 +1,282 @@ package awx -// -//import ( -// "testing" -// "time" -//) -// -//func TestListCredentials(t *testing.T) { -// var ( -// expectListCredentialsResponse = []*Credential{ -// { -// ID: 1, -// Type: "credential", -// URL: "/api/v2/credentials/1/", -// Related: &Related{ -// ObjectRoles: "/api/v2/credentials/1/object_roles/", -// AccessList: "/api/v2/credentials/1/access_list/", -// CredentialType: "/api/v2/credential_types/1/", -// ModifiedBy: "/api/v2/users/4/", -// OwnerUsers: "/api/v2/credentials/1/owner_users/", -// OwnerTeams: "/api/v2/credentials/1/owner_teams/", -// Organization: "/api/v2/organizations/1/", -// Copy: "/api/v2/credentials/1/copy/", -// ActivityStream: "/api/v2/credentials/1/activity_stream/", -// }, -// SummaryFields: &Summary{ -// Organization: &OrgnizationSummary{ -// ID: 1, -// Name: "Default", -// Description: "", -// }, -// Project: &Project{}, -// ModifiedBy: &ByUserSummary{ -// ID: 4, -// Username: "admin", -// FirstName: "", -// LastName: "", -// }, -// ObjectRoles: &ObjectRoles{ -// AdminRole: &ApplyRole{ -// ID: 18, -// Description: "Can manage all aspects of the credential", -// Name: "Admin", -// }, -// UseRole: &ApplyRole{ -// ID: 20, -// Description: "Can use the credential in a job template", -// Name: "Use", -// }, -// ReadRole: &ApplyRole{ -// ID: 19, -// Description: "May view settings for the credential", -// Name: "Read", -// }, -// }, -// UserCapabilities: &UserCapabilities{ -// Edit: true, -// Delete: true, -// Copy: true, -// }, -// }, -// Created: func() time.Time { -// t, _ := time.Parse(time.RFC3339, "2018-12-01T12:10:00.496424Z") -// return t -// }(), -// Modified: func() time.Time { -// t, _ := time.Parse(time.RFC3339, "2018-12-07T16:17:48.131210Z") -// return t -// }(), -// Name: "Demo Credential", -// Description: "", -// Organization: 1, -// CredentialType: 1, -// Inputs: map[string]interface{}{ -// "username": "admin", -// }, -// }, -// } -// ) -// -// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) -// result, _, err := awx.CredentialService.ListCredentials(map[string]string{ -// "name": "Default", -// }) -// -// if err != nil { -// t.Fatalf("ListCredentials err: %s", err) -// } else { -// checkAPICallResult(t, expectListCredentialsResponse, result) -// t.Log("ListCredentials passed!") -// } -//} -// -//func TestCreateCredentials(t *testing.T) { -// var ( -// expectCreateCredentialsResponse = &Credential{ -// ID: 1, -// Type: "credential", -// URL: "/api/v2/credentials/1/", -// Related: &Related{ -// ObjectRoles: "/api/v2/credentials/1/object_roles/", -// AccessList: "/api/v2/credentials/1/access_list/", -// CredentialType: "/api/v2/credential_types/1/", -// ModifiedBy: "/api/v2/users/4/", -// OwnerUsers: "/api/v2/credentials/1/owner_users/", -// OwnerTeams: "/api/v2/credentials/1/owner_teams/", -// Organization: "/api/v2/organizations/1/", -// Copy: "/api/v2/credentials/1/copy/", -// ActivityStream: "/api/v2/credentials/1/activity_stream/", -// }, -// SummaryFields: &Summary{ -// Organization: &OrgnizationSummary{ -// ID: 1, -// Name: "Default", -// Description: "", -// }, -// Project: &Project{}, -// ModifiedBy: &ByUserSummary{ -// ID: 4, -// Username: "admin", -// FirstName: "", -// LastName: "", -// }, -// ObjectRoles: &ObjectRoles{ -// AdminRole: &ApplyRole{ -// ID: 18, -// Description: "Can manage all aspects of the credential", -// Name: "Admin", -// }, -// UseRole: &ApplyRole{ -// ID: 20, -// Description: "Can use the credential in a job template", -// Name: "Use", -// }, -// ReadRole: &ApplyRole{ -// ID: 19, -// Description: "May view settings for the credential", -// Name: "Read", -// }, -// }, -// UserCapabilities: &UserCapabilities{ -// Edit: true, -// Delete: true, -// Copy: true, -// }, -// }, -// Created: func() time.Time { -// t, _ := time.Parse(time.RFC3339, "2018-12-01T12:10:00.496424Z") -// return t -// }(), -// Modified: func() time.Time { -// t, _ := time.Parse(time.RFC3339, "2018-12-07T16:17:48.131210Z") -// return t -// }(), -// Name: "Demo Credential", -// Description: "", -// Organization: 1, -// CredentialType: 1, -// Inputs: map[string]interface{}{ -// "username": "admin", -// }, -// } -// ) -// -// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) -// result, err := awx.CredentialService.CreateCredential(map[string]interface{}{ -// "name": "Demo Credential", -// "organization": 1, -// "credential_type": 1, -// }, map[string]string{}) -// if err != nil { -// t.Fatalf("CreateCredentials err: %s", err) -// } else { -// checkAPICallResult(t, expectCreateCredentialsResponse, result) -// t.Log("CreateCredentials passed!") -// } -//} -// -//func TestUpdateCredentials(t *testing.T) { -// var ( -// expectUpdateCredentialsResponse = &Credential{ -// ID: 1, -// Type: "credential", -// URL: "/api/v2/credentials/1/", -// Related: &Related{ -// ObjectRoles: "/api/v2/credentials/1/object_roles/", -// AccessList: "/api/v2/credentials/1/access_list/", -// CredentialType: "/api/v2/credential_types/1/", -// ModifiedBy: "/api/v2/users/4/", -// OwnerUsers: "/api/v2/credentials/1/owner_users/", -// OwnerTeams: "/api/v2/credentials/1/owner_teams/", -// Organization: "/api/v2/organizations/1/", -// Copy: "/api/v2/credentials/1/copy/", -// ActivityStream: "/api/v2/credentials/1/activity_stream/", -// }, -// SummaryFields: &Summary{ -// Organization: &OrgnizationSummary{ -// ID: 1, -// Name: "Default", -// Description: "", -// }, -// Project: &Project{}, -// ModifiedBy: &ByUserSummary{ -// ID: 4, -// Username: "admin", -// FirstName: "", -// LastName: "", -// }, -// ObjectRoles: &ObjectRoles{ -// AdminRole: &ApplyRole{ -// ID: 18, -// Description: "Can manage all aspects of the credential", -// Name: "Admin", -// }, -// UseRole: &ApplyRole{ -// ID: 20, -// Description: "Can use the credential in a job template", -// Name: "Use", -// }, -// ReadRole: &ApplyRole{ -// ID: 19, -// Description: "May view settings for the credential", -// Name: "Read", -// }, -// }, -// UserCapabilities: &UserCapabilities{ -// Edit: true, -// Delete: true, -// Copy: true, -// }, -// }, -// Created: func() time.Time { -// t, _ := time.Parse(time.RFC3339, "2018-12-01T12:10:00.496424Z") -// return t -// }(), -// Modified: func() time.Time { -// t, _ := time.Parse(time.RFC3339, "2018-12-07T16:17:48.131210Z") -// return t -// }(), -// Name: "Demo Credential", -// Description: "Demo Credential", -// Organization: 1, -// CredentialType: 1, -// Inputs: map[string]interface{}{ -// "username": "admin", -// }, -// } -// ) -// -// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) -// result, err := awx.CredentialService.UpdateCredential(1, map[string]interface{}{ -// "name": "Demo Credential", -// "description": "Demo credential", -// "organization": 1, -// "credential_type": 1, -// "inputs": map[string]interface{}{ -// "username": "admin", -// }, -// }, map[string]string{}) -// if err != nil { -// t.Fatalf("CreateCredentials err: %s", err) -// } else { -// checkAPICallResult(t, expectUpdateCredentialsResponse, result) -// t.Log("CreateCredentials passed!") -// } -//} -// -//func TestDeleteCredentials(t *testing.T) { -// var ( -// expectDeleteCredentialsResponse = &Credential{} -// ) -// -// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) -// result, err := awx.CredentialService.DeleteCredential(1) -// -// if err != nil { -// t.Fatalf("DeleteCredentials err: %s", err) -// } else { -// checkAPICallResult(t, expectDeleteCredentialsResponse, result) -// t.Log("DeleteCredentials passed!") -// } -//} +import ( + "testing" + "time" +) + +func TestListCredentials(t *testing.T) { + var ( + expectListCredentialsResponse = []*Credential{ + { + ID: 1, + Type: "credential", + URL: "/api/v2/credentials/1/", + Related: &Related{ + ObjectRoles: "/api/v2/credentials/1/object_roles/", + AccessList: "/api/v2/credentials/1/access_list/", + CredentialType: "/api/v2/credential_types/1/", + ModifiedBy: "/api/v2/users/4/", + OwnerUsers: "/api/v2/credentials/1/owner_users/", + OwnerTeams: "/api/v2/credentials/1/owner_teams/", + Organization: "/api/v2/organizations/1/", + Copy: "/api/v2/credentials/1/copy/", + ActivityStream: "/api/v2/credentials/1/activity_stream/", + }, + SummaryFields: &Summary{ + Organization: &OrgnizationSummary{ + ID: 1, + Name: "Default", + Description: "", + }, + Project: &Project{}, + ModifiedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, + ObjectRoles: &ObjectRoles{ + AdminRole: &ApplyRole{ + ID: 18, + Description: "Can manage all aspects of the credential", + Name: "Admin", + }, + UseRole: &ApplyRole{ + ID: 20, + Description: "Can use the credential in a job template", + Name: "Use", + }, + ReadRole: &ApplyRole{ + ID: 19, + Description: "May view settings for the credential", + Name: "Read", + }, + }, + UserCapabilities: &UserCapabilities{ + Edit: true, + Delete: true, + Copy: true, + }, + }, + Created: func() time.Time { + t, _ := time.Parse(time.RFC3339, "2018-12-01T12:10:00.496424Z") + return t + }(), + Modified: func() time.Time { + t, _ := time.Parse(time.RFC3339, "2018-12-07T16:17:48.131210Z") + return t + }(), + Name: "Demo Credential", + Description: "", + Organization: 1, + CredentialType: 1, + Inputs: map[string]interface{}{ + "username": "admin", + }, + }, + } + ) + + awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) + result, _, err := awx.CredentialService.ListCredentials(map[string]string{ + "name": "Default", + }) + + if err != nil { + t.Fatalf("ListCredentials err: %s", err) + } else { + checkAPICallResult(t, expectListCredentialsResponse, result) + t.Log("ListCredentials passed!") + } +} + +func TestCreateCredentials(t *testing.T) { + var ( + expectCreateCredentialsResponse = &Credential{ + ID: 1, + Type: "credential", + URL: "/api/v2/credentials/1/", + Related: &Related{ + ObjectRoles: "/api/v2/credentials/1/object_roles/", + AccessList: "/api/v2/credentials/1/access_list/", + CredentialType: "/api/v2/credential_types/1/", + ModifiedBy: "/api/v2/users/4/", + OwnerUsers: "/api/v2/credentials/1/owner_users/", + OwnerTeams: "/api/v2/credentials/1/owner_teams/", + Organization: "/api/v2/organizations/1/", + Copy: "/api/v2/credentials/1/copy/", + ActivityStream: "/api/v2/credentials/1/activity_stream/", + }, + SummaryFields: &Summary{ + Organization: &OrgnizationSummary{ + ID: 1, + Name: "Default", + Description: "", + }, + Project: &Project{}, + ModifiedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, + ObjectRoles: &ObjectRoles{ + AdminRole: &ApplyRole{ + ID: 18, + Description: "Can manage all aspects of the credential", + Name: "Admin", + }, + UseRole: &ApplyRole{ + ID: 20, + Description: "Can use the credential in a job template", + Name: "Use", + }, + ReadRole: &ApplyRole{ + ID: 19, + Description: "May view settings for the credential", + Name: "Read", + }, + }, + UserCapabilities: &UserCapabilities{ + Edit: true, + Delete: true, + Copy: true, + }, + }, + Created: func() time.Time { + t, _ := time.Parse(time.RFC3339, "2018-12-01T12:10:00.496424Z") + return t + }(), + Modified: func() time.Time { + t, _ := time.Parse(time.RFC3339, "2018-12-07T16:17:48.131210Z") + return t + }(), + Name: "Demo Credential", + Description: "", + Organization: 1, + CredentialType: 1, + Inputs: map[string]interface{}{ + "username": "admin", + }, + } + ) + + awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) + result, err := awx.CredentialService.CreateCredential(map[string]interface{}{ + "name": "Demo Credential", + "organization": 1, + "credential_type": 1, + }, map[string]string{}) + if err != nil { + t.Fatalf("CreateCredentials err: %s", err) + } else { + checkAPICallResult(t, expectCreateCredentialsResponse, result) + t.Log("CreateCredentials passed!") + } +} + +func TestUpdateCredentials(t *testing.T) { + var ( + expectUpdateCredentialsResponse = &Credential{ + ID: 1, + Type: "credential", + URL: "/api/v2/credentials/1/", + Related: &Related{ + ObjectRoles: "/api/v2/credentials/1/object_roles/", + AccessList: "/api/v2/credentials/1/access_list/", + CredentialType: "/api/v2/credential_types/1/", + ModifiedBy: "/api/v2/users/4/", + OwnerUsers: "/api/v2/credentials/1/owner_users/", + OwnerTeams: "/api/v2/credentials/1/owner_teams/", + Organization: "/api/v2/organizations/1/", + Copy: "/api/v2/credentials/1/copy/", + ActivityStream: "/api/v2/credentials/1/activity_stream/", + }, + SummaryFields: &Summary{ + Organization: &OrgnizationSummary{ + ID: 1, + Name: "Default", + Description: "", + }, + Project: &Project{}, + ModifiedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, + ObjectRoles: &ObjectRoles{ + AdminRole: &ApplyRole{ + ID: 18, + Description: "Can manage all aspects of the credential", + Name: "Admin", + }, + UseRole: &ApplyRole{ + ID: 20, + Description: "Can use the credential in a job template", + Name: "Use", + }, + ReadRole: &ApplyRole{ + ID: 19, + Description: "May view settings for the credential", + Name: "Read", + }, + }, + UserCapabilities: &UserCapabilities{ + Edit: true, + Delete: true, + Copy: true, + }, + }, + Created: func() time.Time { + t, _ := time.Parse(time.RFC3339, "2018-12-01T12:10:00.496424Z") + return t + }(), + Modified: func() time.Time { + t, _ := time.Parse(time.RFC3339, "2018-12-07T16:17:48.131210Z") + return t + }(), + Name: "Demo Credential", + Description: "Demo Credential", + Organization: 1, + CredentialType: 1, + Inputs: map[string]interface{}{ + "username": "admin", + }, + } + ) + + awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) + result, err := awx.CredentialService.UpdateCredential(1, map[string]interface{}{ + "name": "Demo Credential", + "description": "Demo credential", + "organization": 1, + "credential_type": 1, + "inputs": map[string]interface{}{ + "username": "admin", + }, + }, map[string]string{}) + if err != nil { + t.Fatalf("CreateCredentials err: %s", err) + } else { + checkAPICallResult(t, expectUpdateCredentialsResponse, result) + t.Log("CreateCredentials passed!") + } +} + +func TestDeleteCredentials(t *testing.T) { + var ( + expectDeleteCredentialsResponse = &Credential{} + ) + + awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) + result, err := awx.CredentialService.DeleteCredential(1) + + if err != nil { + t.Fatalf("DeleteCredentials err: %s", err) + } else { + checkAPICallResult(t, expectDeleteCredentialsResponse, result) + t.Log("DeleteCredentials passed!") + } +} diff --git a/teams_test.go b/teams_test.go index 57eb11d..7d43945 100644 --- a/teams_test.go +++ b/teams_test.go @@ -1,312 +1,311 @@ package awx -// -//import ( -// "testing" -// "time" -//) -// -//func TestListTeams(t *testing.T) { -// var ( -// expectListTeamsResponse = []*Team{ -// { -// ID: 1, -// Type: "team", -// URL: "/api/v2/teams/1/", -// Related: &Related{ -// CreatedBy: "/api/v2/users/4/", -// ModifiedBy: "/api/v2/users/4/", -// Users: "/api/v2/teams/1/users/", -// Roles: "/api/v2/teams/1/roles/", -// ObjectRoles: "/api/v2/teams/1/object_roles/", -// Credentials: "/api/v2/teams/1/credentials/", -// Projects: "/api/v2/teams/1/projects/", -// ActivityStream: "/api/v2/teams/1/activity_stream/", -// AccessList: "/api/v2/teams/1/access_list/", -// Organization: "/api/v2/organizations/1/", -// }, -// SummaryFields: &Summary{ -// UserCapabilities: &UserCapabilities{ -// Edit: true, -// Delete: true, -// }, -// Organization: &OrgnizationSummary{ -// ID: 1, -// Name: "Default", -// Description: "", -// }, -// ObjectRoles: &ObjectRoles{ -// AdminRole: &ApplyRole{ -// ID: 30, -// Description: "Can manage all aspects of the team", -// Name: "Admin", -// }, -// -// MemberRole: &ApplyRole{ -// ID: 29, -// Description: "User is a member of the team", -// Name: "Member", -// }, -// -// ReadRole: &ApplyRole{ -// ID: 31, -// Description: "May view settings for the team", -// Name: "Read", -// }, -// }, -// CreatedBy: &ByUserSummary{ -// ID: 4, -// Username: "admin", -// FirstName: "", -// LastName: "", -// }, -// ModifiedBy: &ByUserSummary{ -// ID: 4, -// Username: "admin", -// FirstName: "", -// LastName: "", -// }, -// }, -// Created: func() time.Time { -// t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") -// return t -// }(), -// Modified: func() time.Time { -// t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") -// return t -// }(), -// Name: "test-team", -// Organization: 1, -// Description: "", -// }, -// } -// ) -// -// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) -// result, _, err := awx.TeamService.ListTeams(map[string]string{ -// "name": "test-team", -// }) -// -// if err != nil { -// t.Fatalf("ListTeams err: %s", err) -// } else { -// checkAPICallResult(t, expectListTeamsResponse, result) -// t.Log("ListTeams passed!") -// } -//} -// -//func TestCreateTeam(t *testing.T) { -// var ( -// expectCreateTeamResponse = &Team{ -// ID: 1, -// Type: "team", -// URL: "/api/v2/teams/1/", -// Related: &Related{ -// CreatedBy: "/api/v2/users/4/", -// ModifiedBy: "/api/v2/users/4/", -// Users: "/api/v2/teams/1/users/", -// Roles: "/api/v2/teams/1/roles/", -// ObjectRoles: "/api/v2/teams/1/object_roles/", -// Credentials: "/api/v2/teams/1/credentials/", -// Projects: "/api/v2/teams/1/projects/", -// ActivityStream: "/api/v2/teams/1/activity_stream/", -// AccessList: "/api/v2/teams/1/access_list/", -// Organization: "/api/v2/organizations/1/", -// }, -// SummaryFields: &Summary{ -// UserCapabilities: &UserCapabilities{ -// Edit: true, -// Delete: true, -// }, -// Organization: &OrgnizationSummary{ -// ID: 1, -// Name: "Default", -// Description: "", -// }, -// ObjectRoles: &ObjectRoles{ -// AdminRole: &ApplyRole{ -// ID: 30, -// Description: "Can manage all aspects of the team", -// Name: "Admin", -// }, -// -// MemberRole: &ApplyRole{ -// ID: 29, -// Description: "User is a member of the team", -// Name: "Member", -// }, -// -// ReadRole: &ApplyRole{ -// ID: 31, -// Description: "May view settings for the team", -// Name: "Read", -// }, -// }, -// CreatedBy: &ByUserSummary{ -// ID: 4, -// Username: "admin", -// FirstName: "", -// LastName: "", -// }, -// ModifiedBy: &ByUserSummary{ -// ID: 4, -// Username: "admin", -// FirstName: "", -// LastName: "", -// }, -// }, -// Created: func() time.Time { -// t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") -// return t -// }(), -// Modified: func() time.Time { -// t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") -// return t -// }(), -// Name: "test-team", -// Organization: 1, -// Description: "", -// } -// ) -// -// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) -// result, err := awx.TeamService.CreateTeam(map[string]interface{}{ -// "name": "test-team", -// "organization": 1, -// }, map[string]string{}) -// if err != nil { -// t.Fatalf("CreateTeam err: %s", err) -// } else { -// checkAPICallResult(t, expectCreateTeamResponse, result) -// t.Log("CreateTeam passed!") -// } -//} -// -//func TestUpdateTeam(t *testing.T) { -// var ( -// expectUpdateTeamResponse = &Team{ -// ID: 1, -// Type: "team", -// URL: "/api/v2/teams/1/", -// Related: &Related{ -// CreatedBy: "/api/v2/users/4/", -// ModifiedBy: "/api/v2/users/4/", -// Users: "/api/v2/teams/1/users/", -// Roles: "/api/v2/teams/1/roles/", -// ObjectRoles: "/api/v2/teams/1/object_roles/", -// Credentials: "/api/v2/teams/1/credentials/", -// Projects: "/api/v2/teams/1/projects/", -// ActivityStream: "/api/v2/teams/1/activity_stream/", -// AccessList: "/api/v2/teams/1/access_list/", -// Organization: "/api/v2/organizations/1/", -// }, -// SummaryFields: &Summary{ -// UserCapabilities: &UserCapabilities{ -// Edit: true, -// Delete: true, -// }, -// Organization: &OrgnizationSummary{ -// ID: 1, -// Name: "Default", -// Description: "", -// }, -// ObjectRoles: &ObjectRoles{ -// AdminRole: &ApplyRole{ -// ID: 30, -// Description: "Can manage all aspects of the team", -// Name: "Admin", -// }, -// -// MemberRole: &ApplyRole{ -// ID: 29, -// Description: "User is a member of the team", -// Name: "Member", -// }, -// -// ReadRole: &ApplyRole{ -// ID: 31, -// Description: "May view settings for the team", -// Name: "Read", -// }, -// }, -// CreatedBy: &ByUserSummary{ -// ID: 4, -// Username: "admin", -// FirstName: "", -// LastName: "", -// }, -// ModifiedBy: &ByUserSummary{ -// ID: 4, -// Username: "admin", -// FirstName: "", -// LastName: "", -// }, -// }, -// Created: func() time.Time { -// t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") -// return t -// }(), -// Modified: func() time.Time { -// t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") -// return t -// }(), -// Name: "test-team", -// Organization: 1, -// Description: "Update test-team", -// } -// ) -// -// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) -// result, err := awx.TeamService.UpdateTeam(4, map[string]interface{}{ -// "name": "test-team", -// "organization": 1, -// "description": "Update test-team", -// }, map[string]string{}) -// if err != nil { -// t.Fatalf("CreateTeam err: %s", err) -// } else { -// checkAPICallResult(t, expectUpdateTeamResponse, result) -// t.Log("CreateTeam passed!") -// } -//} -//func TestDeleteTeam(t *testing.T) { -// var ( -// expectDeleteTeamResponse = &Team{} -// ) -// -// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) -// result, err := awx.TeamService.DeleteTeam(1) -// -// if err != nil { -// t.Fatalf("DeleteTeam err: %s", err) -// } else { -// checkAPICallResult(t, expectDeleteTeamResponse, result) -// t.Log("DeleteTeam passed!") -// } -//} -// -//func TestTeamGrantRole(t *testing.T) { -// -// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) -// err := awx.TeamService.GrantRole(4, 170) -// -// if err != nil { -// t.Fatalf("TestTeamGrantRole err: %s", err) -// } else { -// checkAPICallResult(t, nil, nil) -// t.Log("TestTeamGrantRole passed!") -// } -//} -// -//func TestTeamRevokeRole(t *testing.T) { -// -// awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) -// err := awx.TeamService.RevokeRole(1, 170) -// -// if err != nil { -// t.Fatalf("TestTeamRevokeRole err: %s", err) -// } else { -// checkAPICallResult(t, nil, nil) -// t.Log("TestTeamRevokeRole passed!") -// } -//} +import ( + "testing" + "time" +) + +func TestListTeams(t *testing.T) { + var ( + expectListTeamsResponse = []*Team{ + { + ID: 1, + Type: "team", + URL: "/api/v2/teams/1/", + Related: &Related{ + CreatedBy: "/api/v2/users/4/", + ModifiedBy: "/api/v2/users/4/", + Users: "/api/v2/teams/1/users/", + Roles: "/api/v2/teams/1/roles/", + ObjectRoles: "/api/v2/teams/1/object_roles/", + Credentials: "/api/v2/teams/1/credentials/", + Projects: "/api/v2/teams/1/projects/", + ActivityStream: "/api/v2/teams/1/activity_stream/", + AccessList: "/api/v2/teams/1/access_list/", + Organization: "/api/v2/organizations/1/", + }, + SummaryFields: &Summary{ + UserCapabilities: &UserCapabilities{ + Edit: true, + Delete: true, + }, + Organization: &OrgnizationSummary{ + ID: 1, + Name: "Default", + Description: "", + }, + ObjectRoles: &ObjectRoles{ + AdminRole: &ApplyRole{ + ID: 30, + Description: "Can manage all aspects of the team", + Name: "Admin", + }, + + MemberRole: &ApplyRole{ + ID: 29, + Description: "User is a member of the team", + Name: "Member", + }, + + ReadRole: &ApplyRole{ + ID: 31, + Description: "May view settings for the team", + Name: "Read", + }, + }, + CreatedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, + ModifiedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, + }, + Created: func() time.Time { + t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") + return t + }(), + Modified: func() time.Time { + t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") + return t + }(), + Name: "test-team", + Organization: 1, + Description: "", + }, + } + ) + + awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) + result, _, err := awx.TeamService.ListTeams(map[string]string{ + "name": "test-team", + }) + + if err != nil { + t.Fatalf("ListTeams err: %s", err) + } else { + checkAPICallResult(t, expectListTeamsResponse, result) + t.Log("ListTeams passed!") + } +} + +func TestCreateTeam(t *testing.T) { + var ( + expectCreateTeamResponse = &Team{ + ID: 1, + Type: "team", + URL: "/api/v2/teams/1/", + Related: &Related{ + CreatedBy: "/api/v2/users/4/", + ModifiedBy: "/api/v2/users/4/", + Users: "/api/v2/teams/1/users/", + Roles: "/api/v2/teams/1/roles/", + ObjectRoles: "/api/v2/teams/1/object_roles/", + Credentials: "/api/v2/teams/1/credentials/", + Projects: "/api/v2/teams/1/projects/", + ActivityStream: "/api/v2/teams/1/activity_stream/", + AccessList: "/api/v2/teams/1/access_list/", + Organization: "/api/v2/organizations/1/", + }, + SummaryFields: &Summary{ + UserCapabilities: &UserCapabilities{ + Edit: true, + Delete: true, + }, + Organization: &OrgnizationSummary{ + ID: 1, + Name: "Default", + Description: "", + }, + ObjectRoles: &ObjectRoles{ + AdminRole: &ApplyRole{ + ID: 30, + Description: "Can manage all aspects of the team", + Name: "Admin", + }, + + MemberRole: &ApplyRole{ + ID: 29, + Description: "User is a member of the team", + Name: "Member", + }, + + ReadRole: &ApplyRole{ + ID: 31, + Description: "May view settings for the team", + Name: "Read", + }, + }, + CreatedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, + ModifiedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, + }, + Created: func() time.Time { + t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") + return t + }(), + Modified: func() time.Time { + t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") + return t + }(), + Name: "test-team", + Organization: 1, + Description: "", + } + ) + + awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) + result, err := awx.TeamService.CreateTeam(map[string]interface{}{ + "name": "test-team", + "organization": 1, + }, map[string]string{}) + if err != nil { + t.Fatalf("CreateTeam err: %s", err) + } else { + checkAPICallResult(t, expectCreateTeamResponse, result) + t.Log("CreateTeam passed!") + } +} + +func TestUpdateTeam(t *testing.T) { + var ( + expectUpdateTeamResponse = &Team{ + ID: 1, + Type: "team", + URL: "/api/v2/teams/1/", + Related: &Related{ + CreatedBy: "/api/v2/users/4/", + ModifiedBy: "/api/v2/users/4/", + Users: "/api/v2/teams/1/users/", + Roles: "/api/v2/teams/1/roles/", + ObjectRoles: "/api/v2/teams/1/object_roles/", + Credentials: "/api/v2/teams/1/credentials/", + Projects: "/api/v2/teams/1/projects/", + ActivityStream: "/api/v2/teams/1/activity_stream/", + AccessList: "/api/v2/teams/1/access_list/", + Organization: "/api/v2/organizations/1/", + }, + SummaryFields: &Summary{ + UserCapabilities: &UserCapabilities{ + Edit: true, + Delete: true, + }, + Organization: &OrgnizationSummary{ + ID: 1, + Name: "Default", + Description: "", + }, + ObjectRoles: &ObjectRoles{ + AdminRole: &ApplyRole{ + ID: 30, + Description: "Can manage all aspects of the team", + Name: "Admin", + }, + + MemberRole: &ApplyRole{ + ID: 29, + Description: "User is a member of the team", + Name: "Member", + }, + + ReadRole: &ApplyRole{ + ID: 31, + Description: "May view settings for the team", + Name: "Read", + }, + }, + CreatedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, + ModifiedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, + }, + Created: func() time.Time { + t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") + return t + }(), + Modified: func() time.Time { + t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") + return t + }(), + Name: "test-team", + Organization: 1, + Description: "Update test-team", + } + ) + + awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) + result, err := awx.TeamService.UpdateTeam(4, map[string]interface{}{ + "name": "test-team", + "organization": 1, + "description": "Update test-team", + }, map[string]string{}) + if err != nil { + t.Fatalf("CreateTeam err: %s", err) + } else { + checkAPICallResult(t, expectUpdateTeamResponse, result) + t.Log("CreateTeam passed!") + } +} +func TestDeleteTeam(t *testing.T) { + var ( + expectDeleteTeamResponse = &Team{} + ) + + awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) + result, err := awx.TeamService.DeleteTeam(1) + + if err != nil { + t.Fatalf("DeleteTeam err: %s", err) + } else { + checkAPICallResult(t, expectDeleteTeamResponse, result) + t.Log("DeleteTeam passed!") + } +} + +func TestTeamGrantRole(t *testing.T) { + + awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) + err := awx.TeamService.GrantRole(4, 170) + + if err != nil { + t.Fatalf("TestTeamGrantRole err: %s", err) + } else { + checkAPICallResult(t, nil, nil) + t.Log("TestTeamGrantRole passed!") + } +} + +func TestTeamRevokeRole(t *testing.T) { + + awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) + err := awx.TeamService.RevokeRole(1, 170) + + if err != nil { + t.Fatalf("TestTeamRevokeRole err: %s", err) + } else { + checkAPICallResult(t, nil, nil) + t.Log("TestTeamRevokeRole passed!") + } +} From 1dbe1906aeede379cb2d1ca0db31ecef09a9ca2e Mon Sep 17 00:00:00 2001 From: colstuwjx Date: Sun, 29 Mar 2020 13:32:24 +0800 Subject: [PATCH 06/14] fix: fixed go mod and make build issue. --- go.mod | 6 +++++- go.sum | 14 ++++++++++++++ job_template.go | 2 -- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4daadf5..430c9bc 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,8 @@ module github.com/Colstuwjx/awx-go go 1.12 -require github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 +require ( + github.com/kylelemons/godebug v1.1.0 + github.com/stretchr/testify v1.5.1 + github.com/twinj/uuid v1.0.0 +) diff --git a/go.sum b/go.sum index 6827ab3..3bbf723 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,16 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/twinj/uuid v1.0.0 h1:fzz7COZnDrXGTAOHGuUGYd6sG+JMq+AoE7+Jlu0przk= +github.com/twinj/uuid v1.0.0/go.mod h1:mMgcE1RHFUFqe5AfiwlINXisXfDGro23fWdPUfOMjRY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/job_template.go b/job_template.go index 4665ff2..3f3a679 100644 --- a/job_template.go +++ b/job_template.go @@ -3,9 +3,7 @@ package awx import ( "bytes" "encoding/json" - "errors" "fmt" - "strconv" "github.com/twinj/uuid" ) From 23b7a78ad6c595dde6e4bade1ec9f5b0d533066f Mon Sep 17 00:00:00 2001 From: David Fischer Date: Tue, 31 Mar 2020 08:34:53 +0200 Subject: [PATCH 07/14] Favor partial update and always pass given params --- credentials.go | 2 +- organizations.go | 2 +- teams.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/credentials.go b/credentials.go index f1fe428..61ebc90 100644 --- a/credentials.go +++ b/credentials.go @@ -73,7 +73,7 @@ func (t *CredentialService) UpdateCredential(id int, data map[string]interface{} return nil, err } - resp, err := t.client.Requester.PutJSON(endpoint, bytes.NewReader(payload), result, nil) + resp, err := t.client.Requester.PatchJSON(endpoint, bytes.NewReader(payload), result, params) if err != nil { return nil, err } diff --git a/organizations.go b/organizations.go index fe4d5ef..b8381bd 100644 --- a/organizations.go +++ b/organizations.go @@ -73,7 +73,7 @@ func (t *OrganizationService) UpdateOrganization(id int, data map[string]interfa return nil, err } - resp, err := t.client.Requester.PostJSON(endpoint, bytes.NewReader(payload), result, nil) + resp, err := t.client.Requester.PatchJSON(endpoint, bytes.NewReader(payload), result, params) if err != nil { return nil, err } diff --git a/teams.go b/teams.go index 2bea8db..d8deeaa 100644 --- a/teams.go +++ b/teams.go @@ -73,7 +73,7 @@ func (t *TeamService) UpdateTeam(id int, data map[string]interface{}, params map return nil, err } - resp, err := t.client.Requester.PutJSON(endpoint, bytes.NewReader(payload), result, nil) + resp, err := t.client.Requester.PatchJSON(endpoint, bytes.NewReader(payload), result, params) if err != nil { return nil, err } From 5f90946c4d4226075174fa6a6b80fed7f03d3b97 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Mon, 30 Mar 2020 14:54:10 +0200 Subject: [PATCH 08/14] Fix test suite --- organizations_test.go | 64 ++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/organizations_test.go b/organizations_test.go index 9a44e7c..5afec07 100644 --- a/organizations_test.go +++ b/organizations_test.go @@ -1,48 +1,62 @@ package awx import ( - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" + "fmt" + "math/rand" "net/http" "testing" + "time" + + "github.com/stretchr/testify/suite" ) type OrganizationsTestSuite struct { suite.Suite - testOrg *Organization client *AWX + service *OrganizationService } func TestProviders(t *testing.T) { suite.Run(t, &OrganizationsTestSuite{}) } -func (o *OrganizationsTestSuite) SetupTest() { - awxUser := "admin" - awxPassword := "password" - c := &http.Client{} - o.client = NewAWX("http://localhost", awxUser, awxPassword, c) - o.T().Logf("AWX: %+v", o.client) +func (suite *OrganizationsTestSuite) SetupAllSuite() { + rand.Seed(time.Now().UnixNano()) } -func (o *OrganizationsTestSuite) TestCreateOrganization() { - oc := o.client.OrganizationService - - data := map[string]interface{}{"name": "Testing", "description": "A Test organization"} +func (suite *OrganizationsTestSuite) SetupTest() { + suite.client = NewAWX("http://localhost", "admin", "password", &http.Client{}) + suite.service = suite.client.OrganizationService + suite.T().Logf("AWX: %+v", suite.client) +} - org, err := oc.CreateOrganization(data, map[string]string{}) - require.Nil(o.T(), err) - // Make sure that the org was created by making sure an ID was set - require.NotNil(o.T(), org.ID) - o.testOrg = org +func (suite *OrganizationsTestSuite) TestCreateDeleteOrganization() { + name := fmt.Sprintf("Testing-%v", rand.Int()) + org, err := suite.service.CreateOrganization(map[string]interface{}{ + "name": name, + "description": "A Test organization", + }, map[string]string{}) + suite.Nil(err) + suite.NotNil(org.ID) // Make sure that the org was created by making sure an ID was set + suite.Equal(org.Name, name) + org, err = suite.client.OrganizationService.DeleteOrganization(org.ID) + suite.Nil(err) } -func (o *OrganizationsTestSuite) TestListOrganizations() { - oc := o.client.OrganizationService +func (suite *OrganizationsTestSuite) TestUpdateOrganization() { + description := fmt.Sprintf("This is a test %v", time.Now().String()) + org, err := suite.service.UpdateOrganization(1, map[string]interface{}{ + "description": description, + }, map[string]string{}) + suite.Nil(err) + suite.Equal(org.Description, description) +} - org, _, err := oc.ListOrganizations(map[string]string{}) - require.Nil(o.T(), err) - // Make sure we get a non nil list back - require.NotEmpty(o.T(), org) - o.T().Logf("%+v", org) +func (suite *OrganizationsTestSuite) TestListOrganizations() { + org, _, err := suite.service.ListOrganizations(map[string]string{}) + suite.Nil(err) + suite.NotEmpty(org) + suite.Equal(org[0].Type, "organization") + suite.Equal(org[0].Name, "Default") + suite.T().Logf("%+v", org) } From 4d36858e35b46eebf773b68c27cc750abca64285 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Mon, 30 Mar 2020 14:58:59 +0200 Subject: [PATCH 09/14] Add script to run AWX using docker --- awxtesting/dockerized.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100755 awxtesting/dockerized.sh diff --git a/awxtesting/dockerized.sh b/awxtesting/dockerized.sh new file mode 100755 index 0000000..709d472 --- /dev/null +++ b/awxtesting/dockerized.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# Instantiate an AWX server using the AWX Installer: +# - This installer is powered by docker-composer +# - AWX will be available as http://localhost:80 + +rc=$(docker 2&>/dev/null; echo $?) +if [[ $rc -ne 0 ]]; then + echo "You MUST have docker installed" +fi + +git clone https://github.com/ansible/awx.git + +ansible-playbook -i awx/installer/inventory awx/installer/install.yml From 5f15387cc146e2b003bb49fe695ee87146ff2244 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Mon, 30 Mar 2020 17:02:29 +0200 Subject: [PATCH 10/14] Fix tests, disable the ones missing mock data --- awxtesting/mockserver/mockdata/inventories.go | 53 ++++----- credentials_test.go | 27 +++-- inventories_test.go | 94 +++++---------- job_template_test.go | 42 ++----- project_updates_test.go | 5 - projects_test.go | 66 +++++------ teams_test.go | 112 +++++++++--------- 7 files changed, 164 insertions(+), 235 deletions(-) diff --git a/awxtesting/mockserver/mockdata/inventories.go b/awxtesting/mockserver/mockdata/inventories.go index cf342ef..1b006fe 100644 --- a/awxtesting/mockserver/mockdata/inventories.go +++ b/awxtesting/mockserver/mockdata/inventories.go @@ -15,21 +15,21 @@ var ( "related": { "created_by": "/api/v2/users/1/", "modified_by": "/api/v2/users/1/", - "job_templates": "/api/v2/inventories/1/job_templates/", - "variable_data": "/api/v2/inventories/1/variable_data/", + "hosts": "/api/v2/inventories/1/hosts/", + "groups": "/api/v2/inventories/1/groups/", "root_groups": "/api/v2/inventories/1/root_groups/", - "object_roles": "/api/v2/inventories/1/object_roles/", - "ad_hoc_commands": "/api/v2/inventories/1/ad_hoc_commands/", + "variable_data": "/api/v2/inventories/1/variable_data/", "script": "/api/v2/inventories/1/script/", "tree": "/api/v2/inventories/1/tree/", - "access_list": "/api/v2/inventories/1/access_list/", + "inventory_sources": "/api/v2/inventories/1/inventory_sources/", + "update_inventory_sources": "/api/v2/inventories/1/update_inventory_sources/", "activity_stream": "/api/v2/inventories/1/activity_stream/", + "job_templates": "/api/v2/inventories/1/job_templates/", + "ad_hoc_commands": "/api/v2/inventories/1/ad_hoc_commands/", + "access_list": "/api/v2/inventories/1/access_list/", + "object_roles": "/api/v2/inventories/1/object_roles/", "instance_groups": "/api/v2/inventories/1/instance_groups/", - "hosts": "/api/v2/inventories/1/hosts/", - "groups": "/api/v2/inventories/1/groups/", "copy": "/api/v2/inventories/1/copy/", - "update_inventory_sources": "/api/v2/inventories/1/update_inventory_sources/", - "inventory_sources": "/api/v2/inventories/1/inventory_sources/", "organization": "/api/v2/organizations/1/" }, "summary_fields": { @@ -51,37 +51,37 @@ var ( "last_name": "" }, "object_roles": { - "use_role": { - "id": 23, - "description": "Can use the inventory in a job template", - "name": "Use" - }, "admin_role": { - "id": 21, "description": "Can manage all aspects of the inventory", - "name": "Admin" + "name": "Admin", + "id": 21 + }, + "update_role": { + "description": "May update project or inventory or group using the configured source update system", + "name": "Update", + "id": 24 }, "adhoc_role": { - "id": 20, "description": "May run ad hoc commands on an inventory", - "name": "Ad Hoc" + "name": "Ad Hoc", + "id": 20 }, - "update_role": { - "id": 24, - "description": "May update project or inventory or group using the configured source update system", - "name": "Update" + "use_role": { + "description": "Can use the inventory in a job template", + "name": "Use", + "id": 23 }, "read_role": { - "id": 22, "description": "May view settings for the inventory", - "name": "Read" + "name": "Read", + "id": 22 } }, "user_capabilities": { "edit": true, + "delete": true, "copy": true, - "adhoc": true, - "delete": true + "adhoc": true } }, "created": "2018-05-21T01:34:35.657185Z", @@ -96,7 +96,6 @@ var ( "total_hosts": 2, "hosts_with_active_failures": 0, "total_groups": 0, - "groups_with_active_failures": 0, "has_inventory_sources": false, "total_inventory_sources": 0, "inventory_sources_with_failures": 0, diff --git a/credentials_test.go b/credentials_test.go index a165670..5fc8dbc 100644 --- a/credentials_test.go +++ b/credentials_test.go @@ -1,5 +1,7 @@ package awx +// TODO Add mock data and then enable test +/* import ( "testing" "time" @@ -24,7 +26,7 @@ func TestListCredentials(t *testing.T) { ActivityStream: "/api/v2/credentials/1/activity_stream/", }, SummaryFields: &Summary{ - Organization: &OrgnizationSummary{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", @@ -37,17 +39,17 @@ func TestListCredentials(t *testing.T) { LastName: "", }, ObjectRoles: &ObjectRoles{ - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 18, Description: "Can manage all aspects of the credential", Name: "Admin", }, - UseRole: &ApplyRole{ + UseRole: &ObjectRole{ ID: 20, Description: "Can use the credential in a job template", Name: "Use", }, - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 19, Description: "May view settings for the credential", Name: "Read", @@ -109,7 +111,7 @@ func TestCreateCredentials(t *testing.T) { ActivityStream: "/api/v2/credentials/1/activity_stream/", }, SummaryFields: &Summary{ - Organization: &OrgnizationSummary{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", @@ -122,17 +124,17 @@ func TestCreateCredentials(t *testing.T) { LastName: "", }, ObjectRoles: &ObjectRoles{ - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 18, Description: "Can manage all aspects of the credential", Name: "Admin", }, - UseRole: &ApplyRole{ + UseRole: &ObjectRole{ ID: 20, Description: "Can use the credential in a job template", Name: "Use", }, - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 19, Description: "May view settings for the credential", Name: "Read", @@ -194,7 +196,7 @@ func TestUpdateCredentials(t *testing.T) { ActivityStream: "/api/v2/credentials/1/activity_stream/", }, SummaryFields: &Summary{ - Organization: &OrgnizationSummary{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", @@ -207,17 +209,17 @@ func TestUpdateCredentials(t *testing.T) { LastName: "", }, ObjectRoles: &ObjectRoles{ - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 18, Description: "Can manage all aspects of the credential", Name: "Admin", }, - UseRole: &ApplyRole{ + UseRole: &ObjectRole{ ID: 20, Description: "Can use the credential in a job template", Name: "Use", }, - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 19, Description: "May view settings for the credential", Name: "Read", @@ -280,3 +282,4 @@ func TestDeleteCredentials(t *testing.T) { t.Log("DeleteCredentials passed!") } } +*/ diff --git a/inventories_test.go b/inventories_test.go index 07bab1a..f96da20 100644 --- a/inventories_test.go +++ b/inventories_test.go @@ -33,58 +33,50 @@ func TestListInventories(t *testing.T) { Organization: "/api/v2/organizations/1/", }, SummaryFields: &Summary{ - Organization: &OrgnizationSummary{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", }, - CreatedBy: &ByUserSummary{ ID: 1, Username: "admin", FirstName: "", LastName: "", }, - ModifiedBy: &ByUserSummary{ ID: 1, Username: "admin", FirstName: "", LastName: "", }, - ObjectRoles: &ObjectRoles{ - UseRole: &ApplyRole{ - ID: 23, - Description: "Can use the inventory in a job template", - Name: "Use", - }, - - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 21, Description: "Can manage all aspects of the inventory", Name: "Admin", }, - - AdhocRole: &ApplyRole{ + UpdateRole: &ObjectRole{ + ID: 24, + Description: "May update project or inventory or group using the configured source update system", + Name: "Update", + }, + AdhocRole: &ObjectRole{ ID: 20, Description: "May run ad hoc commands on an inventory", Name: "Ad Hoc", }, - - UpdateRole: &ApplyRole{ - ID: 24, - Description: "May update project or inventory or group using the configured source update system", - Name: "Update", + UseRole: &ObjectRole{ + ID: 23, + Description: "Can use the inventory in a job template", + Name: "Use", }, - - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 22, Description: "May view settings for the inventory", Name: "Read", }, }, - UserCapabilities: &UserCapabilities{ Edit: true, Copy: true, @@ -164,58 +156,50 @@ func TestCreateInventory(t *testing.T) { Organization: "/api/v2/organizations/1/", }, SummaryFields: &Summary{ - Organization: &OrgnizationSummary{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", }, - CreatedBy: &ByUserSummary{ ID: 1, Username: "admin", FirstName: "", LastName: "", }, - ModifiedBy: &ByUserSummary{ ID: 1, Username: "admin", FirstName: "", LastName: "", }, - ObjectRoles: &ObjectRoles{ - UseRole: &ApplyRole{ + UseRole: &ObjectRole{ ID: 80, Description: "Can use the inventory in a job template", Name: "Use", }, - - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 78, Description: "Can manage all aspects of the inventory", Name: "Admin", }, - - AdhocRole: &ApplyRole{ + AdhocRole: &ObjectRole{ ID: 77, Description: "May run ad hoc commands on an inventory", Name: "Ad Hoc", }, - - UpdateRole: &ApplyRole{ + UpdateRole: &ObjectRole{ ID: 81, Description: "May update project or inventory or group using the configured source update system", Name: "Update", }, - - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 79, Description: "May view settings for the inventory", Name: "Read", }, }, - UserCapabilities: &UserCapabilities{ Edit: true, Copy: true, @@ -299,58 +283,50 @@ func TestUpdateInventory(t *testing.T) { Organization: "/api/v2/organizations/1/", }, SummaryFields: &Summary{ - Organization: &OrgnizationSummary{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", }, - CreatedBy: &ByUserSummary{ ID: 1, Username: "admin", FirstName: "", LastName: "", }, - ModifiedBy: &ByUserSummary{ ID: 1, Username: "admin", FirstName: "", LastName: "", }, - ObjectRoles: &ObjectRoles{ - UseRole: &ApplyRole{ + UseRole: &ObjectRole{ ID: 80, Description: "Can use the inventory in a job template", Name: "Use", }, - - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 78, Description: "Can manage all aspects of the inventory", Name: "Admin", }, - - AdhocRole: &ApplyRole{ + AdhocRole: &ObjectRole{ ID: 77, Description: "May run ad hoc commands on an inventory", Name: "Ad Hoc", }, - - UpdateRole: &ApplyRole{ + UpdateRole: &ObjectRole{ ID: 81, Description: "May update project or inventory or group using the configured source update system", Name: "Update", }, - - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 79, Description: "May view settings for the inventory", Name: "Read", }, }, - UserCapabilities: &UserCapabilities{ Edit: true, Copy: true, @@ -433,58 +409,50 @@ func TestGetInventory(t *testing.T) { Organization: "/api/v2/organizations/1/", }, SummaryFields: &Summary{ - Organization: &OrgnizationSummary{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", }, - CreatedBy: &ByUserSummary{ ID: 1, Username: "admin", FirstName: "", LastName: "", }, - ModifiedBy: &ByUserSummary{ ID: 1, Username: "admin", FirstName: "", LastName: "", }, - ObjectRoles: &ObjectRoles{ - UseRole: &ApplyRole{ + UseRole: &ObjectRole{ ID: 80, Description: "Can use the inventory in a job template", Name: "Use", }, - - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 78, Description: "Can manage all aspects of the inventory", Name: "Admin", }, - - AdhocRole: &ApplyRole{ + AdhocRole: &ObjectRole{ ID: 77, Description: "May run ad hoc commands on an inventory", Name: "Ad Hoc", }, - - UpdateRole: &ApplyRole{ + UpdateRole: &ObjectRole{ ID: 81, Description: "May update project or inventory or group using the configured source update system", Name: "Update", }, - - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 79, Description: "May view settings for the inventory", Name: "Read", }, }, - UserCapabilities: &UserCapabilities{ Edit: true, Copy: true, diff --git a/job_template_test.go b/job_template_test.go index ea6512e..238d618 100644 --- a/job_template_test.go +++ b/job_template_test.go @@ -50,7 +50,6 @@ func TestListJobTemplates(t *testing.T) { OrganizationID: 1, Kind: "", }, - Project: &Project{ ID: 4, Name: "Demo Project", @@ -58,41 +57,35 @@ func TestListJobTemplates(t *testing.T) { Status: "never updated", ScmType: "git", }, - CreatedBy: &ByUserSummary{ ID: 1, Username: "admin", FirstName: "", LastName: "", }, - ModifiedBy: &ByUserSummary{ ID: 1, Username: "admin", FirstName: "", LastName: "", }, - ObjectRoles: &ObjectRoles{ - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 27, Description: "Can manage all aspects of the job template", Name: "Admin", }, - - ExecuteRole: &ApplyRole{ + ExecuteRole: &ObjectRole{ ID: 26, Description: "May run the job template", Name: "Execute", }, - - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 25, Description: "May view settings for the job template", Name: "Read", }, }, - UserCapabilities: &UserCapabilities{ Edit: true, Start: true, @@ -100,14 +93,11 @@ func TestListJobTemplates(t *testing.T) { Schedule: true, Delete: true, }, - Labels: &Labels{ Count: 0, Results: []interface{}{}, }, - RecentJobs: []interface{}{}, - Credentials: []Credential{ { Description: "", @@ -211,14 +201,12 @@ func TestLauchJob(t *testing.T) { CreateSchedule: "/api/v2/jobs/499/create_schedule/", Relaunch: "/api/v2/jobs/499/relaunch/", }, - SummaryFields: &Summary{ JobTemplate: &JobTemplateSummary{ ID: 5, Name: "Demo Job Template", Description: "", }, - Inventory: &Inventory{ ID: 1, Name: "Demo Inventory", @@ -234,7 +222,6 @@ func TestLauchJob(t *testing.T) { OrganizationID: 1, Kind: "", }, - Credential: &Credential{ Description: "", CredentialTypeID: 1, @@ -242,14 +229,12 @@ func TestLauchJob(t *testing.T) { Kind: "ssh", Name: "Demo Credential", }, - UnifiedJobTemplate: &UnifiedJobTemplate{ ID: 5, Name: "Demo Job Template", Description: "", UnifiedJobType: "job", }, - Project: &Project{ ID: 4, Name: "Demo Project", @@ -257,31 +242,26 @@ func TestLauchJob(t *testing.T) { Status: "successful", ScmType: "git", }, - CreatedBy: &ByUserSummary{ ID: 1, Username: "admin", FirstName: "", LastName: "", }, - ModifiedBy: &ByUserSummary{ ID: 1, Username: "admin", FirstName: "", LastName: "", }, - UserCapabilities: &UserCapabilities{ Start: true, Delete: true, }, - Labels: &Labels{ Count: 0, Results: []interface{}{}, }, - ExtraCredentials: []interface{}{}, Credentials: []Credential{ { @@ -356,8 +336,8 @@ func TestLauchJob(t *testing.T) { ) awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) - result, err := awx.JobTemplateService.Launch(testJobTemplateID, map[string]interface{}{ - "inventory": testInventoryID, + result, err := awx.JobTemplateService.Launch(testJobTemplateID, &JobLaunchOpts{ + Inventory: testInventoryID, }, map[string]string{}) if err != nil { @@ -432,17 +412,17 @@ func TestCreateJobTemplate(t *testing.T) { LastName: "", }, ObjectRoles: &ObjectRoles{ - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 28, Description: "Can manage all aspects of the job template", Name: "Admin", }, - ExecuteRole: &ApplyRole{ + ExecuteRole: &ObjectRole{ ID: 27, Description: "May run the job template", Name: "Execute", }, - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 26, Description: "May view settings for the job template", Name: "Read", @@ -595,17 +575,17 @@ func TestUpdateJobTemplate(t *testing.T) { LastName: "", }, ObjectRoles: &ObjectRoles{ - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 28, Description: "Can manage all aspects of the job template", Name: "Admin", }, - ExecuteRole: &ApplyRole{ + ExecuteRole: &ObjectRole{ ID: 27, Description: "May run the job template", Name: "Execute", }, - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 26, Description: "May view settings for the job template", Name: "Read", diff --git a/project_updates_test.go b/project_updates_test.go index 3f10bb3..31bc70e 100644 --- a/project_updates_test.go +++ b/project_updates_test.go @@ -52,13 +52,11 @@ func TestProjectUpdateGet(t *testing.T) { ID: 1, Name: "tower", }, - JobTemplate: &JobTemplateSummary{ ID: 8, Name: "Hello-world", Description: "", }, - Inventory: &Inventory{ ID: 1, Name: "Demo Inventory", @@ -74,7 +72,6 @@ func TestProjectUpdateGet(t *testing.T) { OrganizationID: 1, Kind: "", }, - ProjectUpdate: &ProjectUpdate{ ID: 303, Name: "DeployBook", @@ -82,14 +79,12 @@ func TestProjectUpdateGet(t *testing.T) { Status: "successful", Failed: false, }, - UnifiedJobTemplate: &UnifiedJobTemplate{ ID: 8, Description: "", Name: "Hello-world", UnifiedJobType: "job", }, - Project: &Project{ ID: 6, Name: "DeployBook", diff --git a/projects_test.go b/projects_test.go index da7076e..bb9bb2f 100644 --- a/projects_test.go +++ b/projects_test.go @@ -22,7 +22,7 @@ func TestListProjects(t *testing.T) { Organization: "/api/v2/organizations/1/", }, SummaryFields: &Summary{ - Organization: &OrgnizationSummary{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", @@ -40,31 +40,27 @@ func TestListProjects(t *testing.T) { LastName: "admin", }, ObjectRoles: &ObjectRoles{ - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 14, Description: "Can manage all aspects of the project", Name: "Admin", }, - - UseRole: &ApplyRole{ - ID: 16, - Description: "Can manage all aspects of the project", - Name: "Use", - }, - - UpdateRole: &ApplyRole{ + UpdateRole: &ObjectRole{ ID: 17, Description: "May update project or inventory or group using the configured source update system", Name: "Update", }, - - ReadRole: &ApplyRole{ + UseRole: &ObjectRole{ + ID: 16, + Description: "Can manage all aspects of the project", + Name: "Use", + }, + ReadRole: &ObjectRole{ ID: 15, Description: "May view settings for the project", Name: "Read", }, }, - UserCapabilities: &UserCapabilities{ Edit: true, Start: true, @@ -127,7 +123,7 @@ func TestCreateProject(t *testing.T) { Organization: "/api/v2/organizations/1/", }, SummaryFields: &Summary{ - Organization: &OrgnizationSummary{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", @@ -145,31 +141,27 @@ func TestCreateProject(t *testing.T) { LastName: "admin", }, ObjectRoles: &ObjectRoles{ - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 14, Description: "Can manage all aspects of the project", Name: "Admin", }, - - UseRole: &ApplyRole{ - ID: 16, - Description: "Can manage all aspects of the project", - Name: "Use", - }, - - UpdateRole: &ApplyRole{ + UpdateRole: &ObjectRole{ ID: 17, Description: "May update project or inventory or group using the configured source update system", Name: "Update", }, - - ReadRole: &ApplyRole{ + UseRole: &ObjectRole{ + ID: 16, + Description: "Can manage all aspects of the project", + Name: "Use", + }, + ReadRole: &ObjectRole{ ID: 15, Description: "May view settings for the project", Name: "Read", }, }, - UserCapabilities: &UserCapabilities{ Edit: true, Start: true, @@ -234,7 +226,7 @@ func TestUpdateProject(t *testing.T) { Organization: "/api/v2/organizations/1/", }, SummaryFields: &Summary{ - Organization: &OrgnizationSummary{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", @@ -252,31 +244,27 @@ func TestUpdateProject(t *testing.T) { LastName: "admin", }, ObjectRoles: &ObjectRoles{ - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 14, Description: "Can manage all aspects of the project", Name: "Admin", }, - - UseRole: &ApplyRole{ - ID: 16, - Description: "Can manage all aspects of the project", - Name: "Use", - }, - - UpdateRole: &ApplyRole{ + UpdateRole: &ObjectRole{ ID: 17, Description: "May update project or inventory or group using the configured source update system", Name: "Update", }, - - ReadRole: &ApplyRole{ + UseRole: &ObjectRole{ + ID: 16, + Description: "Can manage all aspects of the project", + Name: "Use", + }, + ReadRole: &ObjectRole{ ID: 15, Description: "May view settings for the project", Name: "Read", }, }, - UserCapabilities: &UserCapabilities{ Edit: true, Start: true, diff --git a/teams_test.go b/teams_test.go index 7d43945..2f79d26 100644 --- a/teams_test.go +++ b/teams_test.go @@ -1,5 +1,7 @@ package awx +// TODO Add mock data and then enable test +/* import ( "testing" "time" @@ -15,56 +17,54 @@ func TestListTeams(t *testing.T) { Related: &Related{ CreatedBy: "/api/v2/users/4/", ModifiedBy: "/api/v2/users/4/", + Projects: "/api/v2/teams/1/projects/", Users: "/api/v2/teams/1/users/", + Credentials: "/api/v2/teams/1/credentials/", Roles: "/api/v2/teams/1/roles/", ObjectRoles: "/api/v2/teams/1/object_roles/", - Credentials: "/api/v2/teams/1/credentials/", - Projects: "/api/v2/teams/1/projects/", ActivityStream: "/api/v2/teams/1/activity_stream/", AccessList: "/api/v2/teams/1/access_list/", Organization: "/api/v2/organizations/1/", }, - SummaryFields: &Summary{ - UserCapabilities: &UserCapabilities{ - Edit: true, - Delete: true, - }, - Organization: &OrgnizationSummary{ + SummaryFields: &SummaryFields{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", }, + CreatedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, + ModifiedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, + UserCapabilities: &UserCapabilities{ + Edit: true, + Delete: true, + }, ObjectRoles: &ObjectRoles{ - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 30, Description: "Can manage all aspects of the team", Name: "Admin", }, - - MemberRole: &ApplyRole{ + MemberRole: &ObjectRole{ ID: 29, Description: "User is a member of the team", Name: "Member", }, - - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 31, Description: "May view settings for the team", Name: "Read", }, }, - CreatedBy: &ByUserSummary{ - ID: 4, - Username: "admin", - FirstName: "", - LastName: "", - }, - ModifiedBy: &ByUserSummary{ - ID: 4, - Username: "admin", - FirstName: "", - LastName: "", - }, }, Created: func() time.Time { t, _ := time.Parse(time.RFC3339, "2018-12-01T13:33:30.692904Z") @@ -112,30 +112,28 @@ func TestCreateTeam(t *testing.T) { AccessList: "/api/v2/teams/1/access_list/", Organization: "/api/v2/organizations/1/", }, - SummaryFields: &Summary{ + SummaryFields: &SummaryFields{ UserCapabilities: &UserCapabilities{ Edit: true, Delete: true, }, - Organization: &OrgnizationSummary{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", }, ObjectRoles: &ObjectRoles{ - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 30, Description: "Can manage all aspects of the team", Name: "Admin", }, - - MemberRole: &ApplyRole{ + MemberRole: &ObjectRole{ ID: 29, Description: "User is a member of the team", Name: "Member", }, - - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 31, Description: "May view settings for the team", Name: "Read", @@ -190,55 +188,53 @@ func TestUpdateTeam(t *testing.T) { Related: &Related{ CreatedBy: "/api/v2/users/4/", ModifiedBy: "/api/v2/users/4/", + Projects: "/api/v2/teams/1/projects/", Users: "/api/v2/teams/1/users/", + Credentials: "/api/v2/teams/1/credentials/", Roles: "/api/v2/teams/1/roles/", ObjectRoles: "/api/v2/teams/1/object_roles/", - Credentials: "/api/v2/teams/1/credentials/", - Projects: "/api/v2/teams/1/projects/", ActivityStream: "/api/v2/teams/1/activity_stream/", AccessList: "/api/v2/teams/1/access_list/", Organization: "/api/v2/organizations/1/", }, - SummaryFields: &Summary{ - UserCapabilities: &UserCapabilities{ - Edit: true, - Delete: true, - }, - Organization: &OrgnizationSummary{ + SummaryFields: &SummaryFields{ + Organization: &OrganizationSummary{ ID: 1, Name: "Default", Description: "", }, + CreatedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, + ModifiedBy: &ByUserSummary{ + ID: 4, + Username: "admin", + FirstName: "", + LastName: "", + }, ObjectRoles: &ObjectRoles{ - AdminRole: &ApplyRole{ + AdminRole: &ObjectRole{ ID: 30, Description: "Can manage all aspects of the team", Name: "Admin", }, - - MemberRole: &ApplyRole{ + MemberRole: &ObjectRole{ ID: 29, Description: "User is a member of the team", Name: "Member", }, - - ReadRole: &ApplyRole{ + ReadRole: &ObjectRole{ ID: 31, Description: "May view settings for the team", Name: "Read", }, }, - CreatedBy: &ByUserSummary{ - ID: 4, - Username: "admin", - FirstName: "", - LastName: "", - }, - ModifiedBy: &ByUserSummary{ - ID: 4, - Username: "admin", - FirstName: "", - LastName: "", + UserCapabilities: &UserCapabilities{ + Edit: true, + Delete: true, }, }, Created: func() time.Time { @@ -261,6 +257,7 @@ func TestUpdateTeam(t *testing.T) { "organization": 1, "description": "Update test-team", }, map[string]string{}) + if err != nil { t.Fatalf("CreateTeam err: %s", err) } else { @@ -285,7 +282,6 @@ func TestDeleteTeam(t *testing.T) { } func TestTeamGrantRole(t *testing.T) { - awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) err := awx.TeamService.GrantRole(4, 170) @@ -298,7 +294,6 @@ func TestTeamGrantRole(t *testing.T) { } func TestTeamRevokeRole(t *testing.T) { - awx := NewAWX(testAwxHost, testAwxUserName, testAwxPasswd, nil) err := awx.TeamService.RevokeRole(1, 170) @@ -309,3 +304,4 @@ func TestTeamRevokeRole(t *testing.T) { t.Log("TestTeamRevokeRole passed!") } } +*/ From 713d9cb87cbfaccaf94a0c22211b8c6f64eaddcf Mon Sep 17 00:00:00 2001 From: David Fischer Date: Mon, 30 Mar 2020 17:03:00 +0200 Subject: [PATCH 11/14] Require integration flag to run integration tests --- organizations_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/organizations_test.go b/organizations_test.go index 5afec07..16633ec 100644 --- a/organizations_test.go +++ b/organizations_test.go @@ -1,3 +1,5 @@ +// +build integration + package awx import ( From aaa09cc4c923bf4fb05beacafa4c775d7ec61217 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Mon, 30 Mar 2020 17:08:43 +0200 Subject: [PATCH 12/14] Cleanup types --- types.go | 114 +++++++++++-------------------------------------------- 1 file changed, 23 insertions(+), 91 deletions(-) diff --git a/types.go b/types.go index 8dc8665..082a416 100644 --- a/types.go +++ b/types.go @@ -112,31 +112,30 @@ type InstanceGroupSummary struct { Description string `json:"description"` } -// ApplyRole represents the awx api apply role. -type ApplyRole struct { +// ObjectRoles represents the awx api object roles. +type ObjectRoles struct { + UseRole *ObjectRole `json:"use_role"` + AdminRole *ObjectRole `json:"admin_role"` + AdhocRole *ObjectRole `json:"adhoc_role"` + UpdateRole *ObjectRole `json:"update_role"` + ReadRole *ObjectRole `json:"read_role"` + ExecuteRole *ObjectRole `json:"execute_role"` + MemberRole *ObjectRole `json:"member_role"` + NotificationAdminRole *ObjectRole `json:"notification_admin_role"` + WorkflowAdminRole *ObjectRole `json:"workflow_admin_role"` + CredentialAdminRole *ObjectRole `json:"credential_admin_role"` + JobTemplateAdminRole *ObjectRole `json:"job_template_admin_role"` + ProjectAdminRole *ObjectRole `json:"project_admin_role"` + AuditorRole *ObjectRole `json:"auditor_role"` + InventoryAdminRole *ObjectRole `json:"inventory_admin_role"` +} + +type ObjectRole struct { ID int `json:"id"` Name string `json:"name"` Description string `json:"description"` } -// ObjectRoles represents the awx api object roles. -type ObjectRoles struct { - UseRole *ApplyRole `json:"use_role"` - AdminRole *ApplyRole `json:"admin_role"` - AdhocRole *ApplyRole `json:"adhoc_role"` - UpdateRole *ApplyRole `json:"update_role"` - ReadRole *ApplyRole `json:"read_role"` - ExecuteRole *ApplyRole `json:"execute_role"` - MemberRole *MemberRole `json:"member_role"` - NotificationAdminRole *NotificationAdminRole `json:"notification_admin_role"` - WorkflowAdminRole *WorkflowAdminRole `json:"workflow_admin_role"` - CredentialAdminRole *CredentialAdminRole `json:"credential_admin_role"` - JobTemplateAdminRole *JobTemplateAdminRole `json:"job_template_admin_role"` - ProjectAdminRole *ProjectAdminRole `json:"project_admin_role"` - AuditorRole *AuditorRole `json:"auditor_role"` - InventoryAdminRole *InventoryAdminRole `json:"inventory_admin_role"` -} - // UserCapabilities represents the awx api user capabilities. type UserCapabilities struct { Edit bool `json:"edit"` @@ -156,7 +155,7 @@ type Labels struct { // Summary represents the awx api summary fields. type Summary struct { InstanceGroup *InstanceGroupSummary `json:"instance_group"` - Organization *OrgnizationSummary `json:"organization"` + Organization *OrganizationSummary `json:"organization"` CreatedBy *ByUserSummary `json:"created_by"` ModifiedBy *ByUserSummary `json:"modified_by"` ObjectRoles *ObjectRoles `json:"object_roles"` @@ -709,74 +708,6 @@ type Team struct { Organization int `json:"organization"` } -type CreatedBy struct { - ID int `json:"id"` - Username string `json:"username"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` -} -type ModifiedBy struct { - ID int `json:"id"` - Username string `json:"username"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` -} -type AdminRole struct { - ID int `json:"id"` - Description string `json:"description"` - Name string `json:"name"` -} -type ReadRole struct { - ID int `json:"id"` - Description string `json:"description"` - Name string `json:"name"` -} -type MemberRole struct { - ID int `json:"id"` - Description string `json:"description"` - Name string `json:"name"` -} -type ExecuteRole struct { - ID int `json:"id"` - Description string `json:"description"` - Name string `json:"name"` -} -type NotificationAdminRole struct { - ID int `json:"id"` - Description string `json:"description"` - Name string `json:"name"` -} -type WorkflowAdminRole struct { - ID int `json:"id"` - Description string `json:"description"` - Name string `json:"name"` -} -type CredentialAdminRole struct { - ID int `json:"id"` - Description string `json:"description"` - Name string `json:"name"` -} -type JobTemplateAdminRole struct { - ID int `json:"id"` - Description string `json:"description"` - Name string `json:"name"` -} -type ProjectAdminRole struct { - ID int `json:"id"` - Description string `json:"description"` - Name string `json:"name"` -} -type AuditorRole struct { - ID int `json:"id"` - Description string `json:"description"` - Name string `json:"name"` -} -type InventoryAdminRole struct { - ID int `json:"id"` - Description string `json:"description"` - Name string `json:"name"` -} - type RelatedFieldCounts struct { JobTemplates int `json:"job_templates"` Users int `json:"users"` @@ -785,9 +716,10 @@ type RelatedFieldCounts struct { Inventories int `json:"inventories"` Projects int `json:"projects"` } + type SummaryFields struct { - CreatedBy CreatedBy `json:"created_by"` - ModifiedBy ModifiedBy `json:"modified_by"` + CreatedBy ByUserSummary `json:"created_by"` + ModifiedBy ByUserSummary `json:"modified_by"` ObjectRoles ObjectRoles `json:"object_roles"` UserCapabilities UserCapabilities `json:"user_capabilities"` RelatedFieldCounts RelatedFieldCounts `json:"related_field_counts"` From f84c379840951d0dabe6f74534e3e37ad3857fd8 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Mon, 30 Mar 2020 17:11:28 +0200 Subject: [PATCH 13/14] Add make test-integration --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index c6a0552..5948dbe 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,10 @@ test: install-test-reqs @echo ">> running all tests" @$(GO) test $(pkgs) +test-integration: install-test-reqs + @echo ">> running integration tests" + @$(GO) test -tags=integration $(pkgs) + lint: install-test-reqs @gometalinter --vendor --disable-all --enable=gosimple --enable=golint --enable=vet --enable=ineffassign --enable=unconvert \ --exclude="by other packages, and that stutters; consider calling this" \ From 8cc3a8e381337af1cb3a0689bae2fd9c0151a534 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Tue, 31 Mar 2020 08:41:49 +0200 Subject: [PATCH 14/14] Fix typo --- types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types.go b/types.go index 082a416..ee04622 100644 --- a/types.go +++ b/types.go @@ -83,8 +83,8 @@ type Related struct { Callback string `json:"callback"` } -// OrgnizationSummary represents the awx api orgnization summary fields. -type OrgnizationSummary struct { +// OrganizationSummary represents the awx api organization summary fields. +type OrganizationSummary struct { ID int `json:"id"` Name string `json:"name"` Description string `json:"description"`