Skip to content

Commit

Permalink
Refactor using latest goharbor-client (#33)
Browse files Browse the repository at this point in the history
* WIP: Refactor with updated goharbor-client

* add unit tests & mocked runtime.Client

Along with this,

- reduce magic numbers
- add code generation verification action to GH workflow
- add (some) missing periods to comments

* re-generate using operator-sdk

* re-add sdk version as env

* fix codegen action, re-generate via operator-sdk v0.16.0

* drop mockery test, fix annotation

* fix renaming codegen action

* bump golangci-lint version, raise timeout

* ensure naming conventions, apply suggestions

* fix deprecated tag
  • Loading branch information
elenz97 authored Jul 28, 2020
1 parent 3be7136 commit 102cc52
Show file tree
Hide file tree
Showing 59 changed files with 1,523 additions and 870 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/verify-codegen.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Verify code generation integrity

on: pull_request

env:
OPERATOR_SDK_VERSION: v0.16.0

jobs:
verify-operator-sdk:
name: Verify Operator-SDK Codegen
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.13
uses: actions/setup-go@v1
with:
go-version: 1.13
id: go

- name: Check out code into the Go module directory
uses: actions/checkout@v2

- name: Install operator-sdk
run: sudo curl -L -o /usr/local/bin/operator-sdk "https://github.com/operator-framework/operator-sdk/releases/download/${OPERATOR_SDK_VERSION}/operator-sdk-${OPERATOR_SDK_VERSION}-x86_64-linux-gnu" && sudo chmod +x /usr/local/bin/operator-sdk

- name: Run code generation
run: operator-sdk generate k8s && operator-sdk generate crds

- name: Test diff
run: |
git diff | cat
git status --porcelain=v1
test $(git status --porcelain=v1 | wc -l) -eq 0
31 changes: 3 additions & 28 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ on:
pull_request:

env:
KUBECONFIG: /tmp/kubeconfig
OPERATOR_SDK_VERSION: v0.16.0
KUBECONFIG: /tmp/kubeconfig
IMAGE_NAME: quay.io/mittwald/harbor-operator
REGISTRY_URL: quay.io/mittwald

Expand All @@ -30,35 +30,10 @@ jobs:
uses: actions/checkout@v2

- name: Install golangci-lint
run: curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(go env GOPATH)/bin v1.24.0
run: curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(go env GOPATH)/bin v1.28.3

- name: Run golangci-lint
run: $(go env GOPATH)/bin/golangci-lint run -v --timeout 10m

verify:
name: Verify Codegen
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.13
uses: actions/setup-go@v1
with:
go-version: 1.13
id: go

- name: Check out code into the Go module directory
uses: actions/checkout@v2

- name: Install operator-sdk
run: sudo curl -L -o /usr/local/bin/operator-sdk "https://github.com/operator-framework/operator-sdk/releases/download/${OPERATOR_SDK_VERSION}/operator-sdk-${OPERATOR_SDK_VERSION}-x86_64-linux-gnu" && sudo chmod +x /usr/local/bin/operator-sdk

- name: Run code generation
run: operator-sdk generate k8s && operator-sdk generate crds

- name: Test diff
run: |
git diff | cat
git status --porcelain=v1
test $(git status --porcelain=v1 | wc -l) -eq 0
run: $(go env GOPATH)/bin/golangci-lint run -v --timeout 30m

test:
name: Test
Expand Down
12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,14 @@ fmt:
.PHONY: build
build:
operator-sdk build --go-build-args "-ldflags -X=version.Version=${SECRET_OPERATOR_VERSION}" ${DOCKER_IMAGE}
@exit $(.SHELLSTATUS)
@exit $(.SHELLSTATUS)

.PHONY: mock
mock:
@echo generating mocked k8s runtime client via
@echo sigs.k8s.io/[email protected]/pkg/client.Client
curl -sO https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.5.2/pkg/client/interfaces.go
mockery --quiet --dir $(PWD) \
--name Client --structname MockClient --filename=runtime_client_mock.go \
--output "$(PWD)/pkg/internal/mocks"
rm $(PWD)/interfaces.go
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,26 @@

A Kubernetes operator for managing [Goharbor](https://github.com/goharbor/harbor) instances

[![GitHub license](https://img.shields.io/github/license/mittwald/harbor-operator.svg)](https://github.com/mittwald/harbor-operator/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/mittwald/harbor-operator?status.svg)](https://pkg.go.dev/github.com/mittwald/harbor-operator)
[![GitHub license](https://img.shields.io/github/license/mittwald/harbor-operator.svg?style=flat-square)](https://github.com/mittwald/harbor-operator/blob/master/LICENSE)
[![Go Doc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](https://pkg.go.dev/github.com/mittwald/harbor-operator)
[![Release](https://img.shields.io/github/release/mittwald/harbor-operator.svg?style=flat-square)](https://github.com/mittwald/harbor-operator/releases/latest)

[![Go Report Card](https://goreportcard.com/badge/github.com/mittwald/harbor-operator?style=flat-square)](https://goreportcard.com/badge/github.com/mittwald/harbor-operator)
![Go](https://github.com/mittwald/harbor-operator/workflows/Go/badge.svg?branch=master)
[![Maintainability](https://api.codeclimate.com/v1/badges/6208714b76fca48ea633/maintainability)](https://codeclimate.com/github/mittwald/harbor-operator/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/6208714b76fca48ea633/test_coverage)](https://codeclimate.com/github/mittwald/harbor-operator/test_coverage)

##### This project is still under development and not stable yet - breaking changes may happen at any time and without notice
## Features
**Easy Harbor deployment & scaling**: Every Harbor instance is bound only to the deployed Custom Resource.
- **Easy Harbor deployment & scaling**: Every Harbor instance is bound only to the deployed Custom Resource.
The operator utilizes a [helm client](https://github.com/mittwald/go-helm-client) library for the management of these instances

**Custom chart repositories**: If you need to install a customized or private Harbor helm chart, the `instancechartrepo` resource allows you to do so. The official Helm chart can be found [here](https://github.com/goharbor/harbor-helm)

**Harbor resource reconciliation**: This operator automatically manages the following Harbor components by utilizing a custom [harbor client library](https://github.com/mittwald/goharbor-client):

- users
- repositories
- replications
- registries
- garbage collections
- **Custom chart repositories**: If you need to install a customized or private Harbor helm chart, the
`instancechartrepo` resource allows you to do so. The official Harbor Helm chart can be found [here](https://github
.com/goharbor/harbor-helm)

**Helm Chart**: [Installation Guide](#Helm)
- **Harbor resource reconciliation**: This operator automatically manages Harbor components by utilizing
a custom [harbor client](https:/github.com/mittwald/goharbor-client).

### CRDs
- registriesv1alpha1:
Expand Down Expand Up @@ -52,7 +51,8 @@ For more specific documentation, please refer to the [godoc](https://pkg.go.dev/
#### Web UI
For a trouble-free experience with created instances, a valid TLS certificate is required.

For automatic certificate creation, you can set the desired cluster certificate issuer via the instance spec:
For automatic certificate creation, you can set the desired cluster certificate issuer via the instance spec's
ingress annotations:

`.spec.helmChart.valuesYaml.expose.ingress.annotations`

Expand Down
37 changes: 27 additions & 10 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"github.com/mittwald/harbor-operator/pkg/apis"
opconfig "github.com/mittwald/harbor-operator/pkg/config"
"github.com/mittwald/harbor-operator/pkg/controller"
"github.com/mittwald/harbor-operator/version"

"github.com/operator-framework/operator-sdk/pkg/k8sutil"
kubemetrics "github.com/operator-framework/operator-sdk/pkg/kube-metrics"
Expand All @@ -37,7 +36,6 @@ import (
var log = logf.Log.WithName("cmd")

func printVersion() {
log.Info(fmt.Sprintf("Operator Version: %s", version.Version))
log.Info(fmt.Sprintf("Go Version: %s", runtime.Version()))
log.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH))
log.Info(fmt.Sprintf("Version of operator-sdk: %v", sdkVersion.Version))
Expand All @@ -58,13 +56,17 @@ func main() {
pflag.Int32("metrics-port", 8383, "metrics port")

// don't bind commands to variables, access them through viper
pflag.String("helm-client-repo-cache-path", "/tmp/.helmcache", "helm client repository cache path")
pflag.String("helm-client-repo-conf-path", "/tmp/.helmconfig", "helm client repository config path")
pflag.String("helm-client-repo-cache-path",
"/tmp/.helmcache", "helm client repository cache path")
pflag.String("helm-client-repo-conf-path",
"/tmp/.helmconfig", "helm client repository config path")

pflag.Parse()

viper.SetEnvPrefix("HARBOR_OPERATOR")

replacer := strings.NewReplacer("-", "_")

viper.SetEnvKeyReplacer(replacer)

viper.AutomaticEnv()
Expand All @@ -75,7 +77,7 @@ func main() {
os.Exit(1)
}

opconfig.ConfigFromViper()
opconfig.FromViper()

// Use a zap logr.Logger implementation. If none of the zap
// flags are configured (or if the zap flag set is not being
Expand Down Expand Up @@ -151,20 +153,32 @@ func main() {
}

// addMetrics will create the Services and Service Monitors to allow the operator export the metrics by using
// the Prometheus operator
func addMetrics(ctx context.Context, cfg *rest.Config, namespace string, metricsHost string, metricsPort int32, operatorMetricsPort int32) {
// the Prometheus operator.
func addMetrics(ctx context.Context, cfg *rest.Config, namespace string,
metricsHost string, metricsPort int32, operatorMetricsPort int32) {
if err := serveCRMetrics(cfg, metricsHost, operatorMetricsPort); err != nil {
if errors.Is(err, k8sutil.ErrRunLocal) {
log.Info("Skipping CR metrics server creation; not running in a cluster.")
return
}

log.Info("Could not generate and serve custom resource metrics", "error", err.Error())
}

// Add to the below struct any other metrics ports you want to expose.
servicePorts := []v1.ServicePort{
{Port: metricsPort, Name: metrics.OperatorPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: metricsPort}},
{Port: operatorMetricsPort, Name: metrics.CRPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: operatorMetricsPort}},
{
Port: metricsPort,
Name: metrics.OperatorPortName,
Protocol: v1.ProtocolTCP,
TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: metricsPort},
},
{
Port: operatorMetricsPort,
Name: metrics.CRPortName,
Protocol: v1.ProtocolTCP,
TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: operatorMetricsPort},
},
}

// Create Service object to expose the metrics port(s).
Expand All @@ -176,13 +190,15 @@ func addMetrics(ctx context.Context, cfg *rest.Config, namespace string, metrics
// CreateServiceMonitors will automatically create the prometheus-operator ServiceMonitor resources
// necessary to configure Prometheus to scrape metrics from this operator.
services := []*v1.Service{service}

_, err = metrics.CreateServiceMonitors(cfg, namespace, services)
if err != nil {
log.Info("Could not create ServiceMonitor object", "error", err.Error())
// If this operator is deployed to a cluster without the prometheus-operator running, it will return
// ErrServiceMonitorNotPresent, which can be used to safely skip ServiceMonitor creation.
if err == metrics.ErrServiceMonitorNotPresent {
log.Info("Install prometheus-operator in your cluster to create ServiceMonitor objects", "error", err.Error())
log.Info("Install prometheus-operator in your cluster to create ServiceMonitor objects",
"error", err.Error())
}
}
}
Expand All @@ -208,5 +224,6 @@ func serveCRMetrics(cfg *rest.Config, metricsHost string, operatorMetricsPort in
if err != nil {
return err
}

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ spec:
metadata:
type: object
spec:
description: InstanceChartRepoSpec defines the desired state of InstanceChartRepo
description: InstanceChartRepoSpec defines the desired state of InstanceChartRepo.
properties:
name:
type: string
Expand All @@ -57,7 +57,7 @@ spec:
- url
type: object
status:
description: InstanceChartRepoStatus defines the observed state of InstanceChartRepo
description: InstanceChartRepoStatus defines the observed state of InstanceChartRepo.
properties:
state:
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,41 +38,16 @@ spec:
metadata:
type: object
spec:
description: InstanceSpec defines the desired state of Instance
description: InstanceSpec defines the desired state of Instance.
properties:
garbageCollection:
description: GarbageCollectionReq holds request information for a garbage
collection schedule
collection schedule.
properties:
id:
format: int64
type: integer
name:
cron:
type: string
parameters:
additionalProperties:
type: string
type: object
schedule:
description: ScheduleParam defines the parameters of a schedule
trigger
properties:
cron:
description: The cron string of scheduled job
type: string
type:
description: 'Daily, Hourly, Weekly, Custom, Manual, None Note:
When creating pre-defined schedule types (e.g. ''Hourly''),
the Cron string has to be provided.'
type: string
required:
- cron
- type
type: object
status:
scheduleType:
type: string
required:
- schedule
type: object
helmChart:
properties:
Expand Down Expand Up @@ -188,12 +163,12 @@ spec:
- version
type: object
status:
description: InstanceStatus defines the observed state of Instance
description: InstanceStatus defines the observed state of Instance.
properties:
phase:
properties:
lastTransition:
description: Time of last observed transition into this state
description: Time of last observed transition into this state.
format: date-time
type: string
message:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,23 @@ spec:
metadata:
type: object
spec:
description: RegistrySpec defines the desired state of a Registry
description: RegistrySpec defines the desired state of a Registry.
properties:
credential:
description: Credential keeps the access key and/or secret for the related
registry
description: "RegistryCredential registry credential \n swagger:model
RegistryCredential"
properties:
access_key:
description: The key of the access account, for OAuth token, it
can be empty
description: Access key, e.g. user name when credential type is
'basic'.
type: string
access_secret:
description: The secret or password for the key
description: Access secret, e.g. password when credential type is
'basic'.
type: string
type:
description: Type of the credential
description: Credential type, such as 'basic', 'oauth'.
type: string
required:
- access_key
- access_secret
- type
type: object
description:
type: string
Expand All @@ -77,14 +74,7 @@ spec:
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
tokenServiceUrl:
description: TokenServiceURL is only used for local harbor instances
to avoid the requests passing through the external proxy for now
type: string
type:
description: 'TODO: A string enum would be appropriate here, though
kubebuilder seems to not like this annotation: "+kubebuilder:validation:Enum:=harbor,docker-hub,docker-registry,huawei-SWR,google-gcr,aws-ecr,azure-acr,ali-acr,jfrog-artifactory,quay-io,gitlab,helm-hub"
Leaving it as is for the time being'
type: string
url:
description: Target URL of the registry
Expand All @@ -96,7 +86,7 @@ spec:
- url
type: object
status:
description: RegistryStatus defines the observed state of Registry
description: RegistryStatus defines the observed state of Registry.
properties:
lastTransition:
description: Time of last observed transition into this state
Expand Down
Loading

0 comments on commit 102cc52

Please sign in to comment.