Skip to content

Commit

Permalink
feat(controller): add cluster-scoped project resource type and corres…
Browse files Browse the repository at this point in the history
…ponding controller (#1361)

Signed-off-by: Kent Rancourt <[email protected]>
krancour authored Jan 8, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent a1b5588 commit c838780
Showing 17 changed files with 530 additions and 5 deletions.
16 changes: 15 additions & 1 deletion Tiltfile
Original file line number Diff line number Diff line change
@@ -120,6 +120,19 @@ k8s_resource(
resource_deps=['back-end-compile']
)

k8s_resource(
workload = 'kargo-management-controller',
new_name = 'management-controller',
labels = ['kargo'],
objects = [
'kargo-management-controller:clusterrole',
'kargo-management-controller:clusterrolebinding',
'kargo-management-controller:configmap',
'kargo-management-controller:serviceaccount'
],
resource_deps=['back-end-compile']
)

k8s_resource(
workload = 'kargo-ui',
new_name = 'ui',
@@ -152,9 +165,10 @@ k8s_resource(
new_name = 'crds',
objects = [
'freights.kargo.akuity.io:customresourcedefinition',
'stages.kargo.akuity.io:customresourcedefinition',
'projects.kargo.akuity.io:customresourcedefinition',
'promotionpolicies.kargo.akuity.io:customresourcedefinition',
'promotions.kargo.akuity.io:customresourcedefinition',
'stages.kargo.akuity.io:customresourcedefinition',
'warehouses.kargo.akuity.io:customresourcedefinition'
],
labels = ['kargo']
2 changes: 2 additions & 0 deletions api/v1alpha1/groupversion_info.go
Original file line number Diff line number Diff line change
@@ -31,6 +31,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&FreightList{},
&Stage{},
&StageList{},
&Project{},
&ProjectList{},
&Promotion{},
&PromotionList{},
&PromotionPolicy{},
46 changes: 46 additions & 0 deletions api/v1alpha1/project_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package v1alpha1

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

//+kubebuilder:object:root=true
//+kubebuilder:resource:scope=Cluster
//+kubebuilder:subresource:status
//+kubebuilder:printcolumn:name=Age,type=date,JSONPath=`.metadata.creationTimestamp`

// Project is a resource type that reconciles to a specially labeled namespace
// and other TODO: TBD project-level resources.
type Project struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Spec describes a Project.
//
//+kubebuilder:validation:Required
Spec *ProjectSpec `json:"spec"`
// Status describes the Project's current status.
Status ProjectStatus `json:"status,omitempty"`
}

func (p *Project) GetStatus() *ProjectStatus {
return &p.Status
}

// ProjectSpec describes a Project.
type ProjectSpec struct {
// TODO: Figure out the attributes of a ProjectSpec.
}

// ProjectStatus describes a Project's current status.
type ProjectStatus struct {
// TODO: Figure out the attributes of a ProjectStatus.
}

//+kubebuilder:object:root=true

// ProjectList is a list of Project resources.
type ProjectList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Project `json:"items"`
}
93 changes: 93 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

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

11 changes: 11 additions & 0 deletions charts/kargo/README.md
Original file line number Diff line number Diff line change
@@ -107,6 +107,17 @@ the Kargo controller is running.
| `controller.tolerations` | Tolerations for controller pods. | `[]` |
| `controller.affinity` | Specifies pod affinity for controller pods. | `{}` |

### Management Controller

| Name | Description | Value |
| ----------------------------------- | ----------------------------------------------------------------------- | ------ |
| `managementController.enabled` | Whether the management controller is enabled. | `true` |
| `managementController.logLevel` | The log level for the management controller. | `INFO` |
| `managementController.resources` | Resources limits and requests for the management controller containers. | `{}` |
| `managementController.nodeSelector` | Node selector for management controller pods. | `{}` |
| `managementController.tolerations` | Tolerations for management controller pods. | `[]` |
| `managementController.affinity` | Specifies pod affinity for management controller pods. | `{}` |

### Webhooks

| Name | Description | Value |
51 changes: 51 additions & 0 deletions charts/kargo/crds/kargo.akuity.io_projects.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.13.0
name: projects.kargo.akuity.io
spec:
group: kargo.akuity.io
names:
kind: Project
listKind: ProjectList
plural: projects
singular: project
scope: Cluster
versions:
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: 'Project is a resource type that reconciles to a specially labeled
namespace and other TODO: TBD project-level resources.'
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: Spec describes a Project.
type: object
status:
description: Status describes the Project's current status.
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
12 changes: 8 additions & 4 deletions charts/kargo/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -46,18 +46,22 @@ app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: api
{{- end -}}

{{- define "kargo.dexServer.labels" -}}
app.kubernetes.io/component: dex-server
{{- end -}}

{{- define "kargo.controller.labels" -}}
app.kubernetes.io/component: controller
{{- end -}}

{{- define "kargo.dexServer.labels" -}}
app.kubernetes.io/component: dex-server
{{- end -}}

{{- define "kargo.garbageCollector.labels" -}}
app.kubernetes.io/component: garbage-collector
{{- end -}}

{{- define "kargo.managementController.labels" -}}
app.kubernetes.io/component: management-controller
{{- end -}}

{{- define "kargo.webhooksServer.labels" -}}
app.kubernetes.io/component: webhooks-server
{{- end -}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{- if and .Values.managementController.enabled .Values.rbac.installClusterRoleBindings }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kargo-management-controller
labels:
{{- include "kargo.labels" . | nindent 4 }}
{{- include "kargo.managementController.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kargo-management-controller
subjects:
- kind: ServiceAccount
namespace: {{ .Release.Namespace }}
name: kargo-management-controller
{{- end }}
18 changes: 18 additions & 0 deletions charts/kargo/templates/management-controller/cluster-roles.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{{- if and .Values.managementController.enabled .Values.rbac.installClusterRoles }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kargo-management-controller
labels:
{{- include "kargo.labels" . | nindent 4 }}
{{- include "kargo.managementController.labels" . | nindent 4 }}
rules:
- apiGroups:
- kargo.akuity.io
resources:
- projects
verbs:
- get
- list
- watch
{{- end }}
15 changes: 15 additions & 0 deletions charts/kargo/templates/management-controller/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{{- if .Values.managementController.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: kargo-management-controller
namespace: {{ .Release.Namespace }}
labels:
{{- include "kargo.labels" . | nindent 4 }}
{{- include "kargo.managementController.labels" . | nindent 4 }}
data:
LOG_LEVEL: {{ .Values.managementController.logLevel }}
{{- if .Values.kubeconfigSecrets.kargo }}
KUBECONFIG: /etc/kargo/kubeconfigs/kubeconfig.yaml
{{- end }}
{{- end }}
67 changes: 67 additions & 0 deletions charts/kargo/templates/management-controller/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{{- if .Values.managementController.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: kargo-management-controller
namespace: {{ .Release.Namespace }}
labels:
{{- include "kargo.labels" . | nindent 4 }}
{{- include "kargo.managementController.labels" . | nindent 4 }}
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
{{- include "kargo.selectorLabels" . | nindent 6 }}
{{- include "kargo.managementController.labels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "kargo.selectorLabels" . | nindent 8 }}
{{- include "kargo.managementController.labels" . | nindent 8 }}
annotations:
configmap/checksum: {{ include (print $.Template.BasePath "/management-controller/configmap.yaml") . | sha256sum }}
spec:
serviceAccount: kargo-management-controller
{{- with .Values.managementController.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: management-controller
image: {{ include "kargo.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ["/usr/local/bin/kargo", "management-controller"]
envFrom:
- configMapRef:
name: kargo-management-controller
{{- if .Values.kubeconfigSecrets.kargo }}
volumeMounts:
- mountPath: /etc/kargo/kubeconfigs
name: kubeconfigs
readOnly: true
{{- end }}
resources:
{{- toYaml .Values.managementController.resources | nindent 10 }}
{{- if .Values.kubeconfigSecrets.kargo }}
volumes:
- name: kubeconfigs
projected:
sources:
- secret:
name: {{ .Values.kubeconfigSecrets.kargo }}
items:
- key: kubeconfig.yaml
path: kubeconfig.yaml
mode: 0644
{{- end }}
{{- with .Values.managementController.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.managementController.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
10 changes: 10 additions & 0 deletions charts/kargo/templates/management-controller/service-account.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{{- if .Values.managementController.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: kargo-management-controller
namespace: {{ .Release.Namespace }}
labels:
{{- include "kargo.labels" . | nindent 4 }}
{{- include "kargo.managementController.labels" . | nindent 4 }}
{{- end }}
24 changes: 24 additions & 0 deletions charts/kargo/values.yaml
Original file line number Diff line number Diff line change
@@ -243,6 +243,30 @@ controller:
## @param controller.affinity Specifies pod affinity for controller pods.
affinity: {}

## @section Management Controller
## All settings for the management controller component
managementController:
## @param managementController.enabled Whether the management controller is enabled.
enabled: true

## @param managementController.logLevel The log level for the management controller.
logLevel: INFO

## @param managementController.resources Resources limits and requests for the management controller containers.
resources: {}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
## @param managementController.nodeSelector Node selector for management controller pods.
nodeSelector: {}
## @param managementController.tolerations Tolerations for management controller pods.
tolerations: []
## @param managementController.affinity Specifies pod affinity for management controller pods.
affinity: {}

## @section Webhooks
webhooks:
## @param webhooks.register Whether to create `ValidatingWebhookConfiguration` and `MutatingWebhookConfiguration` resources.
82 changes: 82 additions & 0 deletions cmd/controlplane/management_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package main

import (
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/metrics/server"

kargoapi "github.com/akuity/kargo/api/v1alpha1"
"github.com/akuity/kargo/internal/api/kubernetes"
"github.com/akuity/kargo/internal/controller/management/projects"
"github.com/akuity/kargo/internal/os"
versionpkg "github.com/akuity/kargo/internal/version"
)

func newManagementControllerCommand() *cobra.Command {
return &cobra.Command{
Use: "management-controller",
DisableAutoGenTag: true,
SilenceErrors: true,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()

version := versionpkg.GetVersion()

log.WithFields(log.Fields{
"version": version.Version,
"commit": version.GitCommit,
}).Info("Starting Kargo Management Controller")

var kargoMgr manager.Manager
{
restCfg, err :=
kubernetes.GetRestConfig(ctx, os.GetEnv("KUBECONFIG", ""))
if err != nil {
return errors.Wrap(
err,
"error loading REST config for Kargo controller manager",
)
}
restCfg.ContentType = runtime.ContentTypeJSON

scheme := runtime.NewScheme()
if err = corev1.AddToScheme(scheme); err != nil {
return errors.Wrap(
err,
"error adding Kubernetes core API to Kargo controller manager "+
"scheme",
)
}
if err = kargoapi.AddToScheme(scheme); err != nil {
return errors.Wrap(
err,
"error adding Kargo API to Kargo controller manager scheme",
)
}
if kargoMgr, err = ctrl.NewManager(
restCfg,
ctrl.Options{
Scheme: scheme,
Metrics: server.Options{
BindAddress: "0",
},
},
); err != nil {
return errors.Wrap(err, "error initializing Kargo controller manager")
}
}

if err := projects.SetupReconcilerWithManager(kargoMgr); err != nil {
return errors.Wrap(err, "error setting up Projects reconciler")
}

return errors.Wrap(kargoMgr.Start(ctx), "error starting kargo manager")
},
}
}
1 change: 1 addition & 0 deletions cmd/controlplane/root.go
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ func Execute(ctx context.Context) error {
rootCmd.AddCommand(newAPICommand())
rootCmd.AddCommand(newControllerCommand())
rootCmd.AddCommand(newGarbageCollectorCommand())
rootCmd.AddCommand(newManagementControllerCommand())
rootCmd.AddCommand(newVersionCommand())
rootCmd.AddCommand(newWebhooksServerCommand())
return rootCmd.ExecuteContext(ctx)
41 changes: 41 additions & 0 deletions internal/controller/management/projects/projects.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package projects

import (
"context"

ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/manager"

kargoapi "github.com/akuity/kargo/api/v1alpha1"
"github.com/akuity/kargo/internal/controller"
)

// reconciler reconciles Project resources.
type reconciler struct {
kargoClient client.Client
}

// SetupReconcilerWithManager initializes a reconciler for Project resources and
// registers it with the provided Manager.
func SetupReconcilerWithManager(kargoMgr manager.Manager) error {
return ctrl.NewControllerManagedBy(kargoMgr).
For(&kargoapi.Project{}).
WithOptions(controller.CommonOptions()).
Complete(newReconciler(kargoMgr.GetClient()))
}

func newReconciler(kargoClient client.Client) *reconciler {
return &reconciler{
kargoClient: kargoClient,
}
}

// Reconcile is part of the main Kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
func (r *reconciler) Reconcile(
context.Context,
ctrl.Request,
) (ctrl.Result, error) {
return ctrl.Result{}, nil
}
29 changes: 29 additions & 0 deletions ui/src/gen/schema/projects.kargo.akuity.io_v1alpha1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Project is a resource type that reconciles to a specially labeled namespace and other TODO: TBD project-level resources.",
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
"type": "string"
},
"kind": {
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
"type": "string"
},
"metadata": {
"type": "object"
},
"spec": {
"description": "Spec describes a Project.",
"type": "object"
},
"status": {
"description": "Status describes the Project's current status.",
"type": "object"
}
},
"required": [
"spec"
],
"type": "object"
}

0 comments on commit c838780

Please sign in to comment.