diff --git a/api/v1alpha1/runnergroup_types.go b/api/v1alpha1/runnergroup_types.go index bcf5180..656c572 100644 --- a/api/v1alpha1/runnergroup_types.go +++ b/api/v1alpha1/runnergroup_types.go @@ -17,25 +17,70 @@ limitations under the License. package v1alpha1 import ( + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. +// RunnerGroupScope defines the scope of the runner group +type RunnerGroupScope string + +const ( + // RunnerGroupScopeGlobal means the runner group is available globally + RunnerGroupScopeGlobal RunnerGroupScope = "global" + // RunnerGroupScopeOrg means the runner group is scoped to an organization + RunnerGroupScopeOrg RunnerGroupScope = "org" + // RunnerGroupScopeRepo means the runner group is scoped to a repository + RunnerGroupScopeRepo RunnerGroupScope = "repo" +) + // RunnerGroupSpec defines the desired state of RunnerGroup. type RunnerGroupSpec struct { - // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - // Important: Run "make" to regenerate code after modifying this file + // Scope defines the scope of the runner (global, org, repo) + // +kubebuilder:validation:Enum=global;org;repo + // +kubebuilder:validation:Required + Scope RunnerGroupScope `json:"scope"` - // Foo is an example field of RunnerGroup. Edit runnergroup_types.go to remove/update - Foo string `json:"foo,omitempty"` + // Org is required if scope is 'org' + // +optional + Org string `json:"org,omitempty"` + + // Repo is required if scope is 'repo' + // +optional + Repo string `json:"repo,omitempty"` + + // GiteaURL is the base URL of the Gitea instance + // +kubebuilder:validation:Required + GiteaURL string `json:"giteaURL"` + + // Labels to assign to the runner + // +optional + Labels []string `json:"labels,omitempty"` + + // MaxActiveRunners is the maximum number of concurrent jobs + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Required + MaxActiveRunners int `json:"maxActiveRunners"` + + // RegistrationTokenRef references the secret containing the runner registration token + // +kubebuilder:validation:Required + RegistrationTokenRef corev1.SecretKeySelector `json:"registrationToken"` + + // AuthTokenRef references the secret containing the Gitea API token for polling + // +kubebuilder:validation:Required + AuthTokenRef corev1.SecretKeySelector `json:"authToken"` } // RunnerGroupStatus defines the observed state of RunnerGroup. type RunnerGroupStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file + // ActiveRunners is the current number of running jobs + ActiveRunners int `json:"activeRunners"` + + // LastCheckTime is the timestamp of the last poll to Gitea + // +optional + LastCheckTime *metav1.Time `json:"lastCheckTime,omitempty"` } // +kubebuilder:object:root=true diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 9534317..125df9d 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -29,8 +29,8 @@ func (in *RunnerGroup) DeepCopyInto(out *RunnerGroup) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec - out.Status = in.Status + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunnerGroup. @@ -86,6 +86,13 @@ func (in *RunnerGroupList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RunnerGroupSpec) DeepCopyInto(out *RunnerGroupSpec) { *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make([]string, len(*in)) + copy(*out, *in) + } + in.RegistrationTokenRef.DeepCopyInto(&out.RegistrationTokenRef) + in.AuthTokenRef.DeepCopyInto(&out.AuthTokenRef) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunnerGroupSpec. @@ -101,6 +108,10 @@ func (in *RunnerGroupSpec) DeepCopy() *RunnerGroupSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RunnerGroupStatus) DeepCopyInto(out *RunnerGroupStatus) { *out = *in + if in.LastCheckTime != nil { + in, out := &in.LastCheckTime, &out.LastCheckTime + *out = (*in).DeepCopy() + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunnerGroupStatus. diff --git a/config/crd/bases/gitea.bpg.pw_runnergroups.yaml b/config/crd/bases/gitea.bpg.pw_runnergroups.yaml new file mode 100644 index 0000000..99a2365 --- /dev/null +++ b/config/crd/bases/gitea.bpg.pw_runnergroups.yaml @@ -0,0 +1,140 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: runnergroups.gitea.bpg.pw +spec: + group: gitea.bpg.pw + names: + kind: RunnerGroup + listKind: RunnerGroupList + plural: runnergroups + singular: runnergroup + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: RunnerGroup is the Schema for the runnergroups API. + 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: RunnerGroupSpec defines the desired state of RunnerGroup. + properties: + authToken: + description: AuthTokenRef references the secret containing the Gitea + API token for polling + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + giteaURL: + description: GiteaURL is the base URL of the Gitea instance + type: string + labels: + description: Labels to assign to the runner + items: + type: string + type: array + maxActiveRunners: + description: MaxActiveRunners is the maximum number of concurrent + jobs + minimum: 1 + type: integer + org: + description: Org is required if scope is 'org' + type: string + registrationToken: + description: RegistrationTokenRef references the secret containing + the runner registration token + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + repo: + description: Repo is required if scope is 'repo' + type: string + scope: + description: Scope defines the scope of the runner (global, org, repo) + enum: + - global + - org + - repo + type: string + required: + - authToken + - giteaURL + - maxActiveRunners + - registrationToken + - scope + type: object + status: + description: RunnerGroupStatus defines the observed state of RunnerGroup. + properties: + activeRunners: + description: ActiveRunners is the current number of running jobs + type: integer + lastCheckTime: + description: LastCheckTime is the timestamp of the last poll to Gitea + format: date-time + type: string + required: + - activeRunners + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index c2c433b..bfe369f 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -1,11 +1,32 @@ +--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - labels: - app.kubernetes.io/name: gitea-runner-operator - app.kubernetes.io/managed-by: kustomize name: manager-role rules: -- apiGroups: [""] - resources: ["pods"] - verbs: ["get", "list", "watch"] +- apiGroups: + - gitea.bpg.pw + resources: + - runnergroups + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - gitea.bpg.pw + resources: + - runnergroups/finalizers + verbs: + - update +- apiGroups: + - gitea.bpg.pw + resources: + - runnergroups/status + verbs: + - get + - patch + - update