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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ __debug*
tmp/
.tmp/
dist/
deploy/signal/rendered/

# Docker
.dockerignore
Expand Down
58 changes: 49 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ MACHINE_OPS_CONTROLLER_NAME ?= machine-ops-controller
MACHINE_OPS_PROVIDER ?=
MACHINE_OPS_SITE ?=

PROJECT_SIGNAL_CONTROLLER_BIN=bin/project-signal-controller
PROJECT_SIGNAL_CONTROLLER_CMD=./cmd/project-signal-controller
SIGNAL_CONTROLLER_IMAGE ?= example.invalid/project-signal-controller:replace-me
SIGNAL_NAMESPACE ?= project-signal
SIGNAL_MANIFEST_TEMPLATES_DIR := deploy/signal
SIGNAL_MANIFEST_RENDERED_DIR := deploy/signal/rendered

METALMAN_BIN=bin/metalman
METALMAN_CMD=./cmd/metalman
NETBOOT_IMAGE ?= $(CONTAINER_REGISTRY)/netboot:$(VERSION_TAG)
Expand Down Expand Up @@ -230,14 +237,14 @@ NET_FRONTEND_CACHE_FILE := $(NET_FRONTEND_DIST_DIR)/.frontend-build-key
# Frontend build toggle (dev builds produce unminified output with sourcemaps).
REACT_DEV ?= false

.PHONY: all help fmt lint lint-actions test build vulncheck check-deps kubectl-unbounded kubectl-unbounded-build install-tools install-protoc install-helm generate kubectl-unbounded forge relctl relctl-build agent-artifacts-builder agent-artifacts-builder-build orcadev unbounded-agent machina machina-build machina-oci machina-oci-push machina-manifests machine-ops-controller machine-ops-controller-build machine-ops-controller-oci machine-ops-controller-oci-push machine-ops-manifests metalman metalman-build metalman-oci metalman-oci-push unbounded-operator unbounded-operator-build unbounded-operator-manifests playpen-manifests e2e-gantry e2e-playpen e2e-racer gomod docs-serve unbounded-net-controller unbounded-net-controller-build unbounded-net-node unbounded-net-node-build unbounded-net-routeplan-debug unping unping-build unroute unroute-build license-check notice notice-check gantry gantry-build gantry-manifests inventory-manifests
.PHONY: all help fmt lint lint-actions test build vulncheck check-deps kubectl-unbounded kubectl-unbounded-build install-tools install-protoc install-helm generate kubectl-unbounded forge relctl relctl-build agent-artifacts-builder agent-artifacts-builder-build orcadev unbounded-agent machina machina-build machina-oci machina-oci-push machina-manifests machine-ops-controller machine-ops-controller-build machine-ops-controller-oci machine-ops-controller-oci-push machine-ops-manifests project-signal-controller project-signal-controller-build signal-manifests image-project-signal-controller-local metalman metalman-build metalman-oci metalman-oci-push unbounded-operator unbounded-operator-build unbounded-operator-manifests playpen-manifests e2e-gantry e2e-playpen e2e-racer gomod docs-serve unbounded-net-controller unbounded-net-controller-build unbounded-net-node unbounded-net-node-build unbounded-net-routeplan-debug unping unping-build unroute unroute-build license-check notice notice-check gantry gantry-build gantry-manifests inventory-manifests
.PHONY: net-frontend net-frontend-clean net-ebpf-build net-ebpf-generate net-ebpf-verify net-manifests gantry-chart-lint gantry-chart-package release-bom release-manifests unbounded-operator-release-manifest
.PHONY: image-machina-local image-token-refresher-local image-machine-ops-controller-local image-metalman-local image-unbounded-operator-local image-unbounded-operator-push image-playpen-local image-net-controller-local image-net-node-local image-gantry-local image-gantry-push images-local
.PHONY: image-net-controller-push image-net-node-push images-net-all images-net-all-push

##@ General

all: kubectl-unbounded forge relctl machina machine-ops-controller token-refresher unbounded-operator unbounded-net-controller unbounded-net-node unbounded-net-routeplan-debug unping unroute gantry ## Build all binaries (default)
all: kubectl-unbounded forge relctl machina machine-ops-controller project-signal-controller token-refresher unbounded-operator unbounded-net-controller unbounded-net-node unbounded-net-routeplan-debug unping unroute gantry ## Build all binaries (default)

