Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
05e4296
feat: initialize conditions to unknown and move status updates to def…
rafalgalaw Apr 2, 2025
fcb58c5
fix: add missing error events
rafalgalaw Apr 2, 2025
46d41c1
fix: implement ConditionStatusObject interface on all API objects
rafalgalaw Apr 2, 2025
9f5d864
feat: improve garmserverconif controller status updates
rafalgalaw Apr 22, 2025
d9d7f6a
feat: improve githubcredentials controller status updates
rafalgalaw Apr 22, 2025
05cc4db
feat: improve githubendpoint controller status updates
rafalgalaw Apr 22, 2025
c5c5687
fix: cleanup image_types.go
rafalgalaw Apr 22, 2025
98fd1eb
feat: improve pool controller status updates
rafalgalaw Apr 22, 2025
4840764
feat: improve runner controller sync
rafalgalaw Apr 22, 2025
2a9d4c9
fix: improve runner controller performance
rafalgalaw Jun 24, 2025
eb2fdef
fix: rename conditions and add status messages
rafalgalaw Aug 28, 2025
2827af4
fix: runner controller status conditions
rafalgalaw Aug 28, 2025
4d35615
fix: enterprise controller tests
rafalgalaw Aug 28, 2025
5976f74
fix: garmserverconfig_controller tests
rafalgalaw Aug 29, 2025
23a8549
fix: organization_controller tests
rafalgalaw Aug 29, 2025
b3e21cb
fix: repository_controller tests
rafalgalaw Aug 29, 2025
b1415a3
fix: runner_controller tests
rafalgalaw Aug 29, 2025
0dc473e
chore: fix go lint
rafalgalaw Aug 29, 2025
800be3c
fix(runner): remove conditions for now
rafalgalaw Oct 8, 2025
df30b7e
fix(controller): remove depricated ctrl.Result{Requeue: true} and uns…
rafalgalaw Oct 8, 2025
68fbe63
fix(controller): rename initial CR var
rafalgalaw Oct 8, 2025
771f533
fix(conditions): cleanup
rafalgalaw Oct 8, 2025
e284bd7
fix(enterprise): simplify Reconcile method
rafalgalaw Oct 27, 2025
76a9199
fix(organization): simplify Reconcile method
rafalgalaw Oct 27, 2025
9099287
fix(repository): simplify Reconcile method
rafalgalaw Oct 27, 2025
1fc532c
chore: bump go to 1.24.9
rafalgalaw Nov 4, 2025
271ba3e
chore: remove nancy scan
rafalgalaw Nov 4, 2025
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
8 changes: 7 additions & 1 deletion DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,13 @@ Clone the `garm-provider-k8s` repo:
$ git clone https://github.com/mercedes-benz/garm-provider-k8s && cd ./garm-provider-k8s
```
And follow this [guide](https://github.com/mercedes-benz/garm-provider-k8s/blob/main/DEVELOPMENT.md). But `instead` of the `make tilt-up` in the `garm-provider-k8s` repo, execute the folling command. Make sure you are in your `kind-garm-operator` kubernetes context:
This will build a GitHub actions runner image and a garm-server image and bootstrap the garm-server in your local `kind` cluster:
```bash
$ RUNNER_IMAGE="localhost:5000/runner:linux-ubuntu-22.04-x86_64" make build copy docker-build docker-build-summerwind-runner && kubectl apply -k hack/local-development/kubernetes/
$ make build copy docker-build docker-build-summerwind-runner && kubectl apply -k hack/local-development/kubernetes/
```

Deploy the `garm-operator` CRs to your local `kind` cluster:
```bash
$ kubectl apply -k hack/local-development/kubernetes/garm-operator-crs.yaml
```
Essentially this does the same as the `make tilt-up` target in `garm-provider-k8s`, but in your local garm-operator cluster. Otherwise, a separate cluster will be spawned with the latest garm-operator release.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: MIT
# Build the manager binary
FROM golang:1.24.4 as builder
FROM golang:1.24.9 as builder
ARG TARGETOS
ARG TARGETARCH

Expand Down
13 changes: 1 addition & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ MOCKGEN ?= $(LOCALBIN)/mockgen
GORELEASER ?= $(LOCALBIN)/goreleaser
MDTOC ?= $(LOCALBIN)/mdtoc
SLICE ?= $(LOCALBIN)/kubectl-slice
NANCY ?= $(LOCALBIN)/nancy
GOVULNCHECK ?= $(LOCALBIN)/govulncheck
KBOM ?= $(LOCALBIN)/bom
KIND ?= $(LOCALBIN)/kind
Expand Down Expand Up @@ -247,12 +246,6 @@ $(SLICE): $(LOCALBIN)
test -s $(LOCALBIN)/kubectl-slice && $(LOCALBIN)/kubectl-slice --version | grep -q $(SLICE_VERSION) || \
GOBIN=$(LOCALBIN) go install github.com/patrickdappollonio/kubectl-slice@$(SLICE_VERSION)

.PHONY: nancy
nancy: $(NANCY) ## Download nancy locally if necessary. If wrong version is installed, it will be overwritten.
$(NANCY): $(LOCALBIN)
test -s $(LOCALBIN)/nancy && $(LOCALBIN)/nancy --version | grep -q $(NANCY_VERSION) || \
GOBIN=$(LOCALBIN) go install github.com/sonatype-nexus-community/nancy@$(NANCY_VERSION)

.PHONY: govulncheck
govulncheck: $(GOVULNCHECK) ## Download govulncheck locally if necessary. If wrong version is installed, it will be overwritten.
$(GOVULNCHECK): $(LOCALBIN)
Expand Down Expand Up @@ -311,17 +304,13 @@ verify-doctoc: generate-doctoc
fi

.PHONY: verify-security
verify-security: govulncheck-scan nancy-scan ## Verify security by running govulncheck and nancy
verify-security: govulncheck-scan ## Verify security by running govulncheck
@echo "Security checks passed"

.PHONY: govulncheck-scan
govulncheck-scan: govulncheck ## Perform govulncheck scan
$(GOVULNCHECK) ./...

.PHONY: nancy-scan
nancy-scan: nancy ## Perform nancy scan
go list -json -deps ./... | $(NANCY) sleuth

##@ Documentation
.PHONY: generate-doctoc
generate-doctoc: mdtoc ## Generate documentation table of contents
Expand Down
18 changes: 18 additions & 0 deletions api/v1alpha1/enterprise_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ type Enterprise struct {
Status EnterpriseStatus `json:"status,omitempty"`
}

func (e *Enterprise) InitializeConditions() {
if conditions.Get(e, conditions.ReadyCondition) == nil {
conditions.MarkUnknown(e, conditions.ReadyCondition, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg)
}

if conditions.Get(e, conditions.PoolManager) == nil {
conditions.MarkUnknown(e, conditions.PoolManager, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg)
}

if conditions.Get(e, conditions.WebhookSecretReference) == nil {
conditions.MarkUnknown(e, conditions.WebhookSecretReference, conditions.UnknownReason, conditions.WebhookSecretNotReconciledYetMsg)
}

if conditions.Get(e, conditions.GithubCredentialsReference) == nil {
conditions.MarkUnknown(e, conditions.GithubCredentialsReference, conditions.UnknownReason, conditions.CredentialsNotReconciledYetMsg)
}
}

func (e *Enterprise) SetConditions(conditions []metav1.Condition) {
e.Status.Conditions = conditions
}
Expand Down
18 changes: 18 additions & 0 deletions api/v1alpha1/organization_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ type Organization struct {
Status OrganizationStatus `json:"status,omitempty"`
}

func (o *Organization) InitializeConditions() {
if conditions.Get(o, conditions.ReadyCondition) == nil {
conditions.MarkUnknown(o, conditions.ReadyCondition, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg)
}

if conditions.Get(o, conditions.PoolManager) == nil {
conditions.MarkUnknown(o, conditions.PoolManager, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg)
}

if conditions.Get(o, conditions.WebhookSecretReference) == nil {
conditions.MarkUnknown(o, conditions.WebhookSecretReference, conditions.UnknownReason, conditions.WebhookSecretNotReconciledYetMsg)
}

if conditions.Get(o, conditions.GithubCredentialsReference) == nil {
conditions.MarkUnknown(o, conditions.GithubCredentialsReference, conditions.UnknownReason, conditions.CredentialsNotReconciledYetMsg)
}
}

func (o *Organization) SetConditions(conditions []metav1.Condition) {
o.Status.Conditions = conditions
}
Expand Down
18 changes: 18 additions & 0 deletions api/v1alpha1/repository_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,24 @@ type Repository struct {
Status RepositoryStatus `json:"status,omitempty"`
}

func (r *Repository) InitializeConditions() {
if conditions.Get(r, conditions.ReadyCondition) == nil {
conditions.MarkUnknown(r, conditions.ReadyCondition, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg)
}

if conditions.Get(r, conditions.PoolManager) == nil {
conditions.MarkUnknown(r, conditions.PoolManager, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg)
}

if conditions.Get(r, conditions.WebhookSecretReference) == nil {
conditions.MarkUnknown(r, conditions.WebhookSecretReference, conditions.UnknownReason, conditions.WebhookSecretNotReconciledYetMsg)
}

if conditions.Get(r, conditions.GithubCredentialsReference) == nil {
conditions.MarkUnknown(r, conditions.GithubCredentialsReference, conditions.UnknownReason, conditions.CredentialsNotReconciledYetMsg)
}
}

func (r *Repository) SetConditions(conditions []metav1.Condition) {
r.Status.Conditions = conditions
}
Expand Down
20 changes: 20 additions & 0 deletions api/v1alpha1/runner_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package v1alpha1

import (
apiconversion "k8s.io/apimachinery/pkg/conversion"
"sigs.k8s.io/controller-runtime/pkg/conversion"

"github.com/mercedes-benz/garm-operator/api/v1beta1"
Expand All @@ -16,3 +17,22 @@ func (r *Runner) ConvertTo(dstRaw conversion.Hub) error {
func (r *Runner) ConvertFrom(dstRaw conversion.Hub) error {
return Convert_v1beta1_Runner_To_v1alpha1_Runner(dstRaw.(*v1beta1.Runner), r, nil)
}

func Convert_v1beta1_RunnerStatus_To_v1alpha1_RunnerStatus(in *v1beta1.RunnerStatus, out *RunnerStatus, s apiconversion.Scope) error {
out.ID = in.ID
out.ProviderID = in.ProviderID
out.AgentID = in.AgentID
out.Name = in.Name
out.OSType = in.OSType
out.OSName = in.OSName
out.OSVersion = in.OSVersion
out.OSArch = in.OSArch
out.Addresses = nil
out.Status = in.Status
out.InstanceStatus = in.InstanceStatus
out.PoolID = in.PoolID
out.ProviderFault = in.ProviderFault
out.GitHubRunnerGroup = in.GitHubRunnerGroup

return autoConvert_v1beta1_RunnerStatus_To_v1alpha1_RunnerStatus(in, out, s)
}
8 changes: 4 additions & 4 deletions api/v1alpha1/runner_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ type RunnerStatus struct {
// for this instance.
Addresses []commonParams.Address `json:"addresses,omitempty"`

// Status is the status of the instance inside the provider (eg: running, stopped, etc)
Status commonParams.InstanceStatus `json:"status,omitempty"`
// Status is the runner status as it appears on GitHub. (idle, pending, ...)
Status params.RunnerStatus `json:"status,omitempty"`

// RunnerStatus is the github runner status as it appears on GitHub.
InstanceStatus params.RunnerStatus `json:"instanceStatus,omitempty"`
// InstanceStatus of the instance inside the respective cloud provider of the physical instance (eg: running, stopped, ...)
InstanceStatus commonParams.InstanceStatus `json:"instanceStatus,omitempty"`

// PoolID is the ID of the garm pool to which a runner belongs.
PoolID string `json:"poolId,omitempty"`
Expand Down
48 changes: 32 additions & 16 deletions api/v1alpha1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions api/v1beta1/enterprise_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,24 @@ type Enterprise struct {
Status EnterpriseStatus `json:"status,omitempty"`
}

func (e *Enterprise) InitializeConditions() {
if conditions.Get(e, conditions.ReadyCondition) == nil {
conditions.MarkUnknown(e, conditions.ReadyCondition, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg)
}

if conditions.Get(e, conditions.PoolManager) == nil {
conditions.MarkUnknown(e, conditions.PoolManager, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg)
}

if conditions.Get(e, conditions.WebhookSecretReference) == nil {
conditions.MarkUnknown(e, conditions.WebhookSecretReference, conditions.UnknownReason, conditions.WebhookSecretNotReconciledYetMsg)
}

if conditions.Get(e, conditions.GithubCredentialsReference) == nil {
conditions.MarkUnknown(e, conditions.GithubCredentialsReference, conditions.UnknownReason, conditions.CredentialsNotReconciledYetMsg)
}
}

func (e *Enterprise) SetConditions(conditions []metav1.Condition) {
e.Status.Conditions = conditions
}
Expand Down
8 changes: 8 additions & 0 deletions api/v1beta1/garmserverconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package v1beta1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/mercedes-benz/garm-operator/pkg/conditions"
)

// GarmServerConfigSpec defines the desired state of GarmServerConfig
Expand Down Expand Up @@ -47,6 +49,12 @@ type GarmServerConfig struct {
Status GarmServerConfigStatus `json:"status,omitempty"`
}

func (g *GarmServerConfig) InitializeConditions() {
if conditions.Get(g, conditions.ReadyCondition) == nil {
conditions.MarkUnknown(g, conditions.ReadyCondition, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg)
}
}

func (g *GarmServerConfig) SetConditions(conditions []metav1.Condition) {
g.Status.Conditions = conditions
}
Expand Down
16 changes: 16 additions & 0 deletions api/v1beta1/githubcredentials_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"github.com/cloudbase/garm/params"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/mercedes-benz/garm-operator/pkg/conditions"
)

// GitHubCredentialSpec defines the desired state of GitHubCredential
Expand Down Expand Up @@ -60,6 +62,20 @@ type GitHubCredential struct {
Status GitHubCredentialStatus `json:"status,omitempty"`
}

func (g *GitHubCredential) InitializeConditions() {
if conditions.Get(g, conditions.ReadyCondition) == nil {
conditions.MarkUnknown(g, conditions.ReadyCondition, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg)
}

if conditions.Get(g, conditions.GithubEndpointReference) == nil {
conditions.MarkUnknown(g, conditions.GithubEndpointReference, conditions.UnknownReason, conditions.GithubEndpointNotReconciledYetMsg)
}

if conditions.Get(g, conditions.WebhookSecretReference) == nil {
conditions.MarkUnknown(g, conditions.WebhookSecretReference, conditions.UnknownReason, conditions.WebhookSecretNotReconciledYetMsg)
}
}

func (g *GitHubCredential) SetConditions(conditions []metav1.Condition) {
g.Status.Conditions = conditions
}
Expand Down
12 changes: 12 additions & 0 deletions api/v1beta1/githubendpoint_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package v1beta1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/mercedes-benz/garm-operator/pkg/conditions"
)

// GitHubEndpointSpec defines the desired state of GitHubEndpoint
Expand Down Expand Up @@ -38,6 +40,16 @@ type GitHubEndpoint struct {
Status GitHubEndpointStatus `json:"status,omitempty"`
}

func (e *GitHubEndpoint) InitializeConditions() {
if conditions.Get(e, conditions.ReadyCondition) == nil {
conditions.MarkUnknown(e, conditions.ReadyCondition, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg)
}

if conditions.Get(e, conditions.WebhookSecretReference) == nil {
conditions.MarkUnknown(e, conditions.WebhookSecretReference, conditions.UnknownReason, conditions.WebhookSecretNotReconciledYetMsg)
}
}

func (e *GitHubEndpoint) SetConditions(conditions []metav1.Condition) {
e.Status.Conditions = conditions
}
Expand Down
Loading
Loading