Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

bin/
.gobincache/
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM registry.svc.ci.openshift.org/openshift/release:golang-1.15 AS builder
WORKDIR /go/src/github.com/openshift/cluster-api-provider-equinix-metal
COPY . .
# VERSION env gets set in the openshift/release image and refers to the golang version, which interfers with our own
RUN unset VERSION \
&& GOPROXY=off NO_DOCKER=1 make build

FROM registry.svc.ci.openshift.org/openshift/origin-v4.0:base
COPY --from=builder /go/src/github.com/openshift/cluster-api-provider-equinix-metal/bin/machine-controller-manager /
9 changes: 9 additions & 0 deletions Dockerfile.rhel
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM registry.svc.ci.openshift.org/ocp/builder:rhel-8-golang-1.15-openshift-4.7 AS builder
WORKDIR /go/src/github.com/openshift/cluster-api-provider-equinix-metal
COPY . .
# VERSION env gets set in the openshift/release image and refers to the golang version, which interfers with our own
RUN unset VERSION \
&& make build GOPROXY=off NO_DOCKER=1 CGO_ENABLED=0

FROM registry.svc.ci.openshift.org/ocp/4.7:base
COPY --from=builder /go/src/github.com/openshift/cluster-api-provider-equinix-metal/bin/machine-controller-manager /
73 changes: 73 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
DBG ?= 0

ifeq ($(DBG),1)
GOGCFLAGS ?= -gcflags=all="-N -l"
endif

VERSION ?= $(shell git describe --always --abbrev=7)
REPO_PATH ?= github.com/openshift/cluster-api-provider-equinix-metal
LD_FLAGS ?= -X $(REPO_PATH)/pkg/version.Raw=$(VERSION) -extldflags -static

GO111MODULE = on
export GO111MODULE
GOFLAGS ?= -mod=vendor
export GOFLAGS
GOPROXY ?=
export GOPROXY

NO_DOCKER ?= 0
ifeq ($(NO_DOCKER), 1)
DOCKER_CMD =
IMAGE_BUILD_CMD = imagebuilder
CGO_ENABLED = 1
else
DOCKER_CMD := docker run --rm -e CGO_ENABLED=1 -v "$(PWD)":/go/src/$(REPO_PATH):Z -w /go/src/$(REPO_PATH) openshift/origin-release:golang-1.15
IMAGE_BUILD_CMD = docker build
endif

.PHONY: vendor
vendor:
go mod tidy
go mod vendor
go mod verify

.PHONY: generate
generate: gogen goimports
./hack/verify-diff.sh

gogen:
go generate ./pkg/... ./cmd/...

.PHONY: fmt
fmt: ## Go fmt your code
hack/go-fmt.sh .

.PHONY: goimports
goimports: ## Go fmt your code
hack/goimports.sh .

.PHONY: vet
vet: ## Apply go vet to all go files
hack/go-vet.sh ./...

.PHONY: test
test: ## Run tests
@echo -e "\033[32mTesting...\033[0m"
$(DOCKER_CMD) hack/ci-test.sh

.PHONY: unit
unit: # Run unit test
$(DOCKER_CMD) go test -race -cover ./cmd/... ./pkg/...

.PHONY: sec
sec: # Run security static analysis
hack/gosec.sh ./...

.PHONY: build
build: ## build binaries
$(DOCKER_CMD) go build $(GOGCFLAGS) -o "bin/machine-controller-manager" \
-ldflags "$(LD_FLAGS)" ./cmd/manager

.PHONY: test-e2e
test-e2e: ## Run e2e tests
hack/e2e.sh
6 changes: 6 additions & 0 deletions OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
approvers:
- enxebre
- JoelSpeed
- detiber
- displague
Comment thread
detiber marked this conversation as resolved.
- elmiko
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# OpenShift cluster-api-provider-equinix-metal