help: ## Show this help
@echo ""
Expand Down Expand Up @@ -289,6 +296,8 @@ help: ## Show this help
@echo " unbounded-agent Build unbounded-agent (linux)"
@echo " machina | machina-build Build machina controller (with/without lint/test)"
@echo " machine-ops-controller Build machine-ops-controller"
@echo " project-signal-controller Build Project Signal controller"
@echo " signal-manifests Render Project Signal manifests"
@echo " metalman | metalman-build Build metalman controller (with/without lint/test)"
@echo " unbounded-operator | unbounded-operator-build Build the top-level Site operator"
@echo " unbounded-net-controller Build net controller"
Expand All @@ -309,6 +318,10 @@ help: ## Show this help
@echo " image-machina-local Build machina image with \$$(CONTAINER_ENGINE)"
@echo " image-token-refresher-local Build token-refresher image"
@echo " image-machine-ops-controller-local Build machine-ops-controller image"
@echo " image-project-signal-controller-local Build Project Signal controller image"
@echo " Build Project Signal recovery verifier image"
@echo " Build Project Signal GPU runner image"
@echo " Build and push Project Signal GPU runner image"
@echo " image-metalman-local Build metalman image"
@echo " image-unbounded-operator-local Build unbounded-operator image"
@echo " image-unbounded-operator-push Build and push unbounded-operator image"
Expand Down Expand Up @@ -543,13 +556,13 @@ lint-actions: ## Run actionlint over .github/workflows
ifdef CI
# In CI each job is independent; skip chained prerequisites.

test: machina-manifests token-refresher-manifests machine-ops-manifests playpen-manifests net-manifests unbounded-operator-manifests gantry-manifests ## Run all tests with race detector
test: machina-manifests token-refresher-manifests machine-ops-manifests signal-manifests playpen-manifests net-manifests unbounded-operator-manifests gantry-manifests ## Run all tests with race detector
$(GOTEST) -race ./...

else
# Locally, chain test -> lint for convenience.

test: lint machina-manifests token-refresher-manifests machine-ops-manifests playpen-manifests net-manifests unbounded-operator-manifests gantry-manifests ## Run all tests (implies lint)
test: lint machina-manifests token-refresher-manifests machine-ops-manifests signal-manifests playpen-manifests net-manifests unbounded-operator-manifests gantry-manifests ## Run all tests (implies lint)
$(GOTEST) ./...

endif
Expand Down Expand Up @@ -654,16 +667,16 @@ image-racer-object-local: ## Build the racer-object container image locally (sin
--build-arg GIT_COMMIT=$(GIT_COMMIT) \
--build-arg BUILD_TIME=$(BUILD_TIME) \
-t racer-object:$(VERSION_TAG) -t $(RACER_OBJECT_IMAGE) \
-f ./images/racer-object/Containerfile .
$(call trivy-maybe,$(RACER_OBJECT_IMAGE))
-f ./images/racer-object/Containerfile .
$(call trivy-maybe,$(RACER_OBJECT_IMAGE))

build: machina-manifests token-refresher-manifests machine-ops-manifests playpen-manifests net-manifests unbounded-operator-manifests gantry-manifests ## Build all Go packages
$(GOBUILD) ./...
build: machina-manifests token-refresher-manifests machine-ops-manifests signal-manifests playpen-manifests net-manifests unbounded-operator-manifests gantry-manifests ## Build all Go packages
$(GOBUILD) ./...

generate: install-protoc ## Run go generate for API types (deepcopy, CRDs) and protobuf
PATH="$(PROTOC_DIR)/bin:$$PATH" $(GOCMD) generate $(GO_PACKAGES)

