1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
use super::*;

mod impls;

/// MachineTemplateSpec describes the data needed to create a Machine from a template.
#[skip_serializing_none]
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MachineTemplateSpec {
    /// Standard object's metadata.
    /// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
    // +optional
    pub metadata: Option<metav1::ObjectMeta>, // `json:"metadata,omitempty"`

    /// Specification of the desired behavior of the machine.
    /// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
    // +optional
    pub spec: Option<MachineSpec>, // `json:"spec,omitempty"`
}

/*

package v1beta1

import (
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
    "k8s.io/apimachinery/pkg/labels"
    "k8s.io/apimachinery/pkg/util/validation/field"

    capierrors "sigs.k8s.io/cluster-api/errors"
)

const (
    // MachineSetTopologyFinalizer is the finalizer used by the topology MachineDeployment controller to
    // clean up referenced template resources if necessary when a MachineSet is being deleted.
    MachineSetTopologyFinalizer = "machineset.topology.cluster.x-k8s.io"
)

// ANCHOR: MachineSetSpec

// MachineSetSpec defines the desired state of MachineSet.
type MachineSetSpec struct {
    // ClusterName is the name of the Cluster this object belongs to.
    // +kubebuilder:validation:MinLength=1
    ClusterName string `json:"clusterName"`

    // Replicas is the number of desired replicas.
    // This is a pointer to distinguish between explicit zero and unspecified.
    // Defaults to 1.
    // +optional
    // +kubebuilder:default=1
    Replicas *int32 `json:"replicas,omitempty"`

    // MinReadySeconds is the minimum number of seconds for which a newly created machine should be ready.
    // Defaults to 0 (machine will be considered available as soon as it is ready)
    // +optional
    MinReadySeconds int32 `json:"minReadySeconds,omitempty"`

    // DeletePolicy defines the policy used to identify nodes to delete when downscaling.
    // Defaults to "Random".  Valid values are "Random, "Newest", "Oldest"
    // +kubebuilder:validation:Enum=Random;Newest;Oldest
    // +optional
    DeletePolicy string `json:"deletePolicy,omitempty"`

    // Selector is a label query over machines that should match the replica count.
    // Label keys and values that must match in order to be controlled by this MachineSet.
    // It must match the machine template's labels.
    // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
    Selector metav1.LabelSelector `json:"selector"`

    // Template is the object that describes the machine that will be created if
    // insufficient replicas are detected.
    // Object references to custom resources resources are treated as templates.
    // +optional
    Template MachineTemplateSpec `json:"template,omitempty"`
}

// ANCHOR_END: MachineSetSpec

// ANCHOR: MachineTemplateSpec

// ANCHOR_END: MachineTemplateSpec

// MachineSetDeletePolicy defines how priority is assigned to nodes to delete when
// downscaling a MachineSet. Defaults to "Random".
type MachineSetDeletePolicy string

const (
    // RandomMachineSetDeletePolicy prioritizes both Machines that have the annotation
    // "cluster.x-k8s.io/delete-machine=yes" and Machines that are unhealthy
    // (Status.FailureReason or Status.FailureMessage are set to a non-empty value).
    // Finally, it picks Machines at random to delete.
    RandomMachineSetDeletePolicy MachineSetDeletePolicy = "Random"

    // NewestMachineSetDeletePolicy prioritizes both Machines that have the annotation
    // "cluster.x-k8s.io/delete-machine=yes" and Machines that are unhealthy
    // (Status.FailureReason or Status.FailureMessage are set to a non-empty value).
    // It then prioritizes the newest Machines for deletion based on the Machine's CreationTimestamp.
    NewestMachineSetDeletePolicy MachineSetDeletePolicy = "Newest"

    // OldestMachineSetDeletePolicy prioritizes both Machines that have the annotation
    // "cluster.x-k8s.io/delete-machine=yes" and Machines that are unhealthy
    // (Status.FailureReason or Status.FailureMessage are set to a non-empty value).
    // It then prioritizes the oldest Machines for deletion based on the Machine's CreationTimestamp.
    OldestMachineSetDeletePolicy MachineSetDeletePolicy = "Oldest"
)

// ANCHOR: MachineSetStatus

// MachineSetStatus defines the observed state of MachineSet.
type MachineSetStatus struct {
    // Selector is the same as the label selector but in the string format to avoid introspection
    // by clients. The string will be in the same format as the query-param syntax.
    // More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors
    // +optional
    Selector string `json:"selector,omitempty"`

    // Replicas is the most recently observed number of replicas.
    // +optional
    Replicas int32 `json:"replicas"`

    // The number of replicas that have labels matching the labels of the machine template of the MachineSet.
    // +optional
    FullyLabeledReplicas int32 `json:"fullyLabeledReplicas"`

    // The number of ready replicas for this MachineSet. A machine is considered ready when the node has been created and is "Ready".
    // +optional
    ReadyReplicas int32 `json:"readyReplicas"`

    // The number of available replicas (ready for at least minReadySeconds) for this MachineSet.
    // +optional
    AvailableReplicas int32 `json:"availableReplicas"`

    // ObservedGeneration reflects the generation of the most recently observed MachineSet.
    // +optional
    ObservedGeneration int64 `json:"observedGeneration,omitempty"`

    // In the event that there is a terminal problem reconciling the
    // replicas, both FailureReason and FailureMessage will be set. FailureReason
    // will be populated with a succinct value suitable for machine
    // interpretation, while FailureMessage will contain a more verbose
    // string suitable for logging and human consumption.
    //
    // These fields should not be set for transitive errors that a
    // controller faces that are expected to be fixed automatically over
    // time (like service outages), but instead indicate that something is
    // fundamentally wrong with the MachineTemplate's spec or the configuration of
    // the machine controller, and that manual intervention is required. Examples
    // of terminal errors would be invalid combinations of settings in the
    // spec, values that are unsupported by the machine controller, or the
    // responsible machine controller itself being critically misconfigured.
    //
    // Any transient errors that occur during the reconciliation of Machines
    // can be added as events to the MachineSet object and/or logged in the
    // controller's output.
    // +optional
    FailureReason *capierrors.MachineSetStatusError `json:"failureReason,omitempty"`
    // +optional
    FailureMessage *string `json:"failureMessage,omitempty"`
    // Conditions defines current service state of the MachineSet.
    // +optional
    Conditions Conditions `json:"conditions,omitempty"`
}

// ANCHOR_END: MachineSetStatus

// Validate validates the MachineSet fields.
func (m *MachineSet) Validate() field.ErrorList {
    errors := field.ErrorList{}

    // validate spec.selector and spec.template.labels
    fldPath := field.NewPath("spec")
    errors = append(errors, metav1validation.ValidateLabelSelector(&m.Spec.Selector, fldPath.Child("selector"))...)
    if len(m.Spec.Selector.MatchLabels)+len(m.Spec.Selector.MatchExpressions) == 0 {
        errors = append(errors, field.Invalid(fldPath.Child("selector"), m.Spec.Selector, "empty selector is not valid for MachineSet."))
    }
    selector, err := metav1.LabelSelectorAsSelector(&m.Spec.Selector)
    if err != nil {
        errors = append(errors, field.Invalid(fldPath.Child("selector"), m.Spec.Selector, "invalid label selector."))
    } else {
        labels := labels.Set(m.Spec.Template.Labels)
        if !selector.Matches(labels) {
            errors = append(errors, field.Invalid(fldPath.Child("template", "metadata", "labels"), m.Spec.Template.Labels, "`selector` does not match template `labels`"))
        }
    }

    return errors
}

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=machinesets,shortName=ms,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion
// +kubebuilder:subresource:status
// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector
// +kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".spec.clusterName",description="Cluster"
// +kubebuilder:printcolumn:name="Replicas",type="integer",JSONPath=".status.replicas",description="Total number of non-terminated machines targeted by this machineset"
// +kubebuilder:printcolumn:name="Ready",type="integer",JSONPath=".status.readyReplicas",description="Total number of ready machines targeted by this machineset."
// +kubebuilder:printcolumn:name="Available",type="integer",JSONPath=".status.availableReplicas",description="Total number of available machines (ready for at least minReadySeconds)"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of MachineSet"
// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".spec.template.spec.version",description="Kubernetes version associated with this MachineSet"

// MachineSet is the Schema for the machinesets API.
type MachineSet struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   MachineSetSpec   `json:"spec,omitempty"`
    Status MachineSetStatus `json:"status,omitempty"`
}

// GetConditions returns the set of conditions for the MachineSet.
func (m *MachineSet) GetConditions() Conditions {
    return m.Status.Conditions
}

// SetConditions updates the set of conditions on the MachineSet.
func (m *MachineSet) SetConditions(conditions Conditions) {
    m.Status.Conditions = conditions
}

// +kubebuilder:object:root=true

// MachineSetList contains a list of MachineSet.
type MachineSetList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []MachineSet `json:"items"`
}

func init() {
    SchemeBuilder.Register(&MachineSet{}, &MachineSetList{})
}

*/