Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added function to check if imageRepo is public #54

Merged
merged 1 commit into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions pkg/quay/quay.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,56 @@
return false, errors.New(data.ErrorMessage)
}

// IsRepositoryPublic checks if the specified image repository has visibility public in quay.
func (c *QuayClient) IsRepositoryPublic(organization, imageRepository string) (bool, error) {
url := fmt.Sprintf("%s/repository/%s/%s", c.url, organization, imageRepository)

req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return false, fmt.Errorf("failed to create request: %w", err)
}

Check warning on line 149 in pkg/quay/quay.go

View check run for this annotation

Codecov / codecov/patch

pkg/quay/quay.go#L148-L149

Added lines #L148 - L149 were not covered by tests
req.Header.Add("Authorization", fmt.Sprintf("%s %s", "Bearer", c.AuthToken))
req.Header.Add("Content-Type", "application/json")

res, err := c.httpClient.Do(req)
if err != nil {
return false, fmt.Errorf("failed to Do request: %w", err)
}

Check warning on line 156 in pkg/quay/quay.go

View check run for this annotation

Codecov / codecov/patch

pkg/quay/quay.go#L155-L156

Added lines #L155 - L156 were not covered by tests
defer res.Body.Close()

if res.StatusCode == 404 {
return false, fmt.Errorf("repository %s does not exist in %s organization", imageRepository, organization)
}

if res.StatusCode == 200 {
body, _ := io.ReadAll(res.Body)
repo := &Repository{}
err := json.Unmarshal(body, repo)
if err != nil {
return false, fmt.Errorf("failed to unmarshal response body: %w", err)
}

Check warning on line 169 in pkg/quay/quay.go

View check run for this annotation

Codecov / codecov/patch

pkg/quay/quay.go#L168-L169

Added lines #L168 - L169 were not covered by tests
if repo.IsPublic {
return true, nil
} else {
return false, nil
}
}

body, err := io.ReadAll(res.Body)
if err != nil {
return false, fmt.Errorf("failed to read response body: %w", err)
}
data := &QuayError{}
err = json.Unmarshal(body, data)
if err != nil {
return false, fmt.Errorf("failed to unmarshal response body: %w", err)
}
if data.Error != "" {
return false, errors.New(data.Error)
}
return false, errors.New(data.ErrorMessage)

Check warning on line 189 in pkg/quay/quay.go

View check run for this annotation

Codecov / codecov/patch

pkg/quay/quay.go#L177-L189

Added lines #L177 - L189 were not covered by tests
}

// DeleteRepository deletes specified image repository.
func (c *QuayClient) DeleteRepository(organization, imageRepository string) (bool, error) {
url := fmt.Sprintf("%s/repository/%s/%s", c.url, organization, imageRepository)
Expand Down
15 changes: 15 additions & 0 deletions pkg/quay/quay_debug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,21 @@ func TestDeleteRepository(t *testing.T) {
}
}

func TestIsRepositoryPublic(t *testing.T) {
if quayToken == "" {
return
}
quayClient := NewQuayClient(&http.Client{Transport: &http.Transport{}}, quayToken, quayApiUrl)
isPublic, err := quayClient.IsRepositoryPublic(quayOrgName, quayImageRepoName)
if isPublic && err == nil {
t.Log("Repository is public")
} else if isPublic == false && err == nil {
t.Log("Repository is private")
} else {
t.Fatalf("Unexpected error: %s\n", err.Error())
}
}

func TestChangeRepositoryVisibility(t *testing.T) {
if quayToken == "" {
return
Expand Down
59 changes: 59 additions & 0 deletions pkg/quay/quay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,65 @@ func TestQuayClient_DoesRepositoryExist(t *testing.T) {
}
}

func TestQuayClient_IsRepositoryPublic(t *testing.T) {
defer gock.Off()

client := &http.Client{Transport: &http.Transport{}}
gock.InterceptClient(client)

quayClient := NewQuayClient(client, "authtoken", "https://quay.io/api/v1")

testCases := []struct {
name string
isPublic bool
err error
statusCode int
response []byte
}{
{
name: "Repository is public",
isPublic: true,
err: nil,
statusCode: 200,
response: []byte(`{"namespace": "test_org", "name": "test_repo", "kind": "image", "description": "Test repository", "is_public": true, "is_organization": true, "is_starred": false, "status_token": "", "trust_enabled": false, "tag_expiration_s": 1209600, "is_free_account": false, "state": "NORMAL", "tags": {}, "can_write": true, "can_admin": true}`),
},
{
name: "Repository is private",
isPublic: false,
err: nil,
statusCode: 200,
response: []byte(`{"namespace": "test_org", "name": "test_repo", "kind": "image", "description": "Test repository", "is_public": false, "is_organization": true, "is_starred": false, "status_token": "", "trust_enabled": false, "tag_expiration_s": 1209600, "is_free_account": false, "state": "NORMAL", "tags": {}, "can_write": true, "can_admin": true}`),
},
{
name: "Repository does not exist",
isPublic: false,
err: fmt.Errorf("repository %s does not exist in %s organization", repo, org),
statusCode: 404,
response: []byte(`{"detail": "Not Found", "error_message": "Not Found", "error_type": "not_found", "title": "not_found", "type": "https://quay.io/api/v1/error/not_found", "status": 404}`),
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
gock.New("https://quay.io/api/v1").
MatchHeader("Content-Type", "application/json").
MatchHeader("Authorization", "Bearer authtoken").
Get(fmt.Sprintf("repository/%s/%s", org, repo)).
Reply(tc.statusCode).
JSON(tc.response)

isPublic, err := quayClient.IsRepositoryPublic(org, repo)
if isPublic != tc.isPublic {
t.Errorf("expected result to be `%t`, got `%t`", tc.isPublic, isPublic)
}
if (tc.err != nil && err == nil) || (tc.err == nil && err != nil) {
t.Errorf("expected error to be `%v`, got `%v`", tc.err, err)
}

})
}
}

func TestQuayClient_DeleteRepository(t *testing.T) {
defer gock.Off()

Expand Down