diff --git a/PROJECT b/PROJECT index 00a3a9821..194437758 100644 --- a/PROJECT +++ b/PROJECT @@ -126,4 +126,12 @@ resources: kind: Gateway path: github.com/onmetal/onmetal-api/apis/network/v1alpha1 version: v1alpha1 +- api: + crdVersion: v1 + namespaced: true + domain: onmetal.de + group: compute + kind: Console + path: github.com/onmetal/onmetal-api/apis/compute/v1alpha1 + version: v1alpha1 version: "3" diff --git a/apis/compute/v1alpha1/console_types.go b/apis/compute/v1alpha1/console_types.go new file mode 100644 index 000000000..5b4b046dd --- /dev/null +++ b/apis/compute/v1alpha1/console_types.go @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2021 by the OnMetal 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. + */ + +package v1alpha1 + +import ( + commonv1alpha1 "github.com/onmetal/onmetal-api/apis/common/v1alpha1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ConsoleSpec defines the desired state of Console +type ConsoleSpec struct { + // Type is the ConsoleType to use. + Type ConsoleType `json:"type"` + // MachineRef references the machine to open a console to. + MachineRef corev1.LocalObjectReference `json:"machineRef"` + // LighthouseClientConfig is the ConsoleClientConfig for the machine to connect to a common lighthouse. + LighthouseClientConfig *ConsoleClientConfig `json:"lighthouseClientConfig,omitempty"` +} + +type ConsoleClientConfig struct { + // Service is the service to connect to. + Service *ServiceReference `json:"service,omitempty"` + // URL is the url to connect to. + URL *string `json:"url,omitempty"` + // CABundle is a PEM encoded CA bundle which will be used to validate the endpoint's server certificate. + // If unspecified, system trust roots on the machine will be used. + CABundle []byte `json:"caBundle,omitempty"` + // KeySecret is the key that will be looked up for a client key. + KeySecret *commonv1alpha1.SecretKeySelector `json:"keySecret,omitempty"` +} + +const DefaultKeySecretKey = "client.cert" + +type ServiceReference struct { + // Name of the referenced service. + Name string `json:"name"` + // `path` is an optional URL path which will be sent in any request to + // this service. + // +optional + Path *string `json:"path,omitempty"` + + // Port on the service hosting the console. + // Defaults to 443 for backward compatibility. + // `port` should be a valid port number (1-65535, inclusive). + Port *int32 `json:"port,omitempty"` +} + +// ConsoleType represents the type of console. +// +kubebuilder:validation:Enum=Service;Lighthouse +type ConsoleType string + +const ( + ConsoleTypeService ConsoleType = "Service" + ConsoleTypeLightHouse ConsoleType = "Lighthouse" +) + +type ConsoleState string + +const ( + ConsoleStatePending ConsoleState = "Pending" + ConsoleStateReady ConsoleState = "Ready" + ConsoleStateError ConsoleState = "Error" +) + +// ConsoleStatus defines the observed state of Console +type ConsoleStatus struct { + State ConsoleState `json:"state,omitempty"` + ServiceClientConfig *ConsoleClientConfig `json:"serviceClientConfig,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status + +// Console is the Schema for the consoles API +type Console struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ConsoleSpec `json:"spec,omitempty"` + Status ConsoleStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// ConsoleList contains a list of Console +type ConsoleList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Console `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Console{}, &ConsoleList{}) +} diff --git a/apis/compute/v1alpha1/zz_generated.deepcopy.go b/apis/compute/v1alpha1/zz_generated.deepcopy.go index ef1212a5b..225f31bc7 100644 --- a/apis/compute/v1alpha1/zz_generated.deepcopy.go +++ b/apis/compute/v1alpha1/zz_generated.deepcopy.go @@ -27,6 +27,141 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Console) DeepCopyInto(out *Console) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Console. +func (in *Console) DeepCopy() *Console { + if in == nil { + return nil + } + out := new(Console) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Console) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConsoleClientConfig) DeepCopyInto(out *ConsoleClientConfig) { + *out = *in + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(ServiceReference) + (*in).DeepCopyInto(*out) + } + if in.URL != nil { + in, out := &in.URL, &out.URL + *out = new(string) + **out = **in + } + if in.CABundle != nil { + in, out := &in.CABundle, &out.CABundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.KeySecret != nil { + in, out := &in.KeySecret, &out.KeySecret + *out = new(commonv1alpha1.SecretKeySelector) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsoleClientConfig. +func (in *ConsoleClientConfig) DeepCopy() *ConsoleClientConfig { + if in == nil { + return nil + } + out := new(ConsoleClientConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConsoleList) DeepCopyInto(out *ConsoleList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Console, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsoleList. +func (in *ConsoleList) DeepCopy() *ConsoleList { + if in == nil { + return nil + } + out := new(ConsoleList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ConsoleList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConsoleSpec) DeepCopyInto(out *ConsoleSpec) { + *out = *in + out.MachineRef = in.MachineRef + if in.LighthouseClientConfig != nil { + in, out := &in.LighthouseClientConfig, &out.LighthouseClientConfig + *out = new(ConsoleClientConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsoleSpec. +func (in *ConsoleSpec) DeepCopy() *ConsoleSpec { + if in == nil { + return nil + } + out := new(ConsoleSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConsoleStatus) DeepCopyInto(out *ConsoleStatus) { + *out = *in + if in.ServiceClientConfig != nil { + in, out := &in.ServiceClientConfig, &out.ServiceClientConfig + *out = new(ConsoleClientConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsoleStatus. +func (in *ConsoleStatus) DeepCopy() *ConsoleStatus { + if in == nil { + return nil + } + out := new(ConsoleStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EFIVar) DeepCopyInto(out *EFIVar) { *out = *in @@ -460,6 +595,31 @@ func (in *MachineStatus) DeepCopy() *MachineStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceReference) DeepCopyInto(out *ServiceReference) { + *out = *in + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(string) + **out = **in + } + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceReference. +func (in *ServiceReference) DeepCopy() *ServiceReference { + if in == nil { + return nil + } + out := new(ServiceReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VolumeClaim) DeepCopyInto(out *VolumeClaim) { *out = *in diff --git a/config/crd/bases/compute.onmetal.de_consoles.yaml b/config/crd/bases/compute.onmetal.de_consoles.yaml new file mode 100644 index 000000000..364d1680a --- /dev/null +++ b/config/crd/bases/compute.onmetal.de_consoles.yaml @@ -0,0 +1,165 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: consoles.compute.onmetal.de +spec: + group: compute.onmetal.de + names: + kind: Console + listKind: ConsoleList + plural: consoles + singular: console + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Console is the Schema for the consoles 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: ConsoleSpec defines the desired state of Console + properties: + lighthouseClientConfig: + description: LighthouseClientConfig is the ConsoleClientConfig for + the machine to connect to a common lighthouse. + properties: + caBundle: + description: CABundle is a PEM encoded CA bundle which will be + used to validate the endpoint's server certificate. If unspecified, + system trust roots on the machine will be used. + format: byte + type: string + keySecret: + description: KeySecret is the key that will be looked up for a + client key. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this field may + be defaulted, in others it may be required. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + service: + description: Service is the service to connect to. + properties: + name: + description: Name of the referenced service. + type: string + path: + description: '`path` is an optional URL path which will be + sent in any request to this service.' + type: string + port: + description: Port on the service hosting the console. Defaults + to 443 for backward compatibility. `port` should be a valid + port number (1-65535, inclusive). + format: int32 + type: integer + required: + - name + type: object + url: + description: URL is the url to connect to. + type: string + type: object + machineRef: + description: MachineRef references the machine to open a console to. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: + description: Type is the ConsoleType to use. + enum: + - Service + - Lighthouse + type: string + required: + - machineRef + - type + type: object + status: + description: ConsoleStatus defines the observed state of Console + properties: + serviceClientConfig: + properties: + caBundle: + description: CABundle is a PEM encoded CA bundle which will be + used to validate the endpoint's server certificate. If unspecified, + system trust roots on the machine will be used. + format: byte + type: string + keySecret: + description: KeySecret is the key that will be looked up for a + client key. + properties: + key: + description: The key of the entry in the Secret resource's + `data` field to be used. Some instances of this field may + be defaulted, in others it may be required. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + service: + description: Service is the service to connect to. + properties: + name: + description: Name of the referenced service. + type: string + path: + description: '`path` is an optional URL path which will be + sent in any request to this service.' + type: string + port: + description: Port on the service hosting the console. Defaults + to 443 for backward compatibility. `port` should be a valid + port number (1-65535, inclusive). + format: int32 + type: integer + required: + - name + type: object + url: + description: URL is the url to connect to. + type: string + type: object + state: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 23b86840d..9aa9829ca 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -15,6 +15,7 @@ resources: - bases/network.onmetal.de_routingdomains.yaml - bases/network.onmetal.de_ipamranges.yaml - bases/network.onmetal.de_gateways.yaml +- bases/compute.onmetal.de_consoles.yaml #+kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: @@ -33,6 +34,7 @@ patchesStrategicMerge: #- patches/webhook_in_routingdomain.yaml #- patches/webhook_in_ipamranges.yaml #- patches/webhook_in_gateways.yaml +#- patches/webhook_in_consoles.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. @@ -49,6 +51,7 @@ patchesStrategicMerge: - patches/cainjection_in_machines.yaml - patches/cainjection_in_ipamranges.yaml - patches/cainjection_in_gateways.yaml +#- patches/cainjection_in_consoles.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/cainjection_in_consoles.yaml b/config/crd/patches/cainjection_in_consoles.yaml new file mode 100644 index 000000000..93f92f738 --- /dev/null +++ b/config/crd/patches/cainjection_in_consoles.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: consoles.compute.onmetal.de diff --git a/config/crd/patches/webhook_in_consoles.yaml b/config/crd/patches/webhook_in_consoles.yaml new file mode 100644 index 000000000..e00e3c6af --- /dev/null +++ b/config/crd/patches/webhook_in_consoles.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: consoles.compute.onmetal.de +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/rbac/console_editor_role.yaml b/config/rbac/console_editor_role.yaml new file mode 100644 index 000000000..c862a592b --- /dev/null +++ b/config/rbac/console_editor_role.yaml @@ -0,0 +1,24 @@ +# permissions for end users to edit consoles. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: console-editor-role +rules: +- apiGroups: + - compute.onmetal.de + resources: + - consoles + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - compute.onmetal.de + resources: + - consoles/status + verbs: + - get diff --git a/config/rbac/console_viewer_role.yaml b/config/rbac/console_viewer_role.yaml new file mode 100644 index 000000000..633731409 --- /dev/null +++ b/config/rbac/console_viewer_role.yaml @@ -0,0 +1,20 @@ +# permissions for end users to view consoles. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: console-viewer-role +rules: +- apiGroups: + - compute.onmetal.de + resources: + - consoles + verbs: + - get + - list + - watch +- apiGroups: + - compute.onmetal.de + resources: + - consoles/status + verbs: + - get diff --git a/config/samples/compute_v1alpha1_console.yaml b/config/samples/compute_v1alpha1_console.yaml new file mode 100644 index 000000000..036bc1dc6 --- /dev/null +++ b/config/samples/compute_v1alpha1_console.yaml @@ -0,0 +1,32 @@ +--- +apiVersion: compute.onmetal.de/v1alpha1 +kind: Console +metadata: + name: console-sample +spec: + type: Service + machineRef: + name: my-machine +#status: +# state: Ready +# tunnelClientConfig: +# url: https://my-tunnel-url.example.org +# keySecret: +# name: tunnel-key-secret +--- +apiVersion: compute.onmetal.de/v1alpha1 +kind: Console +metadata: + name: console-sample +spec: + type: Lighthouse + machineRef: + name: my-machine + lighthouseClientConfig: + url: https://my-lighthouse.example.org + caBundle: | + my-ca-bundle + keySecret: + name: my-lighthouse-secret +#status: +# state: Ready