This repository hosts an implementation of a provider for Equinix Metal for the
OpenShift [machine-api](https://github.com/openshift/cluster-api).

This provider runs as a machine-controller deployed by the
[machine-api-operator](https://github.com/openshift/machine-api-operator)

Basic Testing:
```sh
export EQUINIX_METAL_API_KEY=`<YOUR API KEY>`
export EQUINIX_METAL_PROJECT_ID=`<YOUR PROJECT ID>`
export SSH_KEY_CONTENTS=$(cat ~/.ssh/id_rsa.pub)

# Create the ignition config
cat << EOF > example.fcc
variant: fcos
version: 1.1.0
passwd:
users:
- name: core
ssh_authorized_keys:
- ${SSH_KEY_CONTENTS}
EOF
docker run -i --rm quay.io/coreos/fcct:release --pretty --strict < example.fcc > example.ign

# Create the kind cluster for testing
kind create cluster

# Deploy the CRDs/RBAC
kustomize build config | kubectl apply -f -

# Create the referenced credentials secret
kubectl create secret generic equinixmetal-credentials-secret --from-literal=api_key=${EQUINIX_METAL_API_KEY}

# Create the referenced user data secret
kubectl create secret generic worker-user-data-secret --from-file=userData=./example.ign

# Create the example machine resource
envsubst < example/worker-machine.yaml | kubectl create -f -

# Build and run the controller
go build -o bin/manager ./cmd/manager
./bin/manager --logtostderr -v 5 -alsologtostderr
```
156 changes: 156 additions & 0 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package main

import (
"flag"
"fmt"
"os"
"time"

configv1 "github.com/openshift/api/config/v1"
"github.com/openshift/cluster-api-provider-equinix-metal/pkg/apis"
"github.com/openshift/cluster-api-provider-equinix-metal/pkg/cloud/equinixmetal/actuators/machine"
machinesetcontroller "github.com/openshift/cluster-api-provider-equinix-metal/pkg/cloud/equinixmetal/actuators/machineset"
"github.com/openshift/cluster-api-provider-equinix-metal/pkg/version"
"github.com/openshift/machine-api-operator/pkg/apis/machine/v1beta1"
capimachine "github.com/openshift/machine-api-operator/pkg/controller/machine"
"github.com/openshift/machine-api-operator/pkg/metrics"
"k8s.io/klog/v2"
"k8s.io/klog/v2/klogr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/manager"
)

// The default durations for the leader electrion operations.
var (
leaseDuration = 120 * time.Second
renewDealine = 110 * time.Second
retryPeriod = 20 * time.Second
)

func main() {
printVersion := flag.Bool(
"version",
false,
"print version and exit",
)

leaderElectResourceNamespace := flag.String(
"leader-elect-resource-namespace",
"",
"The namespace of resource object that is used for locking during leader election. If unspecified and running in cluster, defaults to the service account namespace for the controller. Required for leader-election outside of a cluster.",
)

leaderElect := flag.Bool(
"leader-elect",
false,
"Start a leader election client and gain leadership before executing the main loop. Enable this when running replicated components for high availability.",
)

leaderElectLeaseDuration := flag.Duration(
"leader-elect-lease-duration",
leaseDuration,
"The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate. This is only applicable if leader election is enabled.",
)

watchNamespace := flag.String(
"namespace",
"",
"Namespace that the controller watches to reconcile machine-api objects. If unspecified, the controller watches for machine-api objects across all namespaces.",
)

healthAddr := flag.String(
"health-addr",
":9440",
"The address for health checking.",
)

metricsAddress := flag.String(
"metrics-bind-address",
metrics.DefaultMachineMetricsAddress,
"Address for hosting metrics",
)

klog.InitFlags(nil)
flag.Set("logtostderr", "true")
flag.Parse()

if *printVersion {
fmt.Println(version.String)
os.Exit(0)
}

cfg := config.GetConfigOrDie()

opts := manager.Options{
LeaderElection: *leaderElect,
LeaderElectionNamespace: *leaderElectResourceNamespace,
LeaderElectionID: "cluster-api-provider-equinixmetal-leader",
LeaseDuration: leaderElectLeaseDuration,
HealthProbeBindAddress: *healthAddr,
MetricsBindAddress: *metricsAddress,
// Slow the default retry and renew election rate to reduce etcd writes at idle: BZ 1858400
RetryPeriod: &retryPeriod,
RenewDeadline: &renewDealine,
}

if *watchNamespace != "" {
opts.Namespace = *watchNamespace
klog.Infof("Watching machine-api objects only in namespace %q for reconciliation.", opts.Namespace)
}

// Setup a Manager
mgr, err := manager.New(cfg, opts)
if err != nil {
klog.Fatalf("Failed to set up overall controller manager: %v", err)
}

// Initialize machine actuator.
machineActuator := machine.NewActuator(machine.ActuatorParams{
CoreClient: mgr.GetClient(),
EventRecorder: mgr.GetEventRecorderFor("equinixmetalcontroller"),
// ComputeClientBuilder: computeservice.NewComputeService,
})

if err := apis.AddToScheme(mgr.GetScheme()); err != nil {
klog.Fatal(err)
}

if err := v1beta1.AddToScheme(mgr.GetScheme()); err != nil {
klog.Fatal(err)
}

if err := configv1.AddToScheme(mgr.GetScheme()); err != nil {
klog.Fatal(err)
}

if err := capimachine.AddWithActuator(mgr, machineActuator); err != nil {
klog.Fatal(err)
}

ctrl.SetLogger(klogr.New())
setupLog := ctrl.Log.WithName("setup")

if err = (&machinesetcontroller.Reconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("MachineSet"),
PlanServiceGetter: machinesetcontroller.RealPlanClient,
}).SetupWithManager(mgr, controller.Options{}); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "MachineSet")
os.Exit(1)
}

if err := mgr.AddReadyzCheck("ping", healthz.Ping); err != nil {
klog.Fatal(err)
}

if err := mgr.AddHealthzCheck("ping", healthz.Ping); err != nil {
klog.Fatal(err)
}

if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
klog.Fatalf("Failed to run manager: %v", err)
}
}
75 changes: 75 additions & 0 deletions config/controllers/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: machine-api-controllers
namespace: default
labels:
api: clusterapi
k8s-app: controller
tectonic-operators.coreos.com/managed-by: machine-api-operator
spec:
selector:
matchLabels:
api: clusterapi
k8s-app: controller
replicas: 1
template:
metadata:
labels:
api: clusterapi
k8s-app: controller
spec:
securityContext:
runAsNonRoot: true
runAsUser: 65534
nodeSelector:
node-role.kubernetes.io/master: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/master
- key: CriticalAddonsOnly
operator: Exists
- effect: NoExecute
key: node.alpha.kubernetes.io/notReady
operator: Exists
- effect: NoExecute
key: node.alpha.kubernetes.io/unreachable
operator: Exists
containers:
- name: controller-manager
image: openshift/origin-equinix-metal-machine-controllers:v4.0.0
command:
- "./manager"
resources:
requests:
cpu: 100m
memory: 20Mi
limits:
cpu: 100m
memory: 30Mi
- name: machine-controller
image: openshift/origin-equinix-metal-machine-controllers:v4.0.0
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
command:
- /machine-controller-manager
args:
- --logtostderr=true
- --v=3
- name: nodelink-controller
image: openshift/origin-machine-api-operator:latest
command:
- /nodelink-controller
args:
- --logtostderr=true
- --v=3
resources:
requests:
cpu: 100m
memory: 20Mi
limits:
cpu: 100m
memory: 30Mi
Loading