Skip to content

Commit

Permalink
🌱 don't power off, if off. And wait 5s
Browse files Browse the repository at this point in the history
  • Loading branch information
guettli committed Jun 8, 2023
1 parent 1e3f934 commit b08353e
Show file tree
Hide file tree
Showing 13 changed files with 163 additions and 28 deletions.
5 changes: 5 additions & 0 deletions .github/actions/manager-image/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ runs:
run: |
mkdir -p /tmp/.cache/caphv
- name: Go mod vendor
shell: bash
run: |
go mod vendor
# Import GitHub's cache build to docker cache
- name: Copy caphv Golang cache to docker cache
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # v4.0.0
Expand Down
29 changes: 29 additions & 0 deletions .github/actions/metadata/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: "Metadata"
description: "Generate Image Metadata"
inputs:
metadata_flavor:
description: "metadata_flavor"
required: true
metadata_tags:
description: "metadata_tags"
required: true
outputs:
tags:
description: "generated image tags"
value: ${{ steps.meta.outputs.tags }}
labels:
description: "generated image labels"
value: ${{ steps.meta.outputs.labels }}
version:
description: "generated image version"
value: ${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
runs:
using: "composite"
steps:
- name: Docker manager metadata
id: meta
uses: docker/metadata-action@c4ee3adeed93b1fa6a762f209fb01608c1a22f1e # v4.4.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: ${{ inputs.metadata_flavor }}
tags: ${{ inputs.metadata_tags }}
30 changes: 30 additions & 0 deletions .github/actions/setup-go/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: "Setup Go"
description: "Setup Go"
runs:
using: "composite"
steps:
- name: Install go
uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1
with:
go-version-file: "go.mod"
cache: true
cache-dependency-path: go.sum
- id: go-cache-paths
shell: bash
run: |
echo "::set-output name=go-build::$(go env GOCACHE)"
echo "::set-output name=go-mod::$(go env GOMODCACHE)"
- name: Go Mod Cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3
with:
path: ${{ steps.go-cache-paths.outputs.go-mod }}
key: ${{ runner.os }}-go-mod-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-mod-
- name: Go Build Cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3
with:
path: ${{ steps.go-cache-paths.outputs.go-build }}
key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-build-
25 changes: 12 additions & 13 deletions .github/workflows/pr-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
types: [opened, synchronize, reopened, ready_for_review]
branches:
- main
- e2e-tests
- "releases/**"
paths:
- "**.go"
Expand Down Expand Up @@ -38,18 +37,18 @@ jobs:
id: manager-image
uses: ./.github/actions/manager-image

test-release:
name: Create a Test Release
if: github.event_name != 'pull_request_target' || !github.event.pull_request.draft
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Test Release
id: manager-image
uses: ./.github/actions/test-release
# test-release:
# name: Create a Test Release
# if: github.event_name != 'pull_request_target' || !github.event.pull_request.draft
# runs-on: ubuntu-latest
# steps:
# - name: checkout
# uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
# with:
# ref: ${{ github.event.pull_request.head.sha }}
# - name: Test Release
# id: manager-image
# uses: ./.github/actions/test-release

e2e-basic:
name: End-to-End Test Basic
Expand Down
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ clean-release: ## Remove the release folder

.PHONY: clean-release-git
clean-release-git: ## Restores the git files usually modified during a release
git restore ./*manager_image_patch.yaml ./*manager_pull_policy.yaml
git restore ./*manager_config_patch.yaml ./*manager_pull_policy.yaml

##@ Release

Expand Down Expand Up @@ -535,7 +535,8 @@ release-notes: $(RELEASE_NOTES_DIR) $(RELEASE_NOTES)
.PHONY: set-manifest-image
set-manifest-image:
$(info Updating kustomize image patch file for default resource)
sed -i'' -e 's@image: .*@image: '"${MANIFEST_IMG}:$(MANIFEST_TAG)"'@' ./config/default/manager_image_patch.yaml
sed -i'' -e 's@image: .*@image: '"${MANIFEST_IMG}:$(MANIFEST_TAG)"'@' ./config/default/manager_config_patch.yaml


.PHONY: set-manifest-pull-policy
set-manifest-pull-policy:
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Kubernetes Cluster API Provider Hivelocity

> :warning: This project is in the development stage. DO NOT USE IN PRODUCTION! :warning:
The Hivelocity Provider is a Kubernetes-native tool that allows you to easily create and manage declarative infrastructure for your Kubernetes clusters on Hivelocity's infrastructure. It offers options for high availability on instant bare metal or custom dedicated setups and simplifies the process of creating, updating, and operating production-ready clusters.
Expand Down
3 changes: 2 additions & 1 deletion config/default/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ resources:
# - ../prometheus

patchesStrategicMerge:
- manager_config_patch.yaml
- manager_auth_proxy_patch.yaml
- manager_webhook_patch.yaml
- webhookcainjection_patch.yaml
- manager_config_patch.yaml
- manager_pull_policy.yaml


replacements:
Expand Down
11 changes: 11 additions & 0 deletions config/default/manager_pull_policy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
- name: manager
imagePullPolicy: IfNotPresent
2 changes: 1 addition & 1 deletion controllers/hivelocitycluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func (r *HivelocityClusterReconciler) reconcileNormal(ctx context.Context, clust
}

if err := reconcileTargetSecret(ctx, clusterScope); err != nil {
return reconcile.Result{}, fmt.Errorf("failed to reconcile target secret: %w", err)
return reconcile.Result{RequeueAfter: 30 * time.Second}, fmt.Errorf("failed to reconcile target secret: %s", err)
}

log.V(1).Info("Reconciling finished")
Expand Down
6 changes: 5 additions & 1 deletion docs/book/src/user/getting-started.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
# Getting Started
TBD

Create servers at [Hivelocity](https://www.hivelocity.net/).

Give the servers labels, so that clusters-api-provider-hivelocity knows which
servers should get part of the cluster.
41 changes: 41 additions & 0 deletions images/cache/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright 2023 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


FROM docker.io/library/alpine:3.18.0@sha256:02bb6f428431fbc2809c5d1b41eab5a68350194fb508869a33cb1af4444c9b11 as import-cache

RUN --mount=type=bind,target=/host-tmp \
--mount=type=cache,target=/root/.cache \
--mount=type=cache,target=/go/pkg \
mkdir -p /root/.cache/go-build; \
mkdir -p /go/pkg; \
if [ -f /host-tmp/go-build-cache.tar.gz ]; then \
tar xzf /host-tmp/go-build-cache.tar.gz --no-same-owner -C /root/.cache/go-build; \
fi; \
if [ -f /host-tmp/go-pkg-cache.tar.gz ]; then \
tar xzf /host-tmp/go-pkg-cache.tar.gz --no-same-owner -C /go/pkg; \
fi

FROM docker.io/library/alpine:3.18.0@sha256:02bb6f428431fbc2809c5d1b41eab5a68350194fb508869a33cb1af4444c9b11 as cache-creator
RUN --mount=type=cache,target=/root/.cache \
--mount=type=cache,target=/go/pkg \
tar czf /tmp/go-build-cache.tar.gz -C /root/.cache/go-build . ; \
tar czf /tmp/go-pkg-cache.tar.gz -C /go/pkg .

FROM scratch as export-cache

COPY --from=cache-creator \
/tmp/go-build-cache.tar.gz \
/tmp/go-pkg-cache.tar.gz \
/tmp/
21 changes: 16 additions & 5 deletions pkg/services/hivelocity/client/hvclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"fmt"
"net/http"
"strings"
"time"

"github.com/antihax/optional"
"github.com/hivelocity/cluster-api-provider-hivelocity/pkg/utils"
Expand Down Expand Up @@ -129,14 +130,24 @@ func (c *realClient) ProvisionDevice(ctx context.Context, deviceID int32, opts h
log := log.FromContext(ctx)
var swaggerErr hv.GenericSwaggerError

// First we need to send "shutdown".
// https://developers.hivelocity.net/reference/post_power_resource
_, _, err := c.client.DeviceApi.PostPowerResource(ctx, deviceID, "shutdown", nil) //nolint:bodyclose // Close() gets done in client
power, _, err := c.client.DeviceApi.GetPowerResource(ctx, deviceID, nil) //nolint:bodyclose // Close() gets done in client
if errors.As(err, &swaggerErr) {
body := string(swaggerErr.Body())
log.Info("ProvisionDevice() failed", "DeviceID", deviceID, "body", body)
log.Info("ProvisionDevice() failed (GetPowerResource)", "DeviceID", deviceID, "body", body)
}

if power.PowerStatus == "ON" {
// First we need to send "shutdown".
// https://developers.hivelocity.net/reference/post_power_resource
_, _, err := c.client.DeviceApi.PostPowerResource(ctx, deviceID, "shutdown", nil) //nolint:bodyclose // Close() gets done in client
if errors.As(err, &swaggerErr) {
body := string(swaggerErr.Body())
log.Info("ProvisionDevice() failed (PostPowerResource)", "DeviceID", deviceID, "body", body)
}
}

time.Sleep(5 * time.Second)

log.Info("calling ProvisionDevice()", "DeviceID", deviceID, "hostname", opts.Hostname, "OsName", opts.OsName,
"script", utils.FirstN(opts.Script, 50),
"ForceReload", opts.ForceReload)
Expand All @@ -149,7 +160,7 @@ func (c *realClient) ProvisionDevice(ctx context.Context, deviceID int32, opts h
device, _, err := c.client.BareMetalDevicesApi.PutBareMetalDeviceIdResource(ctx, deviceID, opts, &localVars) //nolint:bodyclose // Close() gets done in client
if errors.As(err, &swaggerErr) {
body := string(swaggerErr.Body())
log.Info("ProvisionDevice() failed", "DeviceID", deviceID, "body", body)
log.Info("ProvisionDevice() failed (PutBareMetalDeviceIdResource)", "DeviceID", deviceID, "body", body)
err = fmt.Errorf("%s: %w", body, swaggerErr)
}
return device, checkRateLimit(err)
Expand Down
12 changes: 7 additions & 5 deletions test/e2e/caphv.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ func CaphvClusterDeploymentSpec(ctx context.Context, inputGetter func() CaphvClu
gomega.Expect(os.MkdirAll(input.ArtifactFolder, 0750)).To(gomega.Succeed(), "Invalid argument. input.ArtifactFolder can't be created for %s spec", specName)
gomega.Expect(input.E2EConfig.Variables).To(gomega.HaveKey(KubernetesVersion))
gomega.Expect(input.E2EConfig.Variables).To(HaveValidVersion(input.E2EConfig.GetVariable(KubernetesVersion)))
gomega.Expect(input.ControlPlaneMachineCount).To(gomega.BeNumerically(">", 0))
gomega.Expect(input.WorkerMachineCount).To(gomega.BeNumerically(">", 0))

// Setup a Namespace where to host objects for this spec and create a watcher for the namespace events.
namespace, cancelWatches = setupSpecNamespace(ctx, specName, input.BootstrapClusterProxy, input.ArtifactFolder)
Expand All @@ -71,9 +73,9 @@ func CaphvClusterDeploymentSpec(ctx context.Context, inputGetter func() CaphvClu
clusterName = fmt.Sprintf("%s-%s", specName, util.RandomString(6))
})

ginkgo.It(fmt.Sprintf("Should successfully create a cluster with %d control planes and %d worker machines",
input.ControlPlaneMachineCount, input.WorkerMachineCount), func() {
ginkgo.By("Creating a workload cluster")
ginkgo.It("Should successfully create a cluster with control planes and worker machines", func() {
ginkgo.By(fmt.Sprintf("Creating a cluster: %d control-planes %d worker", input.ControlPlaneMachineCount,
input.WorkerMachineCount))
clusterctl.ApplyClusterTemplateAndWait(ctx, clusterctl.ApplyClusterTemplateAndWaitInput{
ClusterProxy: input.BootstrapClusterProxy,
ConfigCluster: clusterctl.ConfigClusterInput{
Expand All @@ -85,8 +87,8 @@ func CaphvClusterDeploymentSpec(ctx context.Context, inputGetter func() CaphvClu
Namespace: namespace.Name,
ClusterName: clusterName,
KubernetesVersion: input.E2EConfig.GetVariable(KubernetesVersion),
ControlPlaneMachineCount: pointer.Int64Ptr(input.ControlPlaneMachineCount),
WorkerMachineCount: pointer.Int64Ptr(input.WorkerMachineCount),
ControlPlaneMachineCount: pointer.Int64(input.ControlPlaneMachineCount),
WorkerMachineCount: pointer.Int64(input.WorkerMachineCount),
},
WaitForClusterIntervals: input.E2EConfig.GetIntervals(specName, "wait-cluster"),
WaitForControlPlaneIntervals: input.E2EConfig.GetIntervals(specName, "wait-control-plane"),
Expand Down

0 comments on commit b08353e

Please sign in to comment.