diff --git a/.github/workflows/nexus-operator-integration-checks.yaml b/.github/workflows/nexus-operator-integration-checks.yaml index f72c1619..99593197 100644 --- a/.github/workflows/nexus-operator-integration-checks.yaml +++ b/.github/workflows/nexus-operator-integration-checks.yaml @@ -83,7 +83,7 @@ jobs: - name: Cache testenv uses: actions/cache@v2 with: - path: ${{ env.GOPATH }}/testbin + path: ${{ env.PATH }}/nexus-operator/testbin key: ${{ runner.os }}-testbin-${{ env.OPERATOR_SDK_VERSION }} restore-keys: | ${{ runner.os }}-testbin-${{ env.OPERATOR_SDK_VERSION }} diff --git a/Makefile b/Makefile index f457f887..f33af599 100644 --- a/Makefile +++ b/Makefile @@ -34,18 +34,22 @@ all: manager # Run tests ENVTEST_ASSETS_DIR=$(shell pwd)/testbin -test: generate fmt vet manifests bundle +test: generate-installer fmt vet bundle mkdir -p ${ENVTEST_ASSETS_DIR} test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/master/hack/setup-envtest.sh sed -i "s,#\!.*,#\!\/bin\/bash,g" ${ENVTEST_ASSETS_DIR}/setup-envtest.sh sed -i "/pipefail/d" ${ENVTEST_ASSETS_DIR}/setup-envtest.sh source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./... -coverprofile cover.out - +# Run the OLM test on CI ci-olm-test: ./hack/ci/load-operator-image.sh ./hack/ci/operator-olm-test.sh +generate-installer: generate manifests kustomize + cd config/manager && $(KUSTOMIZE) edit set image controller=$(OPERATOR_IMG) + $(KUSTOMIZE) build config/default > nexus-operator.yaml + # Build manager binary manager: generate fmt vet go build -o bin/manager main.go diff --git a/README.md b/README.md index de6f4a25..bd853454 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ If you have any questions please either [open an issue](https://github.com/m88i/ ## Quick Install -The installation procedure will create a Namespace named `operators` and will install every resources needed for the operator to run: +The installation procedure will create a Namespace named `nexus-operator-system` and will install every resources needed for the operator to run: ```bash # requires python and kubectl diff --git a/hack/uninstall.sh b/hack/uninstall.sh index 7b981ea7..16ffa27e 100755 --- a/hack/uninstall.sh +++ b/hack/uninstall.sh @@ -14,19 +14,12 @@ # limitations under the License. -NAMESPACE=nexus +VERSION=$1 -echo "....... Uninstalling ......." -echo "....... Deleting CRDs......." -kubectl delete -f deploy/crds/apps.m88i.io_nexus_crd.yaml +if [ -z ${VERSION} ]; then + VERSION=$(curl https://api.github.com/repos/m88i/nexus-operator/releases/latest | python -c "import sys, json; print(json.load(sys.stdin)['tag_name'])") +fi -echo "....... Deleting Rules and Service Account ......." -kubectl delete -f deploy/role.yaml -n ${NAMESPACE} -kubectl delete -f deploy/role_binding.yaml -n ${NAMESPACE} -kubectl delete -f deploy/service_account.yaml -n ${NAMESPACE} +echo "....... Uninstall Nexus Operator ${VERSION} ......." -echo "....... Deleting Operator ......." -kubectl delete -f deploy/operator.yaml -n ${NAMESPACE} - -echo "....... Deleting namespace ${NAMESPACE}......." -kubectl delete namespace ${NAMESPACE} +kubectl delete -f https://github.com/m88i/nexus-operator/releases/download/${VERSION}/nexus-operator.yaml \ No newline at end of file diff --git a/nexus-operator.yaml b/nexus-operator.yaml new file mode 100644 index 00000000..1bfa9614 --- /dev/null +++ b/nexus-operator.yaml @@ -0,0 +1,609 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: controller-manager + name: nexus-operator-system +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + creationTimestamp: null + name: nexus.apps.m88i.io +spec: + group: apps.m88i.io + names: + kind: Nexus + listKind: NexusList + plural: nexus + singular: nexus + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: NexusSpec defines the desired state of Nexus + properties: + automaticUpdate: + description: Automatic updates configuration + properties: + disabled: + description: Whether or not the Operator should perform automatic updates. Defaults to `false` (auto updates are enabled). Is set to `false` if `spec.image` is not empty and is different from the default community image. + type: boolean + minorVersion: + description: The Nexus image minor version the deployment should stay in. If left blank and automatic updates are enabled the latest minor is set. + minimum: 0 + type: integer + type: object + generateRandomAdminPassword: + description: 'GenerateRandomAdminPassword enables the random password generation. Defaults to `false`: the default password for a newly created instance is ''admin123'', which should be changed in the first login. If set to `true`, you must use the automatically generated ''admin'' password, stored in the container''s file system at `/nexus-data/admin.password`. The operator uses the default credentials to create a user for itself to create default repositories. If set to `true`, the repositories won''t be created since the operator won''t fetch for the random password.' + type: boolean + image: + description: 'Full image tag name for this specific deployment. Will be ignored if `spec.useRedHatImage` is set to `true`. Default: docker.io/sonatype/nexus3:latest' + type: string + imagePullPolicy: + description: 'The image pull policy for the Nexus image. If left blank behavior will be determined by the image tag (`Always` if "latest" and `IfNotPresent` otherwise). Possible values: `Always`, `IfNotPresent` or `Never`.' + enum: + - Always + - IfNotPresent + - Never + type: string + livenessProbe: + description: LivenessProbe describes how the Nexus container liveness probe should work + properties: + failureThreshold: + description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + description: Number of seconds after the container has started before probes are initiated. Defaults to 240 seconds. Minimum value is 0. + format: int32 + minimum: 0 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. Defaults to 10 seconds. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + description: Number of seconds after which the probe times out. Defaults to 15 seconds. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + type: object + networking: + description: Networking definition + properties: + expose: + description: Set to `true` to expose the Nexus application. Defaults to `false`. + type: boolean + exposeAs: + description: 'Type of networking exposure: NodePort, Route or Ingress. Defaults to Route on OpenShift and Ingress on Kubernetes. Routes are only available on Openshift and Ingresses are only available on Kubernetes.' + enum: + - NodePort + - Route + - Ingress + type: string + host: + description: Host where the Nexus service is exposed. This attribute is required if the service is exposed via Ingress. + type: string + nodePort: + description: NodePort defined in the exposed service. Required if exposed via NodePort. + format: int32 + type: integer + tls: + description: TLS/SSL-related configuration + properties: + mandatory: + description: When exposing via Route, set to `true` to only allow encrypted traffic using TLS (disables HTTP in favor of HTTPS). Defaults to `false`. + type: boolean + secretName: + description: When exposing via Ingress, inform the name of the TLS secret containing certificate and private key for TLS encryption. It must be present in the same namespace as the Operator. + type: string + type: object + type: object + persistence: + description: Persistence definition + properties: + persistent: + description: Flag to indicate if this instance will be persistent or not + type: boolean + storageClass: + description: StorageClass used by the managed PVC. + type: string + volumeSize: + description: 'If persistent, the size of the Volume. Defaults: 10Gi' + type: string + required: + - persistent + type: object + readinessProbe: + description: ReadinessProbe describes how the Nexus container readiness probe should work + properties: + failureThreshold: + description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + description: Number of seconds after the container has started before probes are initiated. Defaults to 240 seconds. Minimum value is 0. + format: int32 + minimum: 0 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. Defaults to 10 seconds. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + description: Number of seconds after which the probe times out. Defaults to 15 seconds. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + type: object + replicas: + description: Number of pod replicas desired. Defaults to 0. + format: int32 + maximum: 100 + minimum: 0 + type: integer + resources: + description: Defined Resources for the Nexus instance + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + serverOperations: + description: ServerOperations describes the options for the operations performed on the deployed server instance + properties: + disableOperatorUserCreation: + description: DisableOperatorUserCreation disables the auto-creation of the `nexus-operator` user on the deployed server. This user performs all the operations on the server (such as creating the community repos). If disabled, the Operator will use the default `admin` user. Defaults to `false` (always create the user). Setting this to `true` is not recommended as it grants the Operator more privileges than it needs and it would not be possible to tell apart operations performed by the `admin` and the Operator. + type: boolean + disableRepositoryCreation: + description: DisableRepositoryCreation disables the auto-creation of Apache, JBoss and Red Hat repositories and their addition to the Maven Public group in this Nexus instance. Defaults to `false` (always try to create the repos). Set this to `true` to not create them. Only works if `spec.generateRandomAdminPassword` is `false`. + type: boolean + type: object + serviceAccountName: + description: ServiceAccountName is the name of the ServiceAccount used to run the Pods. If left blank, a default ServiceAccount is created with the same name as the Nexus CR (`metadata.name`). + type: string + useRedHatImage: + description: If you have access to Red Hat Container Catalog, set this to `true` to use the certified image provided by Sonatype Defaults to `false` + type: boolean + required: + - persistence + - replicas + - useRedHatImage + type: object + status: + description: NexusStatus defines the observed state of Nexus + properties: + deploymentStatus: + description: Condition status for the Nexus deployment + properties: + availableReplicas: + description: Total number of available pods (ready for at least minReadySeconds) targeted by this deployment. + format: int32 + type: integer + collisionCount: + description: Count of hash collisions for the Deployment. The Deployment controller uses this field as a collision avoidance mechanism when it needs to create the name for the newest ReplicaSet. + format: int32 + type: integer + conditions: + description: Represents the latest available observations of a deployment's current state. + items: + description: DeploymentCondition describes the state of a deployment at a certain point. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status to another. + format: date-time + type: string + lastUpdateTime: + description: The last time this condition was updated. + format: date-time + type: string + message: + description: A human readable message indicating details about the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of deployment condition. + type: string + required: + - status + - type + type: object + type: array + observedGeneration: + description: The generation observed by the deployment controller. + format: int64 + type: integer + readyReplicas: + description: Total number of ready pods targeted by this deployment. + format: int32 + type: integer + replicas: + description: Total number of non-terminated pods targeted by this deployment (their labels match the selector). + format: int32 + type: integer + unavailableReplicas: + description: Total number of unavailable pods targeted by this deployment. This is the total number of pods that are still required for the deployment to have 100% available capacity. They may either be pods that are running but not yet available or pods that still have not been created. + format: int32 + type: integer + updatedReplicas: + description: Total number of non-terminated pods targeted by this deployment that have the desired template spec. + format: int32 + type: integer + type: object + nexusRoute: + description: Route for external service access + type: string + nexusStatus: + description: Will be "OK" when this Nexus instance is up + type: string + reason: + description: Gives more information about a failure status + type: string + serverOperationsStatus: + description: ServerOperationsStatus describes the general status for the operations performed in the Nexus server instance + properties: + communityRepositoriesCreated: + type: boolean + mavenCentralUpdated: + type: boolean + operatorUserCreated: + type: boolean + reason: + type: string + serverReady: + type: boolean + type: object + updateConditions: + description: Conditions reached during an update + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: nexus-operator-leader-election-role + namespace: nexus-operator-system +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: nexus-operator-manager-role +rules: +- apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - apps + resources: + - deployments/finalizers + verbs: + - update +- apiGroups: + - apps + resources: + - replicasets + verbs: + - get +- apiGroups: + - apps.m88i.io + resources: + - nexus + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - apps.m88i.io + resources: + - nexus/status + verbs: + - get + - patch + - update +- apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - get +- apiGroups: + - "" + resources: + - events + - persistentvolumeclaims + - secrets + - serviceaccounts + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - pods + verbs: + - get +- apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - create + - get +- apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: nexus-operator-proxy-role +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: nexus-operator-metrics-reader +rules: +- nonResourceURLs: + - /metrics + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: nexus-operator-leader-election-rolebinding + namespace: nexus-operator-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: nexus-operator-leader-election-role +subjects: +- kind: ServiceAccount + name: default + namespace: nexus-operator-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: nexus-operator-manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: nexus-operator-manager-role +subjects: +- kind: ServiceAccount + name: default + namespace: nexus-operator-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: nexus-operator-proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: nexus-operator-proxy-role +subjects: +- kind: ServiceAccount + name: default + namespace: nexus-operator-system +--- +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-manager + name: nexus-operator-controller-manager-metrics-service + namespace: nexus-operator-system +spec: + ports: + - name: https + port: 8443 + targetPort: https + selector: + control-plane: controller-manager +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + control-plane: controller-manager + name: nexus-operator-controller-manager + namespace: nexus-operator-system +spec: + replicas: 1 + selector: + matchLabels: + control-plane: controller-manager + template: + metadata: + labels: + control-plane: controller-manager + spec: + containers: + - args: + - --secure-listen-address=0.0.0.0:8443 + - --upstream=http://127.0.0.1:8080/ + - --logtostderr=true + - --v=10 + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https + - args: + - --metrics-addr=127.0.0.1:8080 + - --enable-leader-election + command: + - /manager + image: quay.io/m88i/nexus-operator:0.4.0 + name: manager + resources: + limits: + cpu: 100m + memory: 30Mi + requests: + cpu: 100m + memory: 20Mi + terminationGracePeriodSeconds: 10 +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + control-plane: controller-manager + name: nexus-operator-controller-manager-metrics-monitor + namespace: nexus-operator-system +spec: + endpoints: + - path: /metrics + port: https + selector: + matchLabels: + control-plane: controller-manager