vulncheck: machina-manifests token-refresher-manifests machine-ops-manifests playpen-manifests net-manifests unbounded-operator-manifests gantry-manifests ## Run govulncheck; fails only on reachable vulnerabilities that have a final-release fix
vulncheck: machina-manifests token-refresher-manifests machine-ops-manifests signal-manifests playpen-manifests net-manifests unbounded-operator-manifests gantry-manifests ## Run govulncheck; fails only on reachable vulnerabilities that have a final-release fix
@# The JSON stream is the documented programmatic interface. The gate owns
@# the verdict, so govulncheck is not asked for one: in JSON mode it exits 0
@# whether or not it found anything, and a non-zero exit here means the scan
Expand Down Expand Up @@ -1075,6 +1088,21 @@ machine-ops-controller-oci: image-machine-ops-controller-local ## Alias for imag
machine-ops-controller-oci-push: machine-ops-controller-oci ## Build and push the machine-ops-controller image
$(CONTAINER_ENGINE) push $(MACHINE_OPS_CONTROLLER_IMAGE)

project-signal-controller-build: signal-manifests ## Build Project Signal controller without lint/test
@mkdir -p bin
$(GOBUILD) -trimpath -ldflags '$(STAMP_LDFLAGS)' -o $(PROJECT_SIGNAL_CONTROLLER_BIN) $(PROJECT_SIGNAL_CONTROLLER_CMD)

project-signal-controller: test project-signal-controller-build ## Build Project Signal controller (implies test)

image-project-signal-controller-local: ## Build Project Signal controller image locally
$(CONTAINER_ENGINE) build \
--build-arg VERSION=$(VERSION) \
--build-arg GIT_COMMIT=$(GIT_COMMIT) \
--build-arg BUILD_TIME=$(BUILD_TIME) \
-t project-signal-controller:$(VERSION_TAG) -t $(SIGNAL_CONTROLLER_IMAGE) \
-f ./images/project-signal-controller/Containerfile .
$(call trivy-maybe,$(SIGNAL_CONTROLLER_IMAGE))

MACHINA_NAMESPACE ?= $(UNBOUNDED_NAMESPACE)
MACHINA_API_SERVER_ENDPOINT ?=
MACHINA_MANIFEST_TEMPLATES_DIR := deploy/machina
Expand Down Expand Up @@ -1147,6 +1175,18 @@ machine-ops-manifests: ## Render machine-ops-controller manifests into deploy/ma
--set APIServerEndpoint=$(MACHINE_OPS_API_SERVER_ENDPOINT)
@echo "Rendered machine-ops manifests into $(MACHINE_OPS_MANIFEST_RENDERED_DIR) (image: $(MACHINE_OPS_CONTROLLER_IMAGE))"

