Skip to content

Commit

Permalink
Handle notifications only if quay.io repository exists (#165)
Browse files Browse the repository at this point in the history
In same rare corner case, can happen that ImageRepository exists with
finalizer, but quay.io repository was removed for some reason,
in such case it shouldn't be trying to add notifications for
non-existing repository

STONEBLD-3195

Signed-off-by: Robert Cerven <[email protected]>
  • Loading branch information
rcerven authored Jan 31, 2025
1 parent 25aad38 commit b52cfee
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 6 deletions.
6 changes: 6 additions & 0 deletions controllers/imagerepository_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,9 @@ var _ = Describe("Image repository controller", func() {
})

assertProvisionRepository := func(updateComponentAnnotation, grantRepoPermission bool) {
quay.RepositoryExistsFunc = func(organization, imageRepository string) (bool, error) {
return true, nil
}
isCreateRepositoryInvoked := false
quay.CreateRepositoryFunc = func(repository quay.RepositoryRequest) (*quay.Repository, error) {
defer GinkgoRecover()
Expand Down Expand Up @@ -754,6 +757,9 @@ var _ = Describe("Image repository controller", func() {
// Wait just for case it takes less than a second to regenerate credentials
time.Sleep(time.Second)

quay.RepositoryExistsFunc = func(organization, imageRepository string) (bool, error) {
return true, nil
}
isRegenerateRobotAccountTokenForPushInvoked := false
isRegenerateRobotAccountTokenForPullInvoked := false
quay.RegenerateRobotAccountTokenFunc = func(organization, robotName string) (*quay.RobotAccount, error) {
Expand Down
6 changes: 6 additions & 0 deletions controllers/imagerepository_notifications.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ func (r *ImageRepositoryReconciler) HandleNotifications(ctx context.Context, ima
return nil
}

repositoryExists, _ := r.QuayClient.RepositoryExists(r.QuayOrganization, imageRepository.Spec.Image.Name)
if !repositoryExists {
log.Info("repository does not exist, skipping handling notifications", "organization", r.QuayOrganization, "repository", imageRepository.Spec.Image.Name)
return nil
}

log.Info("Starting to handle notifications")
for _, notification := range imageRepository.Spec.Notifications {
existsInStatus := false
Expand Down
5 changes: 3 additions & 2 deletions pkg/quay/quay.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
type QuayService interface {
CreateRepository(repositoryRequest RepositoryRequest) (*Repository, error)
DeleteRepository(organization, imageRepository string) (bool, error)
RepositoryExists(organization, imageRepository string) (bool, error)
ChangeRepositoryVisibility(organization, imageRepository, visibility string) error
GetRobotAccount(organization string, robotName string) (*RobotAccount, error)
CreateRobotAccount(organization string, robotName string) (*RobotAccount, error)
Expand Down Expand Up @@ -148,8 +149,8 @@ func (c *QuayClient) CreateRepository(repositoryRequest RepositoryRequest) (*Rep
return data, nil
}

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

resp, err := c.doRequest(url, http.MethodGet, nil)
Expand Down
4 changes: 2 additions & 2 deletions pkg/quay/quay_debug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ func TestCreateRepository(t *testing.T) {
}
}

func TestDoesRepositoryExist(t *testing.T) {
func TestRepositoryExists(t *testing.T) {
if quayToken == "" {
return
}
quayClient := NewQuayClient(&http.Client{Transport: &http.Transport{}}, quayToken, quayApiUrl)
exists, err := quayClient.DoesRepositoryExist(quayOrgName, quayImageRepoName)
exists, err := quayClient.RepositoryExists(quayOrgName, quayImageRepoName)
if exists == true && err == nil {
t.Log("Repository exists")
} else if exists == false && strings.Contains(err.Error(), "does not exist") {
Expand Down
4 changes: 2 additions & 2 deletions pkg/quay/quay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1228,7 +1228,7 @@ func TestQuayClient_DeleteTag(t *testing.T) {
}
}

func TestQuayClient_DoesRepositoryExist(t *testing.T) {
func TestQuayClient_RepositoryExists(t *testing.T) {
client := &http.Client{Transport: &http.Transport{}}
gock.InterceptClient(client)

Expand Down Expand Up @@ -1302,7 +1302,7 @@ func TestQuayClient_DoesRepositoryExist(t *testing.T) {
}

quayClient := NewQuayClient(client, "authtoken", testQuayApiUrl)
exists, err := quayClient.DoesRepositoryExist(org, repo)
exists, err := quayClient.RepositoryExists(org, repo)
assert.Equal(t, tc.shouldExist, exists)
if tc.expectedErr == "" {
assert.NilError(t, err)
Expand Down
10 changes: 10 additions & 0 deletions pkg/quay/test_quay_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var _ QuayService = (*TestQuayClient)(nil)
var (
CreateRepositoryFunc func(repository RepositoryRequest) (*Repository, error)
DeleteRepositoryFunc func(organization, imageRepository string) (bool, error)
RepositoryExistsFunc func(organization, imageRepository string) (bool, error)
ChangeRepositoryVisibilityFunc func(organization, imageRepository string, visibility string) error
GetRobotAccountFunc func(organization string, robotName string) (*RobotAccount, error)
CreateRobotAccountFunc func(organization string, robotName string) (*RobotAccount, error)
Expand All @@ -55,6 +56,7 @@ var (
func ResetTestQuayClient() {
CreateRepositoryFunc = func(repository RepositoryRequest) (*Repository, error) { return &Repository{}, nil }
DeleteRepositoryFunc = func(organization, imageRepository string) (bool, error) { return true, nil }
RepositoryExistsFunc = func(organization, imageRepository string) (bool, error) { return true, nil }
ChangeRepositoryVisibilityFunc = func(organization, imageRepository string, visibility string) error { return nil }
GetRobotAccountFunc = func(organization, robotName string) (*RobotAccount, error) { return &RobotAccount{}, nil }
CreateRobotAccountFunc = func(organization, robotName string) (*RobotAccount, error) { return &RobotAccount{}, nil }
Expand Down Expand Up @@ -92,6 +94,11 @@ func ResetTestQuayClientToFails() {
Fail("DeleteRepository invoked")
return true, nil
}
RepositoryExistsFunc = func(organization, imageRepository string) (bool, error) {
defer GinkgoRecover()
Fail("RepositoryExists invoked")
return true, nil
}
ChangeRepositoryVisibilityFunc = func(organization, imageRepository string, visibility string) error {
defer GinkgoRecover()
Fail("ChangeRepositoryVisibility invoked")
Expand Down Expand Up @@ -190,6 +197,9 @@ func (c TestQuayClient) CreateRepository(repositoryRequest RepositoryRequest) (*
func (c TestQuayClient) DeleteRepository(organization, imageRepository string) (bool, error) {
return DeleteRepositoryFunc(organization, imageRepository)
}
func (c TestQuayClient) RepositoryExists(organization, imageRepository string) (bool, error) {
return RepositoryExistsFunc(organization, imageRepository)
}
func (TestQuayClient) ChangeRepositoryVisibility(organization, imageRepository string, visibility string) error {
return ChangeRepositoryVisibilityFunc(organization, imageRepository, visibility)
}
Expand Down

0 comments on commit b52cfee

Please sign in to comment.