Skip to content

Commit e7efceb

Browse files
authored
chore: Make v1beta1 CRD have it's own version of spec and status (#2637)
* split kyma status * make v1beta1 immutable
1 parent c74803b commit e7efceb

File tree

10 files changed

+770
-23
lines changed

10 files changed

+770
-23
lines changed

api/v1beta1/kyma_types.go

Lines changed: 158 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ package v1beta1
1818

1919
import (
2020
apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21-
22-
"github.com/kyma-project/lifecycle-manager/api/v1beta2"
2321
)
2422

2523
// +genclient
@@ -35,8 +33,8 @@ type Kyma struct {
3533
apimetav1.TypeMeta `json:",inline"`
3634
apimetav1.ObjectMeta `json:"metadata,omitempty"`
3735

38-
Spec KymaSpec `json:"spec,omitempty"`
39-
Status v1beta2.KymaStatus `json:"status,omitempty"`
36+
Spec KymaSpec `json:"spec,omitempty"`
37+
Status KymaStatus `json:"status,omitempty"`
4038
}
4139

4240
// Sync defines settings used to apply the kyma synchronization to other clusters. This is defaulted to false
@@ -49,7 +47,7 @@ type Sync struct {
4947

5048
// +kubebuilder:default:=secret
5149
// Strategy determines the way to look up the remotely synced kubeconfig, by default it is fetched from a secret
52-
Strategy v1beta2.SyncStrategy `json:"strategy,omitempty"`
50+
Strategy SyncStrategy `json:"strategy,omitempty"`
5351

5452
// The target namespace, if empty the namespace is reflected from the control plane
5553
// Note that cleanup is currently not supported if you are switching the namespace, so you will
@@ -67,6 +65,10 @@ type Sync struct {
6765
ModuleCatalog bool `json:"moduleCatalog,omitempty"`
6866
}
6967

68+
// SyncStrategy determines how the Remote Cluster is synchronized with the Control Plane. This can influence secret
69+
// lookup, or other behavioral patterns when interacting with the remote cluster.
70+
type SyncStrategy string
71+
7072
// KymaSpec defines the desired state of Kyma.
7173
type KymaSpec struct {
7274
// Channel specifies the desired Channel of the Installation, usually targeting different module versions.
@@ -80,13 +82,105 @@ type KymaSpec struct {
8082
SkipMaintenanceWindows bool `json:"skipMaintenanceWindows,omitempty"`
8183

8284
// Modules specifies the list of modules to be installed
83-
Modules []v1beta2.Module `json:"modules,omitempty"`
85+
Modules []Module `json:"modules,omitempty"`
8486

8587
// Active Synchronization Settings
8688
// +optional
8789
Sync Sync `json:"sync,omitempty"`
8890
}
8991

92+
// KymaStatus defines the observed state of Kyma.
93+
type KymaStatus struct {
94+
// State signifies current state of Kyma.
95+
// Value can be one of ("Ready", "Processing", "Error", "Deleting").
96+
State State `json:"state,omitempty"`
97+
98+
// List of status conditions to indicate the status of a ServiceInstance.
99+
// +optional
100+
// +listType=map
101+
// +listMapKey=type
102+
Conditions []apimetav1.Condition `json:"conditions,omitempty"`
103+
104+
// Contains essential information about the current deployed module
105+
Modules []ModuleStatus `json:"modules,omitempty"`
106+
107+
// Active Channel
108+
// +optional
109+
ActiveChannel string `json:"activeChannel,omitempty"`
110+
111+
LastOperation `json:"lastOperation,omitempty"`
112+
}
113+
114+
type ModuleStatus struct {
115+
// Name defines the name of the Module in the Spec that the status is used for.
116+
// It can be any kind of Reference format supported by Module.Name.
117+
Name string `json:"name"`
118+
119+
// FQDN is the fully qualified domain name of the module.
120+
// In the ModuleTemplate it is located in .spec.descriptor.component.name of the ModuleTemplate
121+
// FQDN is used to calculate Namespace and Name of the Manifest for tracking.
122+
FQDN string `json:"fqdn,omitempty"`
123+
124+
// Channel tracks the active Channel of the Module. In Case it changes, the new Channel will have caused
125+
// a new lookup to be necessary that maybe picks a different ModuleTemplate, which is why we need to reconcile.
126+
Channel string `json:"channel,omitempty"`
127+
128+
// Channel tracks the active Version of the Module.
129+
Version string `json:"version,omitempty"`
130+
131+
// Message is a human-readable message indicating details about the State.
132+
Message string `json:"message,omitempty"`
133+
134+
// State of the Module in the currently tracked Generation
135+
State State `json:"state"`
136+
137+
// Manifest contains the Information of a related Manifest
138+
Manifest *TrackingObject `json:"manifest,omitempty"`
139+
140+
// Resource contains information about the created module CR.
141+
Resource *TrackingObject `json:"resource,omitempty"`
142+
143+
// It contains information about the last parsed ModuleTemplate in Context of the Installation.
144+
// This will update when Channel or the ModuleTemplate is changed.
145+
// +optional
146+
Template *TrackingObject `json:"template,omitempty"`
147+
}
148+
149+
// TrackingObject contains TypeMeta and PartialMeta to allow a generation based object tracking.
150+
// It purposefully does not use ObjectMeta as the generation of controller-runtime for crds would not validate
151+
// the generation fields even when embedding ObjectMeta.
152+
type TrackingObject struct {
153+
apimetav1.TypeMeta `json:",inline"`
154+
PartialMeta `json:"metadata,omitempty"`
155+
}
156+
157+
// PartialMeta is a subset of ObjectMeta that contains relevant information to track an Object.
158+
// see https://github.com/kubernetes/apimachinery/blob/v0.26.1/pkg/apis/meta/v1/types.go#L111
159+
type PartialMeta struct {
160+
// Name must be unique within a namespace. Is required when creating resources, although
161+
// some resources may allow a client to request the generation of an appropriate name
162+
// automatically. Name is primarily intended for creation idempotence and configuration
163+
// definition.
164+
// Cannot be updated.
165+
// More info: http://kubernetes.io/docs/user-guide/identifiers#names
166+
// +optional
167+
Name string `json:"name"`
168+
// Namespace defines the space within which each name must be unique. An empty namespace is
169+
// equivalent to the "default" namespace, but "default" is the canonical representation.
170+
// Not all objects are required to be scoped to a namespace - the value of this field for
171+
// those objects will be empty.
172+
//
173+
// Must be a DNS_LABEL.
174+
// Cannot be updated.
175+
// More info: http://kubernetes.io/docs/user-guide/namespaces
176+
// +optional
177+
Namespace string `json:"namespace"`
178+
// A sequence number representing a specific generation of the desired state.
179+
// Populated by the system. Read-only.
180+
// +optional
181+
Generation int64 `json:"generation,omitempty"`
182+
}
183+
90184
// +kubebuilder:object:root=true
91185

92186
// KymaList contains a list of Kyma.
@@ -96,6 +190,64 @@ type KymaList struct {
96190
Items []Kyma `json:"items"`
97191
}
98192

193+
// Module defines the components to be installed.
194+
type Module struct {
195+
// Name is a unique identifier of the module.
196+
// It is used to resolve a ModuleTemplate for creating a set of resources on the cluster.
197+
//
198+
// Name can only be the ModuleName label value of the module-template, e.g. operator.kyma-project.io/module-name=my-module
199+
Name string `json:"name"`
200+
201+
// ControllerName is able to set the controller used for reconciliation of the module. It can be used
202+
// together with Cache Configuration on the Operator responsible for the templated Modules to split
203+
// workload.
204+
ControllerName string `json:"controller,omitempty"`
205+
206+
// Channel is the desired channel of the Module. If this changes or is set, it will be used to resolve a new
207+
// ModuleTemplate based on the new resolved resources.
208+
// +kubebuilder:validation:Pattern:=^[a-z]+$
209+
// +kubebuilder:validation:MaxLength:=32
210+
// +kubebuilder:validation:MinLength:=3
211+
Channel string `json:"channel,omitempty"`
212+
213+
// Version is the desired version of the Module. If this changes or is set, it will be used to resolve a new
214+
// ModuleTemplate based on this specific version.
215+
// The Version and Channel are mutually exclusive options.
216+
// The regular expression come from here: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
217+
// json:"-" to disable installation of specific versions until decided to roll this out
218+
// see https://github.com/kyma-project/lifecycle-manager/issues/1847
219+
Version string `json:"-"`
220+
221+
// RemoteModuleTemplateRef is deprecated and will no longer have any functionality.
222+
// It will be removed in the upcoming API version.
223+
RemoteModuleTemplateRef string `json:"remoteModuleTemplateRef,omitempty"`
224+
225+
// +kubebuilder:default:=CreateAndDelete
226+
CustomResourcePolicy `json:"customResourcePolicy,omitempty"`
227+
228+
// Managed is determining whether the module is managed or not. If the module is unmanaged, the user is responsible
229+
// for the lifecycle of the module.
230+
// +kubebuilder:default:=true
231+
Managed bool `json:"managed"`
232+
}
233+
234+
// CustomResourcePolicy determines how a ModuleTemplate should be parsed. When CustomResourcePolicy is set to
235+
// CustomResourcePolicyCreateAndDelete, the Manifest will receive instructions to create it on installation with
236+
// the default values provided in ModuleTemplate, and to remove it when the module or Kyma is deleted.
237+
// +kubebuilder:validation:Enum=CreateAndDelete;Ignore
238+
type CustomResourcePolicy string
239+
240+
const (
241+
// CustomResourcePolicyCreateAndDelete causes the Manifest to contain the default data provided in ModuleTemplate.
242+
// While Updates from the Data are never propagated, the resource is deleted on module removal.
243+
CustomResourcePolicyCreateAndDelete = "CreateAndDelete"
244+
// CustomResourcePolicyIgnore does not pass the Data from ModuleTemplate.
245+
// This ensures the user of the module is able to initialize the Module without any default configuration.
246+
// This is useful if another controller should manage module configuration as data and not be auto-initialized.
247+
// It can also be used to initialize controllers without interacting with them.
248+
CustomResourcePolicyIgnore = "Ignore"
249+
)
250+
99251
//nolint:gochecknoinits // registers Kyma CRD on startup
100252
func init() {
101253
SchemeBuilder.Register(&Kyma{}, &KymaList{})

api/v1beta1/last_operation.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package v1beta1
2+
3+
import (
4+
apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5+
)
6+
7+
// LastOperation defines the last operation from the control-loop.
8+
// +k8s:deepcopy-gen=true
9+
type LastOperation struct {
10+
Operation string `json:"operation"`
11+
LastUpdateTime apimetav1.Time `json:"lastUpdateTime,omitempty"`
12+
}

api/v1beta1/manifest_types.go

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ package v1beta1
1818

1919
import (
2020
apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21-
22-
"github.com/kyma-project/lifecycle-manager/api/shared"
23-
"github.com/kyma-project/lifecycle-manager/api/v1beta2"
21+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
22+
machineryruntime "k8s.io/apimachinery/pkg/runtime"
2423
)
2524

2625
// +kubebuilder:object:root=true
@@ -35,10 +34,74 @@ type Manifest struct {
3534
apimetav1.TypeMeta `json:",inline"`
3635
apimetav1.ObjectMeta `json:"metadata,omitempty"`
3736

38-
Spec v1beta2.ManifestSpec `json:"spec,omitempty"`
39-
Status shared.Status `json:"status,omitempty"`
37+
Spec ManifestSpec `json:"spec,omitempty"`
38+
Status Status `json:"status,omitempty"`
39+
}
40+
41+
// ManifestSpec defines the desired state of Manifest.
42+
type ManifestSpec struct {
43+
// Remote indicates if Manifest should be installed on a remote cluster
44+
Remote bool `json:"remote"`
45+
46+
// Version specifies current Resource version
47+
// +optional
48+
Version string `json:"version,omitempty"`
49+
50+
// Config specifies OCI image configuration for Manifest
51+
Config *ImageSpec `json:"config,omitempty"`
52+
53+
// Install specifies a list of installations for Manifest
54+
Install InstallInfo `json:"install"`
55+
56+
// +kubebuilder:pruning:PreserveUnknownFields
57+
// +kubebuilder:validation:XEmbeddedResource
58+
// +nullable
59+
// Resource specifies a resource to be watched for state updates
60+
Resource *unstructured.Unstructured `json:"resource,omitempty"`
61+
62+
// +kubebuilder:default:=CreateAndDelete
63+
CustomResourcePolicy `json:"customResourcePolicy,omitempty"`
64+
}
65+
66+
// InstallInfo defines installation information.
67+
type InstallInfo struct {
68+
// Source in the ImageSpec format
69+
// +kubebuilder:pruning:PreserveUnknownFields
70+
Source machineryruntime.RawExtension `json:"source"`
71+
72+
// Name specifies a unique install name for Manifest
73+
Name string `json:"name"`
74+
}
75+
76+
// ImageSpec defines OCI Image specifications.
77+
// +k8s:deepcopy-gen=true
78+
type ImageSpec struct {
79+
// Repo defines the Image repo
80+
Repo string `json:"repo,omitempty"`
81+
82+
// Name defines the Image name
83+
Name string `json:"name,omitempty"`
84+
85+
// Ref is either a sha value, tag or version
86+
Ref string `json:"ref,omitempty"`
87+
88+
// Type specifies the type of installation specification
89+
// that could be provided as part of a custom resource.
90+
// This time is used in codec to successfully decode from raw extensions.
91+
// +kubebuilder:validation:Enum=helm-chart;oci-ref;"kustomize";""
92+
Type RefTypeMetadata `json:"type,omitempty"`
93+
94+
// Deprecated: Field will be removed soon and is not supported anymore.
95+
CredSecretSelector *apimetav1.LabelSelector `json:"credSecretSelector,omitempty"`
4096
}
4197

98+
type RefTypeMetadata string
99+
100+
const (
101+
OciRefType RefTypeMetadata = "oci-ref"
102+
OciDirType RefTypeMetadata = "oci-dir"
103+
)
104+
42105
// +kubebuilder:object:root=true
43106

44107
// ManifestList contains a list of Manifest.

api/v1beta1/moduletemplate_types.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ import (
2020
apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2121
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2222
machineryruntime "k8s.io/apimachinery/pkg/runtime"
23-
24-
"github.com/kyma-project/lifecycle-manager/api/v1beta2"
2523
)
2624

2725
// ModuleTemplate is a representation of a Template used for creating Module Instances within the Module Lifecycle.
@@ -84,13 +82,24 @@ type ModuleTemplateSpec struct {
8482
// hint by downstream controllers to determine which client implementation to use for working with the Module
8583
Target Target `json:"target"`
8684

87-
CustomStateCheck []*v1beta2.CustomStateCheck `json:"customStateCheck,omitempty"`
85+
CustomStateCheck []*CustomStateCheck `json:"customStateCheck,omitempty"`
8886

8987
// RequiresDowntime indicates whether the module requires downtime in support of maintenance windows during module upgrades.
9088
// +optional
9189
RequiresDowntime bool `json:"requiresDowntime,omitempty"`
9290
}
9391

92+
type CustomStateCheck struct {
93+
// JSONPath specifies the JSON path to the state variable in the Module CR
94+
JSONPath string `json:"jsonPath" yaml:"jsonPath"`
95+
96+
// Value is the value at the JSONPath for which the Module CR state should map with MappedState
97+
Value string `json:"value" yaml:"value"`
98+
99+
// MappedState is the Kyma CR State
100+
MappedState State `json:"mappedState" yaml:"mappedState"`
101+
}
102+
94103
// +kubebuilder:object:root=true
95104

96105
// ModuleTemplateList contains a list of ModuleTemplate.

api/v1beta1/resource.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package v1beta1
2+
3+
import (
4+
"strings"
5+
6+
apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
8+
"k8s.io/apimachinery/pkg/runtime/schema"
9+
)
10+
11+
// +k8s:deepcopy-gen=true
12+
type Resource struct {
13+
Name string `json:"name"`
14+
Namespace string `json:"namespace"`
15+
apimetav1.GroupVersionKind `json:",inline"`
16+
}
17+
18+
func (r Resource) ToUnstructured() *unstructured.Unstructured {
19+
obj := unstructured.Unstructured{}
20+
obj.SetGroupVersionKind(schema.GroupVersionKind(r.GroupVersionKind))
21+
obj.SetName(r.Name)
22+
obj.SetNamespace(r.Namespace)
23+
return &obj
24+
}
25+
26+
func (r Resource) ID() string {
27+
return strings.Join([]string{r.Namespace, r.Name, r.Group, r.Version, r.Kind}, "/")
28+
}

0 commit comments

Comments
 (0)