From d0f1208db96c99d59d7362231a9cea8e1f10439b Mon Sep 17 00:00:00 2001 From: Ross Bryan Date: Tue, 27 Feb 2024 15:42:21 -0500 Subject: [PATCH] fix: nil check http response when err is not nil (PROJQUAY-6620) Topic: projquay-6620 The operator was panicking due to the httpResponse being nil and attempting to return the httpResponse.StatusCode in the response; the response was most likely nil due to a prior error when attempting to marshal json and build the http request itself. This now allows the error to be propagated out to the logs instead of causing the operator to panic Signed-off-by: Ross Bryan fix: addtl nil checking http responses (PROJQUAY-6620) chore: lint_controllers (PROJQUAY-6620) chore: lint quay client (PROJQUAY-6620) Signed-off-by: Ross Bryan --- controllers/build_controller.go | 17 ---- controllers/namespace_controller.go | 100 +++++++--------------- controllers/quayintegration_controller.go | 5 +- pkg/client/quay/client.go | 24 +++--- 4 files changed, 50 insertions(+), 96 deletions(-) diff --git a/controllers/build_controller.go b/controllers/build_controller.go index 24f3e8c8..7305abdd 100644 --- a/controllers/build_controller.go +++ b/controllers/build_controller.go @@ -52,12 +52,10 @@ type BuildIntegrationReconciler struct { //+kubebuilder:rbac:groups=build.openshift.io,resources=builds,verbs=get;list;watch;create;update;patch func (r *BuildIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - logging.Log.Info("Reconciling Build", "Request.Namespace", req.Namespace, "Request.Name", req.Name) instance := &buildv1.Build{} err := r.CoreComponents.ReconcilerBase.GetClient().Get(ctx, req.NamespacedName, instance) - if err != nil { if apierrors.IsNotFound(err) { return reconcile.Result{}, nil @@ -69,7 +67,6 @@ func (r *BuildIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Req // Get ImageStream Tag buildImageStreamTagAnnotation, found := instance.GetAnnotations()[constants.BuildDestinationImageStreamAnnotation] - if !found { // If annotation not found, ImageStreamTag import has been completed return reconcile.Result{}, nil @@ -88,7 +85,6 @@ func (r *BuildIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Req } buildImageStreamNamespace := buildImageStreamComponents[0] - imageNameTagComponents := strings.Split(buildImageStreamComponents[1], ":") if len(imageNameTagComponents) != 2 { @@ -98,7 +94,6 @@ func (r *BuildIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Req KeyAndValues: []interface{}{"Namespace", instance.Namespace, "Build", instance.Name, "Annotation", buildImageStreamTagAnnotation, "Actual Size", len(imageNameTagComponents)}, Reason: "ProcessingError", }) - } buildImageName := imageNameTagComponents[0] @@ -107,7 +102,6 @@ func (r *BuildIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Req logging.Log.Info("Importing ImageStream after Build", "ImageStream Namespace", buildImageStreamNamespace, "ImageStream Name", buildImageName, "ImageStream Tag", buildImageTag) quayIntegration, result, err := r.CoreComponents.GetQuayIntegration(instance) - if err != nil { return result, err } @@ -115,7 +109,6 @@ func (r *BuildIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Req // First, Get the ImageStream existingImageStream := &imagev1.ImageStream{} err = r.CoreComponents.ReconcilerBase.GetClient().Get(ctx, types.NamespacedName{Namespace: buildImageStreamNamespace, Name: buildImageName}, existingImageStream) - if err != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: instance, @@ -123,7 +116,6 @@ func (r *BuildIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Req KeyAndValues: []interface{}{"Namespace", buildImageStreamNamespace, "Build", buildImageName}, Reason: "ProcessingError", }) - } isi := &imagev1.ImageStreamImport{ @@ -154,7 +146,6 @@ func (r *BuildIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Req } err = r.CoreComponents.ReconcilerBase.GetClient().Create(ctx, isi) - if err != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: instance, @@ -167,7 +158,6 @@ func (r *BuildIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Req // Update the Build instance.GetAnnotations()[constants.BuildDestinationImageStreamTagImportedAnnotation] = "true" - err = r.CoreComponents.ReconcilerBase.GetClient().Update(ctx, instance) if err != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ @@ -180,7 +170,6 @@ func (r *BuildIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Req } return reconcile.Result{}, nil - } // SetupWithManager sets up the controller with the Manager. @@ -188,12 +177,8 @@ func (r *BuildIntegrationReconciler) SetupWithManager(mgr ctrl.Manager) error { buildPredicates := []predicate.Predicate{ predicate.Funcs{ - UpdateFunc: func(e event.UpdateEvent) bool { - newBuild, ok := e.ObjectNew.(*buildv1.Build) - - // Check to see if it has the Managed Annotations _, managedAnnotationFound := e.ObjectNew.GetAnnotations()[constants.BuildOperatorManagedAnnotation] _, imageStreamImportedAnnotationFound := e.ObjectNew.GetAnnotations()[constants.BuildDestinationImageStreamTagImportedAnnotation] @@ -203,11 +188,9 @@ func (r *BuildIntegrationReconciler) SetupWithManager(mgr ctrl.Manager) error { return true }, - CreateFunc: func(e event.CreateEvent) bool { return false }, - DeleteFunc: func(e event.DeleteEvent) bool { return false }, diff --git a/controllers/namespace_controller.go b/controllers/namespace_controller.go index 529dc54a..2be2016f 100644 --- a/controllers/namespace_controller.go +++ b/controllers/namespace_controller.go @@ -75,7 +75,6 @@ type NamespaceIntegrationReconciler struct { //+kubebuilder:rbac:groups="image.openshift.io",resources=imagestreams;imagestreamimports,verbs=get;list;watch;create;update;patch func (r *NamespaceIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - r.Log.Info("Reconciling Namespace", "Name", req.Name) // Fetch the Namespace instance @@ -96,7 +95,6 @@ func (r *NamespaceIntegrationReconciler) Reconcile(ctx context.Context, req ctrl quayIntegrations := quayv1.QuayIntegrationList{} err = r.CoreComponents.ReconcilerBase.GetClient().List(ctx, &quayIntegrations, &client.ListOptions{}) - if err != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: instance, @@ -117,27 +115,22 @@ func (r *NamespaceIntegrationReconciler) Reconcile(ctx context.Context, req ctrl // Check is this is a valid namespace (TODO: Use a predicate to filter out?) validNamespace := quayIntegration.IsAllowedNamespace(instance.Name) - if !validNamespace { - // Not a synchronized namespace return reconcile.Result{}, nil } if quayIntegration.Spec.CredentialsSecret == nil { - return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: instance, Message: "Required parameter 'CredentialsSecret' not found", Reason: "ConfigurationError", }) - } secretCredential := &corev1.Secret{} err = r.CoreComponents.ReconcilerBase.GetClient().Get(ctx, types.NamespacedName{Namespace: quayIntegration.Spec.CredentialsSecret.Namespace, Name: quayIntegration.Spec.CredentialsSecret.Name}, secretCredential) - if err != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: instance, @@ -181,7 +174,6 @@ func (r *NamespaceIntegrationReconciler) Reconcile(ctx context.Context, req ctrl // Remove Resources result, err := r.cleanupResources(req, instance, quayClient, quayOrganizationName) - if err != nil { return result, err } @@ -197,19 +189,15 @@ func (r *NamespaceIntegrationReconciler) Reconcile(ctx context.Context, req ctrl }) } return reconcile.Result{}, nil - } // Finalizer Management if !util.HasFinalizer(instance, constants.NamespaceFinalizer) { - // Check if OpenShift Project if utils.IsOpenShiftAnnotatedNamespace(instance) { - if _, sccMcsFound := instance.Annotations[constants.OpenShiftSccMcsAnnotation]; !sccMcsFound { return reconcile.Result{}, nil } - } util.AddFinalizer(instance, constants.NamespaceFinalizer) @@ -227,13 +215,11 @@ func (r *NamespaceIntegrationReconciler) Reconcile(ctx context.Context, req ctrl // Setup Resources result, err := r.setupResources(ctx, req, instance, quayClient, quayOrganizationName, quayIntegration.Spec.ClusterID, quayIntegration.Spec.QuayHostname) - if err != nil { return result, err } return reconcile.Result{}, nil - } func (r *NamespaceIntegrationReconciler) setupResources(ctx context.Context, request reconcile.Request, namespace *corev1.Namespace, quayClient *qclient.QuayClient, quayOrganizationName string, quayName string, quayHostname string) (reconcile.Result, error) { @@ -250,12 +236,10 @@ func (r *NamespaceIntegrationReconciler) setupResources(ctx context.Context, req // Check to see if Organization Exists (Response Code) if organizationResponse.StatusCode == 404 { - // Create Organization logging.Log.Info("Organization Does Not Exist", "Name", quayOrganizationName) _, createOrganizationResponse, createOrganizationError := quayClient.CreateOrganization(quayOrganizationName) - if createOrganizationError.Error != nil || createOrganizationResponse.StatusCode != 201 { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, @@ -264,9 +248,7 @@ func (r *NamespaceIntegrationReconciler) setupResources(ctx context.Context, req Error: organizationError.Error, }) } - } else if organizationResponse.StatusCode != 200 { - return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, Message: "Error occurred retrieving Quay Organization", @@ -296,7 +278,6 @@ func (r *NamespaceIntegrationReconciler) setupResources(ctx context.Context, req imageStreams := imagev1.ImageStreamList{} err := r.CoreComponents.ReconcilerBase.GetClient().List(ctx, &imageStreams, &client.ListOptions{Namespace: namespace.Name}) - if err != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, @@ -304,14 +285,20 @@ func (r *NamespaceIntegrationReconciler) setupResources(ctx context.Context, req KeyAndValues: []interface{}{"Namespace", namespace.Name}, Error: err, }) - } for _, imageStream := range imageStreams.Items { - imageStreamName := imageStream.Name // Check if Repository Exists _, repositoryHttpResponse, repositoryErr := quayClient.GetRepository(quayOrganizationName, imageStreamName) + if repositoryHttpResponse == nil { + return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ + Object: namespace, + Message: "Error creating request to retrieve repository", + KeyAndValues: []interface{}{"Namespace", namespace.Name, "Name", imageStreamName}, + Error: repositoryErr.Error, + }) + } if repositoryErr.Error != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ @@ -320,15 +307,12 @@ func (r *NamespaceIntegrationReconciler) setupResources(ctx context.Context, req KeyAndValues: []interface{}{"Namespace", namespace.Name, "Name", imageStreamName, "Status Code", repositoryHttpResponse.StatusCode}, Error: repositoryErr.Error, }) - } // If an Repository reports back that it cannot be found or permission dened if repositoryHttpResponse.StatusCode == 403 || repositoryHttpResponse.StatusCode == 404 { logging.Log.Info("Creating Repository", "Organization", quayOrganizationName, "Name", imageStreamName) - _, createRepositoryResponse, createRepositoryErr := quayClient.CreateRepository(quayOrganizationName, imageStreamName) - if createRepositoryErr.Error != nil || createRepositoryResponse.StatusCode != 201 { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, @@ -336,9 +320,7 @@ func (r *NamespaceIntegrationReconciler) setupResources(ctx context.Context, req KeyAndValues: []interface{}{"Quay Repository", fmt.Sprintf("%s/%s", quayOrganizationName, imageStreamName), "Status Code", createRepositoryResponse.StatusCode}, Error: createRepositoryErr.Error, }) - } - } else if repositoryHttpResponse.StatusCode != 200 { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, @@ -346,17 +328,23 @@ func (r *NamespaceIntegrationReconciler) setupResources(ctx context.Context, req KeyAndValues: []interface{}{"Quay Repository", fmt.Sprintf("%s/%s", quayOrganizationName, imageStreamName), "Status Code", repositoryHttpResponse.StatusCode}, }) } - } return reconcile.Result{}, nil - } // createRobotAccountAndSecret creates a robot account, creates a secret and adds the secret to the service account func (r *NamespaceIntegrationReconciler) createRobotAccountAssociateToSA(ctx context.Context, request reconcile.Request, namespace *corev1.Namespace, quayClient *qclient.QuayClient, quayOrganizationName string, serviceAccount qotypes.OpenShiftServiceAccount, role qclient.QuayRole, quayName string, quayHostname string) (reconcile.Result, error) { // Setup Robot Account robotAccount, robotAccountResponse, robotAccountError := quayClient.GetOrganizationRobotAccount(quayOrganizationName, string(serviceAccount)) + if robotAccountResponse == nil { + return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ + Object: namespace, + Message: "Error occured creating HTTP request to fetch Quay Organization Robot Acccount", + KeyAndValues: []interface{}{"Quay Repository", quayOrganizationName, "Robot Account", serviceAccount}, + Error: robotAccountError.Error, + }) + } if robotAccountError.Error != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ @@ -369,23 +357,18 @@ func (r *NamespaceIntegrationReconciler) createRobotAccountAssociateToSA(ctx con // Check to see if Robot Exists if robotAccountResponse.StatusCode == 400 { - // Create Robot Account robotAccount, robotAccountResponse, robotAccountError = quayClient.CreateOrganizationRobotAccount(quayOrganizationName, string(serviceAccount)) - if robotAccountError.Error != nil || robotAccountResponse.StatusCode != 201 { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, Message: "Error occurred retrieving robot account for Quay Organization", KeyAndValues: []interface{}{"Quay Repository", quayOrganizationName, "Robot Account", serviceAccount, "Status Code", robotAccountResponse.StatusCode}, }) - } - } organizationPrototypes, organizationPrototypesResponse, organizationPrototypesError := quayClient.GetPrototypesByOrganization(quayOrganizationName) - if organizationPrototypesError.Error != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, @@ -393,7 +376,6 @@ func (r *NamespaceIntegrationReconciler) createRobotAccountAssociateToSA(ctx con KeyAndValues: []interface{}{"Quay Repository", quayOrganizationName, "Status Code", robotAccountResponse.StatusCode}, Error: organizationPrototypesError.Error, }) - } if organizationPrototypesResponse.StatusCode != 200 { @@ -402,13 +384,11 @@ func (r *NamespaceIntegrationReconciler) createRobotAccountAssociateToSA(ctx con Message: "Error occurred retrieving Prototypes for Quay Organization", KeyAndValues: []interface{}{"Quay Repository", quayOrganizationName, "Status Code", robotAccountResponse.StatusCode}, }) - } if found := qclient.IsRobotAccountInPrototypeByRole(organizationPrototypes.Prototypes, robotAccount.Name, string(role)); !found { // Create Prototype _, robotPrototypeResponse, robotPrototypeError := quayClient.CreateRobotPermissionForOrganization(quayOrganizationName, robotAccount.Name, string(role)) - if robotPrototypeError.Error != nil || robotPrototypeResponse.StatusCode != 200 { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, @@ -417,12 +397,10 @@ func (r *NamespaceIntegrationReconciler) createRobotAccountAssociateToSA(ctx con Error: robotPrototypeError.Error, }) } - } // Parse out hostname from Quay Hostname quayURL, quayURLErr := url.Parse(quayHostname) - if quayURLErr != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, @@ -430,13 +408,10 @@ func (r *NamespaceIntegrationReconciler) createRobotAccountAssociateToSA(ctx con KeyAndValues: []interface{}{"Hostname", quayHostname}, Error: quayURLErr, }) - } // Setup Secret for Quay Robot Account robotSecret, robotSecretErr := credentials.GenerateDockerJsonSecret(utils.GenerateDockerJsonSecretNameForServiceAccount(string(serviceAccount), quayName), quayURL.Host, robotAccount.Name, robotAccount.Token, "") - robotSecret.ObjectMeta.Namespace = namespace.Name - if robotSecretErr != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, @@ -446,15 +421,15 @@ func (r *NamespaceIntegrationReconciler) createRobotAccountAssociateToSA(ctx con }) } - robotCreateSecretErr := r.CoreComponents.ReconcilerBase.CreateOrUpdateResource(ctx, nil, namespace.Name, robotSecret) + robotSecret.ObjectMeta.Namespace = namespace.Name + robotCreateSecretErr := r.CoreComponents.ReconcilerBase.CreateOrUpdateResource(ctx, nil, namespace.Name, robotSecret) if robotCreateSecretErr != nil { return reconcile.Result{Requeue: true}, robotSecretErr } existingServiceAccount := &corev1.ServiceAccount{} serviceAccountErr := r.CoreComponents.ReconcilerBase.GetClient().Get(ctx, types.NamespacedName{Namespace: namespace.Name, Name: string(serviceAccount)}, existingServiceAccount) - if serviceAccountErr != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, @@ -466,11 +441,8 @@ func (r *NamespaceIntegrationReconciler) createRobotAccountAssociateToSA(ctx con } _, updated := r.updateSecretWithMountablePullSecret(existingServiceAccount, robotSecret.Name) - if updated { - updatedServiceAccountErr := r.CoreComponents.ReconcilerBase.CreateOrUpdateResource(ctx, nil, namespace.Name, existingServiceAccount) - if updatedServiceAccountErr != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, @@ -478,26 +450,22 @@ func (r *NamespaceIntegrationReconciler) createRobotAccountAssociateToSA(ctx con KeyAndValues: []interface{}{"Namespace", namespace.Name, "Service Account", serviceAccount}, Error: updatedServiceAccountErr, }) - } } return reconcile.Result{}, nil - } func (r *NamespaceIntegrationReconciler) cleanupResources(request reconcile.Request, namespace *corev1.Namespace, quayClient *qclient.QuayClient, quayOrganizationName string) (reconcile.Result, error) { - logging.Log.Info("Deleting Organization", "Organization Name", quayOrganizationName) - _, organizationResponse, orgniazationError := quayClient.GetOrganizationByname(quayOrganizationName) - - if orgniazationError.Error != nil { + _, organizationResponse, organizationError := quayClient.GetOrganizationByname(quayOrganizationName) + if organizationError.Error != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, Message: "Error occurred retrieving Organization", KeyAndValues: []interface{}{"Quay Organization", quayOrganizationName, "Status Code", organizationResponse.StatusCode}, - Error: orgniazationError.Error, + Error: organizationError.Error, }) } @@ -506,14 +474,22 @@ func (r *NamespaceIntegrationReconciler) cleanupResources(request reconcile.Requ return reconcile.Result{}, nil // Organization is not present } else if organizationResponse.StatusCode == 200 { - organizationDeleteResponse, orgniazationDeleteError := quayClient.DeleteOrganization(quayOrganizationName) + organizationDeleteResponse, organizationDeleteError := quayClient.DeleteOrganization(quayOrganizationName) + if organizationDeleteResponse == nil { + return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ + Object: namespace, + Message: "Error occurred building HTTP request to delete Organization", + KeyAndValues: []interface{}{"Quay Organization", quayOrganizationName}, + Error: organizationDeleteError.Error, + }) + } - if orgniazationDeleteError.Error != nil { + if organizationDeleteError.Error != nil { return r.CoreComponents.ManageError(&core.QuayIntegrationCoreError{ Object: namespace, Message: "Error occurred deleting Organization", KeyAndValues: []interface{}{"Quay Organization", quayOrganizationName, "Status Code", organizationDeleteResponse.StatusCode}, - Error: orgniazationDeleteError.Error, + Error: organizationDeleteError.Error, }) } @@ -524,7 +500,6 @@ func (r *NamespaceIntegrationReconciler) cleanupResources(request reconcile.Requ KeyAndValues: []interface{}{"Quay Organization", quayOrganizationName, "Status Code", organizationDeleteResponse.StatusCode}, }) } - return reconcile.Result{}, nil } else { @@ -534,24 +509,18 @@ func (r *NamespaceIntegrationReconciler) cleanupResources(request reconcile.Requ KeyAndValues: []interface{}{"Quay Organization", quayOrganizationName, "Status Code", organizationResponse.StatusCode}, }) } - } func (r *NamespaceIntegrationReconciler) updateSecretWithMountablePullSecret(serviceAccount *corev1.ServiceAccount, name string) (*corev1.ServiceAccount, bool) { - - updated := false + var updated bool if found := utils.LocalObjectReferenceNameExists(serviceAccount.ImagePullSecrets, name); !found { - serviceAccount.ImagePullSecrets = append(serviceAccount.ImagePullSecrets, corev1.LocalObjectReference{Name: name}) - updated = true } if found := utils.ObjectReferenceNameExists(serviceAccount.Secrets, name); !found { - serviceAccount.Secrets = append(serviceAccount.Secrets, corev1.ObjectReference{Name: name}) - updated = true } @@ -560,7 +529,6 @@ func (r *NamespaceIntegrationReconciler) updateSecretWithMountablePullSecret(ser // SetupWithManager sets up the controller with the Manager. func (r *NamespaceIntegrationReconciler) SetupWithManager(mgr ctrl.Manager) error { - //Retriggers a reconcilation of a namespace upon a change to an ImageStream within a namespace. Currently only supports adding repositories to Quay imageStreamToNamespace := handler.MapFunc( func(a client.Object) []reconcile.Request { @@ -570,9 +538,7 @@ func (r *NamespaceIntegrationReconciler) SetupWithManager(mgr ctrl.Manager) erro Name: a.GetNamespace(), }, }) - return res - }) return ctrl.NewControllerManagedBy(mgr). diff --git a/controllers/quayintegration_controller.go b/controllers/quayintegration_controller.go index e12fc7c6..9d3f7b6a 100644 --- a/controllers/quayintegration_controller.go +++ b/controllers/quayintegration_controller.go @@ -46,7 +46,6 @@ func (r *QuayIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Requ instance := &quayv1.QuayIntegration{} err := r.GetClient().Get(ctx, req.NamespacedName, instance) - if err != nil { if apierrors.IsNotFound(err) { return reconcile.Result{}, nil @@ -66,22 +65,24 @@ func (r *QuayIntegrationReconciler) Reconcile(ctx context.Context, req ctrl.Requ if err != nil { return reconcile.Result{Requeue: true}, err } + instance, err = instance.SetStatus(&quayv1.QuayIntegrationStatus{}) if err != nil { return reconcile.Result{Requeue: true}, err } + err = r.GetClient().Status().Update(ctx, instance) if err != nil { logger.Error(err, "Failed to update QuayIntegration status") return reconcile.Result{Requeue: true}, err } + logger.Info("Updated QuayIntegration status") specBytes, _ = json.Marshal(instance.Spec) r.LastSeenSpec[req.NamespacedName] = string(specBytes) return reconcile.Result{Requeue: false}, nil - } // SetupWithManager sets up the controller with the Manager. diff --git a/pkg/client/quay/client.go b/pkg/client/quay/client.go index 5a488fa7..c24afb5b 100644 --- a/pkg/client/quay/client.go +++ b/pkg/client/quay/client.go @@ -41,7 +41,6 @@ func (c *QuayClient) GetOrganizationByname(orgName string) (Organization, *http. } func (c *QuayClient) CreateOrganization(name string) (StringValue, *http.Response, QuayApiError) { - newOrganization := OrganizationRequest{ Name: name, Email: fmt.Sprintf("%s@redhat.com", name), @@ -51,6 +50,7 @@ func (c *QuayClient) CreateOrganization(name string) (StringValue, *http.Respons if err != nil { return StringValue{}, nil, QuayApiError{Error: err} } + var newOrganizationResponse StringValue resp, err := c.do(req, &newOrganizationResponse) @@ -58,11 +58,11 @@ func (c *QuayClient) CreateOrganization(name string) (StringValue, *http.Respons } func (c *QuayClient) GetOrganizationRobotAccount(organizationName string, robotName string) (RobotAccount, *http.Response, QuayApiError) { - req, err := c.newRequest("GET", fmt.Sprintf("/api/v1/organization/%s/robots/%s", organizationName, robotName), nil) if err != nil { return RobotAccount{}, nil, QuayApiError{Error: err} } + var getOrganizationRobotResponse RobotAccount resp, err := c.do(req, &getOrganizationRobotResponse) @@ -70,11 +70,11 @@ func (c *QuayClient) GetOrganizationRobotAccount(organizationName string, robotN } func (c *QuayClient) GetPrototypesByOrganization(organizationName string) (PrototypesResponse, *http.Response, QuayApiError) { - req, err := c.newRequest("GET", fmt.Sprintf("/api/v1/organization/%s/prototypes", organizationName), nil) if err != nil { return PrototypesResponse{}, nil, QuayApiError{Error: err} } + var getPrototypeResponse PrototypesResponse resp, err := c.do(req, &getPrototypeResponse) @@ -82,11 +82,11 @@ func (c *QuayClient) GetPrototypesByOrganization(organizationName string) (Proto } func (c *QuayClient) CreateOrganizationRobotAccount(organizationName string, robotName string) (RobotAccount, *http.Response, QuayApiError) { - req, err := c.newRequest("PUT", fmt.Sprintf("/api/v1/organization/%s/robots/%s", organizationName, robotName), nil) if err != nil { return RobotAccount{}, nil, QuayApiError{Error: err} } + var createOrganizationRobotResponse RobotAccount resp, err := c.do(req, &createOrganizationRobotResponse) @@ -98,13 +98,13 @@ func (c *QuayClient) DeleteOrganization(orgName string) (*http.Response, QuayApi if err != nil { return nil, QuayApiError{Error: err} } + resp, err := c.do(req, nil) return resp, QuayApiError{Error: err} } func (c *QuayClient) CreateRobotPermissionForOrganization(organizationName string, robotAccount string, role string) (Prototype, *http.Response, QuayApiError) { - robotOrganizationPermission := Prototype{ Role: role, Delegate: PrototypeDelegate{ @@ -119,6 +119,7 @@ func (c *QuayClient) CreateRobotPermissionForOrganization(organizationName strin if err != nil { return Prototype{}, nil, QuayApiError{Error: err} } + var newPrototypeResponse Prototype resp, err := c.do(req, &newPrototypeResponse) @@ -130,6 +131,7 @@ func (c *QuayClient) GetRepository(orgName string, repositoryName string) (Repos if err != nil { return Repository{}, nil, QuayApiError{Error: err} } + var repository Repository resp, err := c.do(req, &repository) @@ -137,7 +139,6 @@ func (c *QuayClient) GetRepository(orgName string, repositoryName string) (Repos } func (c *QuayClient) CreateRepository(namespace, name string) (RepositoryRequest, *http.Response, QuayApiError) { - newRepository := RepositoryRequest{ Repository: name, Namespace: namespace, @@ -150,6 +151,7 @@ func (c *QuayClient) CreateRepository(namespace, name string) (RepositoryRequest if err != nil { return RepositoryRequest{}, nil, QuayApiError{Error: err} } + var newRepositoryResponse RepositoryRequest resp, err := c.do(req, &newRepositoryResponse) @@ -159,6 +161,7 @@ func (c *QuayClient) CreateRepository(namespace, name string) (RepositoryRequest func (c *QuayClient) newRequest(method, path string, body interface{}) (*http.Request, error) { rel := &url.URL{Path: path} u := c.BaseURL.ResolveReference(rel) + var buf io.ReadWriter if body != nil { buf = new(bytes.Buffer) @@ -167,8 +170,8 @@ func (c *QuayClient) newRequest(method, path string, body interface{}) (*http.Re return nil, err } } - req, err := http.NewRequest(method, u.String(), buf) + req, err := http.NewRequest(method, u.String(), buf) if !utils.IsZeroOfUnderlyingType(c.AuthToken) { req.Header.Set("Authorization", "Bearer "+c.AuthToken) } @@ -176,12 +179,15 @@ func (c *QuayClient) newRequest(method, path string, body interface{}) (*http.Re if err != nil { return nil, err } + if body != nil { req.Header.Set("Content-Type", "application/json") } + req.Header.Set("Accept", "application/json") return req, nil } + func (c *QuayClient) do(req *http.Request, v interface{}) (*http.Response, error) { resp, err := c.httpClient.Do(req) if err != nil { @@ -190,22 +196,20 @@ func (c *QuayClient) do(req *http.Request, v interface{}) (*http.Response, error defer resp.Body.Close() if v != nil { - if _, ok := v.(*StringValue); ok { responseData, err := ioutil.ReadAll(resp.Body) if err != nil { return resp, err } + responseObject := v.(*StringValue) responseObject.Value = string(responseData) - } else { err = json.NewDecoder(resp.Body).Decode(v) if err != nil { return resp, err } } - } return resp, err