signal-manifests: ## Render Project Signal manifests into deploy/signal/rendered
@mkdir -p $(SIGNAL_MANIFEST_RENDERED_DIR)/crd
@find $(SIGNAL_MANIFEST_RENDERED_DIR) -mindepth 1 -not -name .gitignore -delete
$(GOCMD) run ./hack/cmd/render-manifests \
--templates-dir $(SIGNAL_MANIFEST_TEMPLATES_DIR) \
--output-dir $(SIGNAL_MANIFEST_RENDERED_DIR) \
--set Namespace=$(SIGNAL_NAMESPACE) \
--set ControllerImage=$(SIGNAL_CONTROLLER_IMAGE)
@mkdir -p $(SIGNAL_MANIFEST_RENDERED_DIR)/crd
@cp $(SIGNAL_MANIFEST_TEMPLATES_DIR)/crd/*.yaml $(SIGNAL_MANIFEST_RENDERED_DIR)/crd/
@echo "Rendered Project Signal manifests into $(SIGNAL_MANIFEST_RENDERED_DIR) (image: $(SIGNAL_CONTROLLER_IMAGE))"

playpen-manifests: ## Render playpen operator and runner manifests into deploy/playpen/rendered
@mkdir -p $(PLAYPEN_MANIFEST_RENDERED_DIR)
@find $(PLAYPEN_MANIFEST_RENDERED_DIR) -mindepth 1 -not -name .gitignore -delete
Expand Down
126 changes: 126 additions & 0 deletions api/signal/v1alpha1/certificationprofile_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0

package v1alpha1

import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type ScriptReference struct {
Name string `json:"name"`
Key string `json:"key"`
}

type WorkflowReference struct {
Name string `json:"name"`
}

type CertificationPurpose string

const (
PurposeFullCertification CertificationPurpose = "FullCertification"
PurposeQuickCertification CertificationPurpose = "QuickCertification"
PurposePreflight CertificationPurpose = "Preflight"
PurposeTargetedVerification CertificationPurpose = "TargetedVerification"
PurposeDiagnostic CertificationPurpose = "Diagnostic"
)

type CertificationStage struct {
ID string `json:"id"`
DisplayName string `json:"displayName"`
Category string `json:"category"`
Description string `json:"description,omitempty"`
ExpectedDuration metav1.Duration `json:"expectedDuration,omitempty"`
Required bool `json:"required"`
Conditional bool `json:"conditional,omitempty"`
}

type ExecutionBackend struct {
APIVersion string `json:"apiVersion"`
Kind string `json:"kind"`
Queue string `json:"queue,omitempty"`
}

type ParticipantPolicy struct {
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=64
Count int32 `json:"count"`

Selector metav1.LabelSelector `json:"selector"`

RequiredResources corev1.ResourceList `json:"requiredResources,omitempty"`
}

type CertificationProfileSpec struct {
Participants ParticipantPolicy `json:"participants"`
Script ScriptReference `json:"script"`
Workflow WorkflowReference `json:"workflow"`
Backend ExecutionBackend `json:"backend"`
RunnerImage string `json:"runnerImage"`
// +kubebuilder:validation:Enum=FullCertification;QuickCertification;Preflight;TargetedVerification;Diagnostic
Purpose CertificationPurpose `json:"purpose,omitempty"`
StagePlan []CertificationStage `json:"stagePlan,omitempty"`
Parameters map[string]string `json:"parameters,omitempty"`
EvidencePath string `json:"evidencePath"`
Deadline metav1.Duration `json:"deadline"`
MaxAttempts int32 `json:"maxAttempts,omitempty"`
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
Recurring *RecurringPolicy `json:"recurring,omitempty"`
}

type RecurringPolicy struct {
Enabled bool `json:"enabled"`
NodeNames []string `json:"nodeNames"`
MinIdleDuration metav1.Duration `json:"minIdleDuration"`
ValidFor metav1.Duration `json:"validFor"`
NotBefore *metav1.Time `json:"notBefore,omitempty"`
ExpiresAt metav1.Time `json:"expiresAt"`
EvaluationInterval metav1.Duration `json:"evaluationInterval,omitempty"`
FailureBackoff metav1.Duration `json:"failureBackoff"`
MaxConsecutiveFailures int32 `json:"maxConsecutiveFailures"`
MaxConcurrent int32 `json:"maxConcurrent"`
FailureDomainLabel string `json:"failureDomainLabel,omitempty"`
MaxConcurrentPerFailureDomain int32 `json:"maxConcurrentPerFailureDomain,omitempty"`
ExclusiveProfiles []string `json:"exclusiveProfiles,omitempty"`
}

type RecurringNodeStatus struct {
NodeName string `json:"nodeName"`
IdleSince *metav1.Time `json:"idleSince,omitempty"`
LastEvaluatedAt *metav1.Time `json:"lastEvaluatedAt,omitempty"`
LastSuccessfulRun string `json:"lastSuccessfulRun,omitempty"`
LastSuccessfulAt *metav1.Time `json:"lastSuccessfulAt,omitempty"`
NextDueAt *metav1.Time `json:"nextDueAt,omitempty"`
ConsecutiveFailures int32 `json:"consecutiveFailures,omitempty"`
Suspended bool `json:"suspended,omitempty"`
Reason string `json:"reason,omitempty"`
}

type CertificationProfileStatus struct {
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
Nodes []RecurringNodeStatus `json:"nodes,omitempty"`
Conditions []metav1.Condition `json:"conditions,omitempty"`
}

// +kubebuilder:object:root=true
// +kubebuilder:resource:scope=Cluster,shortName=certprofile
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Backend",type=string,JSONPath=`.spec.backend.kind`
// +kubebuilder:printcolumn:name="Participants",type=integer,JSONPath=`.spec.participants.count`
// +kubebuilder:printcolumn:name="Recurring",type=boolean,JSONPath=`.spec.recurring.enabled`
type CertificationProfile struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec CertificationProfileSpec `json:"spec"`
Status CertificationProfileStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true
type CertificationProfileList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []CertificationProfile `json:"items"`
}
Loading
Loading