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