Promote Advacned StatefulSet to v1beta1 (#423)

This commit is contained in:
Siyu Wang 2020-11-03 02:01:04 +08:00 committed by GitHub
parent ffb3f87eec
commit dbe481e5d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
106 changed files with 6620 additions and 919 deletions

View File

@ -1,8 +1,8 @@
# Image URL to use all building/pushing image targets
IMG ?= openkruise/kruise-manager:test
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
CRD_OPTIONS ?= "crd:trivialVersions=true"
# Produce CRDs that work for API servers that supports v1beta1 CRD and conversion, requires k8s 1.13 or later.
CRD_OPTIONS ?= "crd"
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
@ -69,18 +69,18 @@ docker-push:
# find or download controller-gen
# download controller-gen if necessary
controller-gen:
ifeq (, $(shell which controller-gen-kruise))
ifeq (, $(shell which controller-gen-kruise-2))
@{ \
set -e ;\
CONTROLLER_GEN_TMP_DIR=$$(mktemp -d) ;\
cd $$CONTROLLER_GEN_TMP_DIR ;\
go mod init tmp ;\
echo "replace sigs.k8s.io/controller-tools => github.com/openkruise/controller-tools v0.2.9-kruise" >> go.mod ;\
echo "replace sigs.k8s.io/controller-tools => github.com/openkruise/controller-tools v0.2.9-kruise.2" >> go.mod ;\
go get sigs.k8s.io/controller-tools/cmd/controller-gen@v0.2.9 ;\
rm -rf $$CONTROLLER_GEN_TMP_DIR ;\
mv $(GOPATH)/bin/controller-gen $(GOPATH)/bin/controller-gen-kruise ;\
mv $(GOPATH)/bin/controller-gen $(GOPATH)/bin/controller-gen-kruise-2 ;\
}
CONTROLLER_GEN=$(GOPATH)/bin/controller-gen-kruise
CONTROLLER_GEN=$(GOPATH)/bin/controller-gen-kruise-2
else
CONTROLLER_GEN=$(shell which controller-gen-kruise)
CONTROLLER_GEN=$(shell which controller-gen-kruise-2)
endif

View File

@ -26,4 +26,7 @@ resources:
- group: apps
kind: ImagePullJob
version: v1alpha1
- group: apps
kind: StatefulSet
version: v1beta1
version: "2"

View File

@ -0,0 +1,26 @@
/*
Copyright 2020 The Kruise 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 apis
import (
"github.com/openkruise/kruise/apis/apps/v1beta1"
)
func init() {
// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
AddToSchemes = append(AddToSchemes, v1beta1.SchemeBuilder.AddToScheme)
}

18
apis/apps/pub/doc.go Normal file
View File

@ -0,0 +1,18 @@
/*
Copyright 2020 The Kruise 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.
*/
// +kubebuilder:object:generate=true
package pub

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
package pub
import (
v1 "k8s.io/api/core/v1"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
package pub
const (
LifecycleStateKey = "lifecycle.apps.kruise.io/state"

View File

@ -14,9 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
package pub
import (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -53,3 +55,34 @@ type UpdatePriorityWeightTerm struct {
// MatchSelector is used to select by pod's labels.
MatchSelector metav1.LabelSelector `json:"matchSelector"`
}
// FieldsValidation checks invalid fields in UpdatePriorityStrategy.
func (strategy *UpdatePriorityStrategy) FieldsValidation() error {
if strategy == nil {
return nil
}
if len(strategy.WeightPriority) > 0 && len(strategy.OrderPriority) > 0 {
return fmt.Errorf("only one of weightPriority and orderPriority can be used")
}
for _, w := range strategy.WeightPriority {
if w.Weight < 0 || w.Weight > 100 {
return fmt.Errorf("weight must be valid number in the range 1-100")
}
if w.MatchSelector.Size() == 0 {
return fmt.Errorf("selector can not be empty")
}
if _, err := metav1.LabelSelectorAsSelector(&w.MatchSelector); err != nil {
return fmt.Errorf("invalid selector %v", err)
}
}
for _, o := range strategy.OrderPriority {
if len(o.OrderedKey) == 0 {
return fmt.Errorf("order key can not be empty")
}
}
return nil
}

View File

@ -0,0 +1,186 @@
// +build !ignore_autogenerated
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by controller-gen. DO NOT EDIT.
package pub
import ()
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InPlaceUpdateContainerStatus) DeepCopyInto(out *InPlaceUpdateContainerStatus) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InPlaceUpdateContainerStatus.
func (in *InPlaceUpdateContainerStatus) DeepCopy() *InPlaceUpdateContainerStatus {
if in == nil {
return nil
}
out := new(InPlaceUpdateContainerStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InPlaceUpdateState) DeepCopyInto(out *InPlaceUpdateState) {
*out = *in
in.UpdateTimestamp.DeepCopyInto(&out.UpdateTimestamp)
if in.LastContainerStatuses != nil {
in, out := &in.LastContainerStatuses, &out.LastContainerStatuses
*out = make(map[string]InPlaceUpdateContainerStatus, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InPlaceUpdateState.
func (in *InPlaceUpdateState) DeepCopy() *InPlaceUpdateState {
if in == nil {
return nil
}
out := new(InPlaceUpdateState)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InPlaceUpdateStrategy) DeepCopyInto(out *InPlaceUpdateStrategy) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InPlaceUpdateStrategy.
func (in *InPlaceUpdateStrategy) DeepCopy() *InPlaceUpdateStrategy {
if in == nil {
return nil
}
out := new(InPlaceUpdateStrategy)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Lifecycle) DeepCopyInto(out *Lifecycle) {
*out = *in
if in.PreDelete != nil {
in, out := &in.PreDelete, &out.PreDelete
*out = new(LifecycleHook)
(*in).DeepCopyInto(*out)
}
if in.InPlaceUpdate != nil {
in, out := &in.InPlaceUpdate, &out.InPlaceUpdate
*out = new(LifecycleHook)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Lifecycle.
func (in *Lifecycle) DeepCopy() *Lifecycle {
if in == nil {
return nil
}
out := new(Lifecycle)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LifecycleHook) DeepCopyInto(out *LifecycleHook) {
*out = *in
if in.LabelsHandler != nil {
in, out := &in.LabelsHandler, &out.LabelsHandler
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.FinalizersHandler != nil {
in, out := &in.FinalizersHandler, &out.FinalizersHandler
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LifecycleHook.
func (in *LifecycleHook) DeepCopy() *LifecycleHook {
if in == nil {
return nil
}
out := new(LifecycleHook)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdatePriorityOrderTerm) DeepCopyInto(out *UpdatePriorityOrderTerm) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdatePriorityOrderTerm.
func (in *UpdatePriorityOrderTerm) DeepCopy() *UpdatePriorityOrderTerm {
if in == nil {
return nil
}
out := new(UpdatePriorityOrderTerm)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdatePriorityStrategy) DeepCopyInto(out *UpdatePriorityStrategy) {
*out = *in
if in.OrderPriority != nil {
in, out := &in.OrderPriority, &out.OrderPriority
*out = make([]UpdatePriorityOrderTerm, len(*in))
copy(*out, *in)
}
if in.WeightPriority != nil {
in, out := &in.WeightPriority, &out.WeightPriority
*out = make([]UpdatePriorityWeightTerm, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdatePriorityStrategy.
func (in *UpdatePriorityStrategy) DeepCopy() *UpdatePriorityStrategy {
if in == nil {
return nil
}
out := new(UpdatePriorityStrategy)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdatePriorityWeightTerm) DeepCopyInto(out *UpdatePriorityWeightTerm) {
*out = *in
in.MatchSelector.DeepCopyInto(&out.MatchSelector)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdatePriorityWeightTerm.
func (in *UpdatePriorityWeightTerm) DeepCopy() *UpdatePriorityWeightTerm {
if in == nil {
return nil
}
out := new(UpdatePriorityWeightTerm)
in.DeepCopyInto(out)
return out
}

View File

@ -17,6 +17,9 @@ limitations under the License.
package v1alpha1
import (
"fmt"
appspub "github.com/openkruise/kruise/apis/apps/pub"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
@ -71,7 +74,7 @@ type CloneSetSpec struct {
MinReadySeconds int32 `json:"minReadySeconds,omitempty"`
// Lifecycle defines the lifecycle hooks for Pods pre-delete, in-place update.
Lifecycle *Lifecycle `json:"lifecycle,omitempty"`
Lifecycle *appspub.Lifecycle `json:"lifecycle,omitempty"`
}
// CloneSetScaleStrategy defines strategies for pods scale.
@ -106,14 +109,14 @@ type CloneSetUpdateStrategy struct {
Paused bool `json:"paused,omitempty"`
// Priorities are the rules for calculating the priority of updating pods.
// Each pod to be updated, will pass through these terms and get a sum of weights.
PriorityStrategy *UpdatePriorityStrategy `json:"priorityStrategy,omitempty"`
PriorityStrategy *appspub.UpdatePriorityStrategy `json:"priorityStrategy,omitempty"`
// ScatterStrategy defines the scatter rules to make pods been scattered when update.
// This will avoid pods with the same key-value to be updated in one batch.
// - Note that pods will be scattered after priority sort. So, although priority strategy and scatter strategy can be applied together, we suggest to use either one of them.
// - If scatterStrategy is used, we suggest to just use one term. Otherwise, the update order can be hard to understand.
ScatterStrategy CloneSetUpdateScatterStrategy `json:"scatterStrategy,omitempty"`
// InPlaceUpdateStrategy contains strategies for in-place update.
InPlaceUpdateStrategy *InPlaceUpdateStrategy `json:"inPlaceUpdateStrategy,omitempty"`
InPlaceUpdateStrategy *appspub.InPlaceUpdateStrategy `json:"inPlaceUpdateStrategy,omitempty"`
}
// CloneSetUpdateStrategyType defines strategies for pods in-place update.
@ -148,6 +151,28 @@ type CloneSetUpdateScatterTerm struct {
Value string `json:"value"`
}
// FieldsValidation checks invalid fields in CloneSetUpdateScatterStrategy.
func (strategy CloneSetUpdateScatterStrategy) FieldsValidation() error {
if len(strategy) == 0 {
return nil
}
m := make(map[string]struct{}, len(strategy))
for _, term := range strategy {
if term.Key == "" {
return fmt.Errorf("key should not be empty")
}
id := term.Key + ":" + term.Value
if _, ok := m[id]; !ok {
m[id] = struct{}{}
} else {
return fmt.Errorf("duplicated key=%v value=%v", term.Key, term.Value)
}
}
return nil
}
// CloneSetStatus defines the observed state of CloneSet
type CloneSetStatus struct {
// ObservedGeneration is the most recent generation observed for this CloneSet. It corresponds to the

View File

@ -17,6 +17,7 @@ limitations under the License.
package v1alpha1
import (
appspub "github.com/openkruise/kruise/apis/apps/pub"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/intstr"
@ -210,7 +211,7 @@ func SetDefaultsCloneSet(obj *CloneSet) {
obj.Spec.UpdateStrategy.Type = RecreateCloneSetUpdateStrategyType
case InPlaceIfPossibleCloneSetUpdateStrategyType, InPlaceOnlyCloneSetUpdateStrategyType:
if obj.Spec.UpdateStrategy.InPlaceUpdateStrategy == nil {
obj.Spec.UpdateStrategy.InPlaceUpdateStrategy = &InPlaceUpdateStrategy{}
obj.Spec.UpdateStrategy.InPlaceUpdateStrategy = &appspub.InPlaceUpdateStrategy{}
}
}

View File

@ -0,0 +1,137 @@
/*
Copyright 2020 The Kruise 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 (
"fmt"
"github.com/openkruise/kruise/apis/apps/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/conversion"
)
func (sts *StatefulSet) ConvertTo(dst conversion.Hub) error {
switch t := dst.(type) {
case *v1beta1.StatefulSet:
stsv1beta1 := dst.(*v1beta1.StatefulSet)
stsv1beta1.ObjectMeta = sts.ObjectMeta
// spec
stsv1beta1.Spec = v1beta1.StatefulSetSpec{
Replicas: sts.Spec.Replicas,
Selector: sts.Spec.Selector,
Template: sts.Spec.Template,
VolumeClaimTemplates: sts.Spec.VolumeClaimTemplates,
ServiceName: sts.Spec.ServiceName,
PodManagementPolicy: sts.Spec.PodManagementPolicy,
UpdateStrategy: v1beta1.StatefulSetUpdateStrategy{
Type: sts.Spec.UpdateStrategy.Type,
},
RevisionHistoryLimit: sts.Spec.RevisionHistoryLimit,
}
if sts.Spec.UpdateStrategy.RollingUpdate != nil {
stsv1beta1.Spec.UpdateStrategy.RollingUpdate = &v1beta1.RollingUpdateStatefulSetStrategy{
Partition: sts.Spec.UpdateStrategy.RollingUpdate.Partition,
MaxUnavailable: sts.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable,
PodUpdatePolicy: v1beta1.PodUpdateStrategyType(sts.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy),
Paused: sts.Spec.UpdateStrategy.RollingUpdate.Paused,
InPlaceUpdateStrategy: sts.Spec.UpdateStrategy.RollingUpdate.InPlaceUpdateStrategy,
MinReadySeconds: sts.Spec.UpdateStrategy.RollingUpdate.MinReadySeconds,
}
if sts.Spec.UpdateStrategy.RollingUpdate.UnorderedUpdate != nil {
stsv1beta1.Spec.UpdateStrategy.RollingUpdate.UnorderedUpdate = &v1beta1.UnorderedUpdateStrategy{
PriorityStrategy: sts.Spec.UpdateStrategy.RollingUpdate.UnorderedUpdate.PriorityStrategy,
}
}
}
// status
stsv1beta1.Status = v1beta1.StatefulSetStatus{
ObservedGeneration: sts.Status.ObservedGeneration,
Replicas: sts.Status.Replicas,
ReadyReplicas: sts.Status.ReadyReplicas,
AvailableReplicas: sts.Status.AvailableReplicas,
CurrentReplicas: sts.Status.CurrentReplicas,
UpdatedReplicas: sts.Status.UpdatedReplicas,
CurrentRevision: sts.Status.CurrentRevision,
UpdateRevision: sts.Status.UpdateRevision,
CollisionCount: sts.Status.CollisionCount,
Conditions: sts.Status.Conditions,
LabelSelector: sts.Status.LabelSelector,
}
return nil
default:
return fmt.Errorf("unsupported type %v", t)
}
}
func (sts *StatefulSet) ConvertFrom(src conversion.Hub) error {
switch t := src.(type) {
case *v1beta1.StatefulSet:
stsv1beta1 := src.(*v1beta1.StatefulSet)
sts.ObjectMeta = stsv1beta1.ObjectMeta
// spec
sts.Spec = StatefulSetSpec{
Replicas: stsv1beta1.Spec.Replicas,
Selector: stsv1beta1.Spec.Selector,
Template: stsv1beta1.Spec.Template,
VolumeClaimTemplates: stsv1beta1.Spec.VolumeClaimTemplates,
ServiceName: stsv1beta1.Spec.ServiceName,
PodManagementPolicy: stsv1beta1.Spec.PodManagementPolicy,
UpdateStrategy: StatefulSetUpdateStrategy{
Type: stsv1beta1.Spec.UpdateStrategy.Type,
},
RevisionHistoryLimit: stsv1beta1.Spec.RevisionHistoryLimit,
}
if stsv1beta1.Spec.UpdateStrategy.RollingUpdate != nil {
sts.Spec.UpdateStrategy.RollingUpdate = &RollingUpdateStatefulSetStrategy{
Partition: stsv1beta1.Spec.UpdateStrategy.RollingUpdate.Partition,
MaxUnavailable: stsv1beta1.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable,
PodUpdatePolicy: PodUpdateStrategyType(stsv1beta1.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy),
Paused: stsv1beta1.Spec.UpdateStrategy.RollingUpdate.Paused,
InPlaceUpdateStrategy: stsv1beta1.Spec.UpdateStrategy.RollingUpdate.InPlaceUpdateStrategy,
MinReadySeconds: stsv1beta1.Spec.UpdateStrategy.RollingUpdate.MinReadySeconds,
}
if stsv1beta1.Spec.UpdateStrategy.RollingUpdate.UnorderedUpdate != nil {
sts.Spec.UpdateStrategy.RollingUpdate.UnorderedUpdate = &UnorderedUpdateStrategy{
PriorityStrategy: stsv1beta1.Spec.UpdateStrategy.RollingUpdate.UnorderedUpdate.PriorityStrategy,
}
}
}
// status
sts.Status = StatefulSetStatus{
ObservedGeneration: stsv1beta1.Status.ObservedGeneration,
Replicas: stsv1beta1.Status.Replicas,
ReadyReplicas: stsv1beta1.Status.ReadyReplicas,
AvailableReplicas: stsv1beta1.Status.AvailableReplicas,
CurrentReplicas: stsv1beta1.Status.CurrentReplicas,
UpdatedReplicas: stsv1beta1.Status.UpdatedReplicas,
CurrentRevision: stsv1beta1.Status.CurrentRevision,
UpdateRevision: stsv1beta1.Status.UpdateRevision,
CollisionCount: stsv1beta1.Status.CollisionCount,
Conditions: stsv1beta1.Status.Conditions,
LabelSelector: stsv1beta1.Status.LabelSelector,
}
return nil
default:
return fmt.Errorf("unsupported type %v", t)
}
}

View File

@ -17,6 +17,7 @@ limitations under the License.
package v1alpha1
import (
appspub "github.com/openkruise/kruise/apis/apps/pub"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -72,7 +73,7 @@ type RollingUpdateStatefulSetStrategy struct {
UnorderedUpdate *UnorderedUpdateStrategy `json:"unorderedUpdate,omitempty"`
// InPlaceUpdateStrategy contains strategies for in-place update.
// +optional
InPlaceUpdateStrategy *InPlaceUpdateStrategy `json:"inPlaceUpdateStrategy,omitempty"`
InPlaceUpdateStrategy *appspub.InPlaceUpdateStrategy `json:"inPlaceUpdateStrategy,omitempty"`
// MinReadySeconds indicates how long will the pod be considered ready after it's updated.
// MinReadySeconds works with both OrderedReady and Parallel podManagementPolicy.
// It affects the pod scale up speed when the podManagementPolicy is set to be OrderedReady.
@ -87,7 +88,7 @@ type UnorderedUpdateStrategy struct {
// Priorities are the rules for calculating the priority of updating pods.
// Each pod to be updated, will pass through these terms and get a sum of weights.
// +optional
PriorityStrategy *UpdatePriorityStrategy `json:"priorityStrategy,omitempty"`
PriorityStrategy *appspub.UpdatePriorityStrategy `json:"priorityStrategy,omitempty"`
}
// PodUpdateStrategyType is a string enumeration type that enumerates

View File

@ -94,17 +94,20 @@ type SubsetTemplate struct {
// StatefulSetTemplateSpec defines the subset template of StatefulSet.
type StatefulSetTemplateSpec struct {
// +kubebuilder:validation:XPreserveUnknownFields
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec appsv1.StatefulSetSpec `json:"spec"`
}
// AdvancedStatefulSetTemplateSpec defines the subset template of AdvancedStatefulSet.
type AdvancedStatefulSetTemplateSpec struct {
// +kubebuilder:validation:XPreserveUnknownFields
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec StatefulSetSpec `json:"spec"`
}
type CloneSetTemplateSpec struct {
// +kubebuilder:validation:XPreserveUnknownFields
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec CloneSetSpec `json:"spec"`
}

View File

@ -1,76 +0,0 @@
/*
Copyright 2020 The Kruise 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 (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// FieldsValidation checks invalid fields in UpdatePriorityStrategy.
func (strategy *UpdatePriorityStrategy) FieldsValidation() error {
if strategy == nil {
return nil
}
if len(strategy.WeightPriority) > 0 && len(strategy.OrderPriority) > 0 {
return fmt.Errorf("only one of weightPriority and orderPriority can be used")
}
for _, w := range strategy.WeightPriority {
if w.Weight < 0 || w.Weight > 100 {
return fmt.Errorf("weight must be valid number in the range 1-100")
}
if w.MatchSelector.Size() == 0 {
return fmt.Errorf("selector can not be empty")
}
if _, err := metav1.LabelSelectorAsSelector(&w.MatchSelector); err != nil {
return fmt.Errorf("invalid selector %v", err)
}
}
for _, o := range strategy.OrderPriority {
if len(o.OrderedKey) == 0 {
return fmt.Errorf("order key can not be empty")
}
}
return nil
}
// FieldsValidation checks invalid fields in CloneSetUpdateScatterStrategy.
func (strategy CloneSetUpdateScatterStrategy) FieldsValidation() error {
if len(strategy) == 0 {
return nil
}
m := make(map[string]struct{}, len(strategy))
for _, term := range strategy {
if term.Key == "" {
return fmt.Errorf("key should not be empty")
}
id := term.Key + ":" + term.Value
if _, ok := m[id]; !ok {
m[id] = struct{}{}
} else {
return fmt.Errorf("duplicated key=%v value=%v", term.Key, term.Value)
}
}
return nil
}

View File

@ -21,6 +21,7 @@ limitations under the License.
package v1alpha1
import (
"github.com/openkruise/kruise/apis/apps/pub"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1"
@ -282,7 +283,7 @@ func (in *CloneSetSpec) DeepCopyInto(out *CloneSetSpec) {
}
if in.Lifecycle != nil {
in, out := &in.Lifecycle, &out.Lifecycle
*out = new(Lifecycle)
*out = new(pub.Lifecycle)
(*in).DeepCopyInto(*out)
}
}
@ -395,7 +396,7 @@ func (in *CloneSetUpdateStrategy) DeepCopyInto(out *CloneSetUpdateStrategy) {
}
if in.PriorityStrategy != nil {
in, out := &in.PriorityStrategy, &out.PriorityStrategy
*out = new(UpdatePriorityStrategy)
*out = new(pub.UpdatePriorityStrategy)
(*in).DeepCopyInto(*out)
}
if in.ScatterStrategy != nil {
@ -405,7 +406,7 @@ func (in *CloneSetUpdateStrategy) DeepCopyInto(out *CloneSetUpdateStrategy) {
}
if in.InPlaceUpdateStrategy != nil {
in, out := &in.InPlaceUpdateStrategy, &out.InPlaceUpdateStrategy
*out = new(InPlaceUpdateStrategy)
*out = new(pub.InPlaceUpdateStrategy)
**out = **in
}
}
@ -873,59 +874,6 @@ func (in *ImageTagStatus) DeepCopy() *ImageTagStatus {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InPlaceUpdateContainerStatus) DeepCopyInto(out *InPlaceUpdateContainerStatus) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InPlaceUpdateContainerStatus.
func (in *InPlaceUpdateContainerStatus) DeepCopy() *InPlaceUpdateContainerStatus {
if in == nil {
return nil
}
out := new(InPlaceUpdateContainerStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InPlaceUpdateState) DeepCopyInto(out *InPlaceUpdateState) {
*out = *in
in.UpdateTimestamp.DeepCopyInto(&out.UpdateTimestamp)
if in.LastContainerStatuses != nil {
in, out := &in.LastContainerStatuses, &out.LastContainerStatuses
*out = make(map[string]InPlaceUpdateContainerStatus, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InPlaceUpdateState.
func (in *InPlaceUpdateState) DeepCopy() *InPlaceUpdateState {
if in == nil {
return nil
}
out := new(InPlaceUpdateState)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InPlaceUpdateStrategy) DeepCopyInto(out *InPlaceUpdateStrategy) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InPlaceUpdateStrategy.
func (in *InPlaceUpdateStrategy) DeepCopy() *InPlaceUpdateStrategy {
if in == nil {
return nil
}
out := new(InPlaceUpdateStrategy)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JobCondition) DeepCopyInto(out *JobCondition) {
*out = *in
@ -943,58 +891,6 @@ func (in *JobCondition) DeepCopy() *JobCondition {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Lifecycle) DeepCopyInto(out *Lifecycle) {
*out = *in
if in.PreDelete != nil {
in, out := &in.PreDelete, &out.PreDelete
*out = new(LifecycleHook)
(*in).DeepCopyInto(*out)
}
if in.InPlaceUpdate != nil {
in, out := &in.InPlaceUpdate, &out.InPlaceUpdate
*out = new(LifecycleHook)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Lifecycle.
func (in *Lifecycle) DeepCopy() *Lifecycle {
if in == nil {
return nil
}
out := new(Lifecycle)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LifecycleHook) DeepCopyInto(out *LifecycleHook) {
*out = *in
if in.LabelsHandler != nil {
in, out := &in.LabelsHandler, &out.LabelsHandler
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.FinalizersHandler != nil {
in, out := &in.FinalizersHandler, &out.FinalizersHandler
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LifecycleHook.
func (in *LifecycleHook) DeepCopy() *LifecycleHook {
if in == nil {
return nil
}
out := new(LifecycleHook)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManualUpdate) DeepCopyInto(out *ManualUpdate) {
*out = *in
@ -1266,7 +1162,7 @@ func (in *RollingUpdateStatefulSetStrategy) DeepCopyInto(out *RollingUpdateState
}
if in.InPlaceUpdateStrategy != nil {
in, out := &in.InPlaceUpdateStrategy, &out.InPlaceUpdateStrategy
*out = new(InPlaceUpdateStrategy)
*out = new(pub.InPlaceUpdateStrategy)
**out = **in
}
if in.MinReadySeconds != nil {
@ -1868,7 +1764,7 @@ func (in *UnorderedUpdateStrategy) DeepCopyInto(out *UnorderedUpdateStrategy) {
*out = *in
if in.PriorityStrategy != nil {
in, out := &in.PriorityStrategy, &out.PriorityStrategy
*out = new(UpdatePriorityStrategy)
*out = new(pub.UpdatePriorityStrategy)
(*in).DeepCopyInto(*out)
}
}
@ -1883,64 +1779,6 @@ func (in *UnorderedUpdateStrategy) DeepCopy() *UnorderedUpdateStrategy {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdatePriorityOrderTerm) DeepCopyInto(out *UpdatePriorityOrderTerm) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdatePriorityOrderTerm.
func (in *UpdatePriorityOrderTerm) DeepCopy() *UpdatePriorityOrderTerm {
if in == nil {
return nil
}
out := new(UpdatePriorityOrderTerm)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdatePriorityStrategy) DeepCopyInto(out *UpdatePriorityStrategy) {
*out = *in
if in.OrderPriority != nil {
in, out := &in.OrderPriority, &out.OrderPriority
*out = make([]UpdatePriorityOrderTerm, len(*in))
copy(*out, *in)
}
if in.WeightPriority != nil {
in, out := &in.WeightPriority, &out.WeightPriority
*out = make([]UpdatePriorityWeightTerm, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdatePriorityStrategy.
func (in *UpdatePriorityStrategy) DeepCopy() *UpdatePriorityStrategy {
if in == nil {
return nil
}
out := new(UpdatePriorityStrategy)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdatePriorityWeightTerm) DeepCopyInto(out *UpdatePriorityWeightTerm) {
*out = *in
in.MatchSelector.DeepCopyInto(&out.MatchSelector)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdatePriorityWeightTerm.
func (in *UpdatePriorityWeightTerm) DeepCopy() *UpdatePriorityWeightTerm {
if in == nil {
return nil
}
out := new(UpdatePriorityWeightTerm)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdateStatus) DeepCopyInto(out *UpdateStatus) {
*out = *in

View File

@ -0,0 +1,218 @@
/*
Copyright 2020 The Kruise 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 v1beta1
import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/intstr"
v1 "k8s.io/kubernetes/pkg/apis/core/v1"
utilpointer "k8s.io/utils/pointer"
)
// SetDefaults_StatefulSet set default values for StatefulSet.
func SetDefaultsStatefulSet(obj *StatefulSet) {
if len(obj.Spec.PodManagementPolicy) == 0 {
obj.Spec.PodManagementPolicy = appsv1.OrderedReadyPodManagement
}
if obj.Spec.UpdateStrategy.Type == "" {
obj.Spec.UpdateStrategy.Type = appsv1.RollingUpdateStatefulSetStrategyType
// UpdateStrategy.RollingUpdate will take default values below.
obj.Spec.UpdateStrategy.RollingUpdate = &RollingUpdateStatefulSetStrategy{}
}
if obj.Spec.UpdateStrategy.Type == appsv1.RollingUpdateStatefulSetStrategyType {
if obj.Spec.UpdateStrategy.RollingUpdate == nil {
obj.Spec.UpdateStrategy.RollingUpdate = &RollingUpdateStatefulSetStrategy{}
}
if obj.Spec.UpdateStrategy.RollingUpdate.Partition == nil {
obj.Spec.UpdateStrategy.RollingUpdate.Partition = utilpointer.Int32Ptr(0)
}
if obj.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable == nil {
maxUnavailable := intstr.FromInt(1)
obj.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable = &maxUnavailable
}
if obj.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy == "" {
obj.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy = RecreatePodUpdateStrategyType
}
if obj.Spec.UpdateStrategy.RollingUpdate.MinReadySeconds == nil {
obj.Spec.UpdateStrategy.RollingUpdate.MinReadySeconds = utilpointer.Int32Ptr(0)
}
}
if obj.Spec.Replicas == nil {
obj.Spec.Replicas = utilpointer.Int32Ptr(1)
}
if obj.Spec.RevisionHistoryLimit == nil {
obj.Spec.RevisionHistoryLimit = utilpointer.Int32Ptr(10)
}
SetDefaultPodSpec(&obj.Spec.Template.Spec)
for i := range obj.Spec.VolumeClaimTemplates {
a := &obj.Spec.VolumeClaimTemplates[i]
v1.SetDefaults_PersistentVolumeClaim(a)
v1.SetDefaults_ResourceList(&a.Spec.Resources.Limits)
v1.SetDefaults_ResourceList(&a.Spec.Resources.Requests)
v1.SetDefaults_ResourceList(&a.Status.Capacity)
}
}
// SetDefaultPodSpec sets default pod spec
func SetDefaultPodSpec(in *corev1.PodSpec) {
v1.SetDefaults_PodSpec(in)
for i := range in.Volumes {
a := &in.Volumes[i]
v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
}
if a.VolumeSource.ISCSI != nil {
v1.SetDefaults_ISCSIVolumeSource(a.VolumeSource.ISCSI)
}
if a.VolumeSource.RBD != nil {
v1.SetDefaults_RBDVolumeSource(a.VolumeSource.RBD)
}
if a.VolumeSource.DownwardAPI != nil {
v1.SetDefaults_DownwardAPIVolumeSource(a.VolumeSource.DownwardAPI)
for j := range a.VolumeSource.DownwardAPI.Items {
b := &a.VolumeSource.DownwardAPI.Items[j]
if b.FieldRef != nil {
v1.SetDefaults_ObjectFieldSelector(b.FieldRef)
}
}
}
if a.VolumeSource.ConfigMap != nil {
v1.SetDefaults_ConfigMapVolumeSource(a.VolumeSource.ConfigMap)
}
if a.VolumeSource.AzureDisk != nil {
v1.SetDefaults_AzureDiskVolumeSource(a.VolumeSource.AzureDisk)
}
if a.VolumeSource.Projected != nil {
v1.SetDefaults_ProjectedVolumeSource(a.VolumeSource.Projected)
for j := range a.VolumeSource.Projected.Sources {
b := &a.VolumeSource.Projected.Sources[j]
if b.DownwardAPI != nil {
for k := range b.DownwardAPI.Items {
c := &b.DownwardAPI.Items[k]
if c.FieldRef != nil {
v1.SetDefaults_ObjectFieldSelector(c.FieldRef)
}
}
}
if b.ServiceAccountToken != nil {
v1.SetDefaults_ServiceAccountTokenProjection(b.ServiceAccountToken)
}
}
}
if a.VolumeSource.ScaleIO != nil {
v1.SetDefaults_ScaleIOVolumeSource(a.VolumeSource.ScaleIO)
}
}
for i := range in.InitContainers {
a := &in.InitContainers[i]
v1.SetDefaults_Container(a)
for j := range a.Ports {
b := &a.Ports[j]
v1.SetDefaults_ContainerPort(b)
}
for j := range a.Env {
b := &a.Env[j]
if b.ValueFrom != nil {
if b.ValueFrom.FieldRef != nil {
v1.SetDefaults_ObjectFieldSelector(b.ValueFrom.FieldRef)
}
}
}
v1.SetDefaults_ResourceList(&a.Resources.Limits)
v1.SetDefaults_ResourceList(&a.Resources.Requests)
if a.LivenessProbe != nil {
v1.SetDefaults_Probe(a.LivenessProbe)
if a.LivenessProbe.Handler.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.LivenessProbe.Handler.HTTPGet)
}
}
if a.ReadinessProbe != nil {
v1.SetDefaults_Probe(a.ReadinessProbe)
if a.ReadinessProbe.Handler.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.ReadinessProbe.Handler.HTTPGet)
}
}
if a.Lifecycle != nil {
if a.Lifecycle.PostStart != nil {
if a.Lifecycle.PostStart.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.Lifecycle.PostStart.HTTPGet)
}
}
if a.Lifecycle.PreStop != nil {
if a.Lifecycle.PreStop.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.Lifecycle.PreStop.HTTPGet)
}
}
}
}
for i := range in.Containers {
a := &in.Containers[i]
// For in-place update, we set default imagePullPolicy to Always
if a.ImagePullPolicy == "" {
a.ImagePullPolicy = corev1.PullAlways
}
v1.SetDefaults_Container(a)
for j := range a.Ports {
b := &a.Ports[j]
v1.SetDefaults_ContainerPort(b)
}
for j := range a.Env {
b := &a.Env[j]
if b.ValueFrom != nil {
if b.ValueFrom.FieldRef != nil {
v1.SetDefaults_ObjectFieldSelector(b.ValueFrom.FieldRef)
}
}
}
v1.SetDefaults_ResourceList(&a.Resources.Limits)
v1.SetDefaults_ResourceList(&a.Resources.Requests)
if a.LivenessProbe != nil {
v1.SetDefaults_Probe(a.LivenessProbe)
if a.LivenessProbe.Handler.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.LivenessProbe.Handler.HTTPGet)
}
}
if a.ReadinessProbe != nil {
v1.SetDefaults_Probe(a.ReadinessProbe)
if a.ReadinessProbe.Handler.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.ReadinessProbe.Handler.HTTPGet)
}
}
if a.Lifecycle != nil {
if a.Lifecycle.PostStart != nil {
if a.Lifecycle.PostStart.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.Lifecycle.PostStart.HTTPGet)
}
}
if a.Lifecycle.PreStop != nil {
if a.Lifecycle.PreStop.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.Lifecycle.PreStop.HTTPGet)
}
}
}
}
}

18
apis/apps/v1beta1/doc.go Normal file
View File

@ -0,0 +1,18 @@
/*
Copyright 2020 The Kruise 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.
*/
// +groupName=apps.kruise.io
package v1beta1

View File

@ -0,0 +1,43 @@
/*
Copyright 2020 The Kruise 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 v1beta1 contains API Schema definitions for the apps v1beta1 API group
// +kubebuilder:object:generate=true
// +groupName=apps.kruise.io
package v1beta1
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "apps.kruise.io", Version: "v1beta1"}
SchemeGroupVersion = GroupVersion
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)
// Resource is required by pkg/client/listers/...
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}

View File

@ -0,0 +1,19 @@
/*
Copyright 2020 The Kruise 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 v1beta1
func (*StatefulSet) Hub() {}

View File

@ -0,0 +1,261 @@
/*
Copyright 2020 The Kruise 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 v1beta1
import (
appspub "github.com/openkruise/kruise/apis/apps/pub"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)
const (
// MaxMinReadySeconds is the max value of MinReadySeconds
MaxMinReadySeconds = 300
)
// StatefulSetUpdateStrategy indicates the strategy that the StatefulSet
// controller will use to perform updates. It includes any additional parameters
// necessary to perform the update for the indicated strategy.
type StatefulSetUpdateStrategy struct {
// Type indicates the type of the StatefulSetUpdateStrategy.
// Default is RollingUpdate.
// +optional
Type apps.StatefulSetUpdateStrategyType `json:"type,omitempty"`
// RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType.
// +optional
RollingUpdate *RollingUpdateStatefulSetStrategy `json:"rollingUpdate,omitempty"`
}
// RollingUpdateStatefulSetStrategy is used to communicate parameter for RollingUpdateStatefulSetStrategyType.
type RollingUpdateStatefulSetStrategy struct {
// Partition indicates the ordinal at which the StatefulSet should be partitioned by default.
// But if unorderedUpdate has been set:
// - Partition indicates the number of pods with non-updated revisions when rolling update.
// - It means controller will update $(replicas - partition) number of pod.
// Default value is 0.
// +optional
Partition *int32 `json:"partition,omitempty"`
// The maximum number of pods that can be unavailable during the update.
// Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
// Absolute number is calculated from percentage by rounding down.
// Also, maxUnavailable can just be allowed to work with Parallel podManagementPolicy.
// Defaults to 1.
// +optional
MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"`
// PodUpdatePolicy indicates how pods should be updated
// Default value is "ReCreate"
// +optional
PodUpdatePolicy PodUpdateStrategyType `json:"podUpdatePolicy,omitempty"`
// Paused indicates that the StatefulSet is paused.
// Default value is false
// +optional
Paused bool `json:"paused,omitempty"`
// UnorderedUpdate contains strategies for non-ordered update.
// If it is not nil, pods will be updated with non-ordered sequence.
// Noted that UnorderedUpdate can only be allowed to work with Parallel podManagementPolicy
// +optional
UnorderedUpdate *UnorderedUpdateStrategy `json:"unorderedUpdate,omitempty"`
// InPlaceUpdateStrategy contains strategies for in-place update.
// +optional
InPlaceUpdateStrategy *appspub.InPlaceUpdateStrategy `json:"inPlaceUpdateStrategy,omitempty"`
// MinReadySeconds indicates how long will the pod be considered ready after it's updated.
// MinReadySeconds works with both OrderedReady and Parallel podManagementPolicy.
// It affects the pod scale up speed when the podManagementPolicy is set to be OrderedReady.
// Combined with MaxUnavailable, it affects the pod update speed regardless of podManagementPolicy.
// Default value is 0, max is 300.
// +optional
MinReadySeconds *int32 `json:"minReadySeconds,omitempty"`
}
// UnorderedUpdateStrategy defines strategies for non-ordered update.
type UnorderedUpdateStrategy struct {
// Priorities are the rules for calculating the priority of updating pods.
// Each pod to be updated, will pass through these terms and get a sum of weights.
// +optional
PriorityStrategy *appspub.UpdatePriorityStrategy `json:"priorityStrategy,omitempty"`
}
// PodUpdateStrategyType is a string enumeration type that enumerates
// all possible ways we can update a Pod when updating application
type PodUpdateStrategyType string
const (
// RecreatePodUpdateStrategyType indicates that we always delete Pod and create new Pod
// during Pod update, which is the default behavior
RecreatePodUpdateStrategyType PodUpdateStrategyType = "ReCreate"
// InPlaceIfPossiblePodUpdateStrategyType indicates that we try to in-place update Pod instead of
// recreating Pod when possible. Currently, only image update of pod spec is allowed. Any other changes to the pod
// spec will fall back to ReCreate PodUpdateStrategyType where pod will be recreated.
InPlaceIfPossiblePodUpdateStrategyType PodUpdateStrategyType = "InPlaceIfPossible"
// InPlaceOnlyPodUpdateStrategyType indicates that we will in-place update Pod instead of
// recreating pod. Currently we only allow image update for pod spec. Any other changes to the pod spec will be
// rejected by kube-apiserver
InPlaceOnlyPodUpdateStrategyType PodUpdateStrategyType = "InPlaceOnly"
)
// StatefulSetSpec defines the desired state of StatefulSet
type StatefulSetSpec struct {
// replicas is the desired number of replicas of the given Template.
// These are replicas in the sense that they are instantiations of the
// same Template, but individual replicas also have a consistent identity.
// If unspecified, defaults to 1.
// TODO: Consider a rename of this field.
// +optional
Replicas *int32 `json:"replicas,omitempty"`
// selector is a label query over pods that should match the replica count.
// It must match the pod 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 pod that will be created if
// insufficient replicas are detected. Each pod stamped out by the StatefulSet
// will fulfill this Template, but have a unique identity from the rest
// of the StatefulSet.
Template v1.PodTemplateSpec `json:"template"`
// volumeClaimTemplates is a list of claims that pods are allowed to reference.
// The StatefulSet controller is responsible for mapping network identities to
// claims in a way that maintains the identity of a pod. Every claim in
// this list must have at least one matching (by name) volumeMount in one
// container in the template. A claim in this list takes precedence over
// any volumes in the template, with the same name.
// TODO: Define the behavior if a claim already exists with the same name.
// +optional
VolumeClaimTemplates []v1.PersistentVolumeClaim `json:"volumeClaimTemplates,omitempty"`
// serviceName is the name of the service that governs this StatefulSet.
// This service must exist before the StatefulSet, and is responsible for
// the network identity of the set. Pods get DNS/hostnames that follow the
// pattern: pod-specific-string.serviceName.default.svc.cluster.local
// where "pod-specific-string" is managed by the StatefulSet controller.
ServiceName string `json:"serviceName,omitempty"`
// podManagementPolicy controls how pods are created during initial scale up,
// when replacing pods on nodes, or when scaling down. The default policy is
// `OrderedReady`, where pods are created in increasing order (pod-0, then
// pod-1, etc) and the controller will wait until each pod is ready before
// continuing. When scaling down, the pods are removed in the opposite order.
// The alternative policy is `Parallel` which will create pods in parallel
// to match the desired scale without waiting, and on scale down will delete
// all pods at once.
// +optional
PodManagementPolicy apps.PodManagementPolicyType `json:"podManagementPolicy,omitempty"`
// updateStrategy indicates the StatefulSetUpdateStrategy that will be
// employed to update Pods in the StatefulSet when a revision is made to
// Template.
UpdateStrategy StatefulSetUpdateStrategy `json:"updateStrategy,omitempty"`
// revisionHistoryLimit is the maximum number of revisions that will
// be maintained in the StatefulSet's revision history. The revision history
// consists of all revisions not represented by a currently applied
// StatefulSetSpec version. The default value is 10.
RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty"`
}
// StatefulSetStatus defines the observed state of StatefulSet
type StatefulSetStatus struct {
// observedGeneration is the most recent generation observed for this StatefulSet. It corresponds to the
// StatefulSet's generation, which is updated on mutation by the API Server.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// replicas is the number of Pods created by the StatefulSet controller.
Replicas int32 `json:"replicas"`
// readyReplicas is the number of Pods created by the StatefulSet controller that have a Ready Condition.
ReadyReplicas int32 `json:"readyReplicas"`
// AvailableReplicas is the number of Pods created by the StatefulSet controller that have been ready for
//minReadySeconds.
AvailableReplicas int32 `json:"availableReplicas"`
// currentReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version
// indicated by currentRevision.
CurrentReplicas int32 `json:"currentReplicas"`
// updatedReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version
// indicated by updateRevision.
UpdatedReplicas int32 `json:"updatedReplicas"`
// currentRevision, if not empty, indicates the version of the StatefulSet used to generate Pods in the
// sequence [0,currentReplicas).
CurrentRevision string `json:"currentRevision,omitempty"`
// updateRevision, if not empty, indicates the version of the StatefulSet used to generate Pods in the sequence
// [replicas-updatedReplicas,replicas)
UpdateRevision string `json:"updateRevision,omitempty"`
// collisionCount is the count of hash collisions for the StatefulSet. The StatefulSet controller
// uses this field as a collision avoidance mechanism when it needs to create the name for the
// newest ControllerRevision.
// +optional
CollisionCount *int32 `json:"collisionCount,omitempty"`
// Represents the latest available observations of a statefulset's current state.
// +optional
// +patchMergeKey=type
// +patchStrategy=merge
Conditions []apps.StatefulSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
// LabelSelector is label selectors for query over pods that should match the replica count used by HPA.
LabelSelector string `json:"labelSelector,omitempty"`
}
// These are valid conditions of a statefulset.
const (
FailedCreatePod apps.StatefulSetConditionType = "FailedCreatePod"
FailedUpdatePod apps.StatefulSetConditionType = "FailedUpdatePod"
)
// +genclient
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.labelSelector
// +kubebuilder:resource:shortName=sts;asts
// +kubebuilder:storageversion
// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.labelSelector
// +kubebuilder:printcolumn:name="DESIRED",type="integer",JSONPath=".spec.replicas",description="The desired number of pods."
// +kubebuilder:printcolumn:name="CURRENT",type="integer",JSONPath=".status.replicas",description="The number of currently all pods."
// +kubebuilder:printcolumn:name="UPDATED",type="integer",JSONPath=".status.updatedReplicas",description="The number of pods updated."
// +kubebuilder:printcolumn:name="READY",type="integer",JSONPath=".status.readyReplicas",description="The number of pods ready."
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp",description="CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC."
// StatefulSet is the Schema for the statefulsets API
type StatefulSet struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec StatefulSetSpec `json:"spec,omitempty"`
Status StatefulSetStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// StatefulSetList contains a list of StatefulSet
type StatefulSetList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []StatefulSet `json:"items"`
}
func init() {
SchemeBuilder.Register(&StatefulSet{}, &StatefulSetList{})
}

View File

@ -0,0 +1,235 @@
// +build !ignore_autogenerated
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by controller-gen. DO NOT EDIT.
package v1beta1
import (
"github.com/openkruise/kruise/apis/apps/pub"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RollingUpdateStatefulSetStrategy) DeepCopyInto(out *RollingUpdateStatefulSetStrategy) {
*out = *in
if in.Partition != nil {
in, out := &in.Partition, &out.Partition
*out = new(int32)
**out = **in
}
if in.MaxUnavailable != nil {
in, out := &in.MaxUnavailable, &out.MaxUnavailable
*out = new(intstr.IntOrString)
**out = **in
}
if in.UnorderedUpdate != nil {
in, out := &in.UnorderedUpdate, &out.UnorderedUpdate
*out = new(UnorderedUpdateStrategy)
(*in).DeepCopyInto(*out)
}
if in.InPlaceUpdateStrategy != nil {
in, out := &in.InPlaceUpdateStrategy, &out.InPlaceUpdateStrategy
*out = new(pub.InPlaceUpdateStrategy)
**out = **in
}
if in.MinReadySeconds != nil {
in, out := &in.MinReadySeconds, &out.MinReadySeconds
*out = new(int32)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RollingUpdateStatefulSetStrategy.
func (in *RollingUpdateStatefulSetStrategy) DeepCopy() *RollingUpdateStatefulSetStrategy {
if in == nil {
return nil
}
out := new(RollingUpdateStatefulSetStrategy)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StatefulSet) DeepCopyInto(out *StatefulSet) {
*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 StatefulSet.
func (in *StatefulSet) DeepCopy() *StatefulSet {
if in == nil {
return nil
}
out := new(StatefulSet)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *StatefulSet) 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 *StatefulSetList) DeepCopyInto(out *StatefulSetList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]StatefulSet, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatefulSetList.
func (in *StatefulSetList) DeepCopy() *StatefulSetList {
if in == nil {
return nil
}
out := new(StatefulSetList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *StatefulSetList) 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 *StatefulSetSpec) DeepCopyInto(out *StatefulSetSpec) {
*out = *in
if in.Replicas != nil {
in, out := &in.Replicas, &out.Replicas
*out = new(int32)
**out = **in
}
if in.Selector != nil {
in, out := &in.Selector, &out.Selector
*out = new(v1.LabelSelector)
(*in).DeepCopyInto(*out)
}
in.Template.DeepCopyInto(&out.Template)
if in.VolumeClaimTemplates != nil {
in, out := &in.VolumeClaimTemplates, &out.VolumeClaimTemplates
*out = make([]corev1.PersistentVolumeClaim, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
in.UpdateStrategy.DeepCopyInto(&out.UpdateStrategy)
if in.RevisionHistoryLimit != nil {
in, out := &in.RevisionHistoryLimit, &out.RevisionHistoryLimit
*out = new(int32)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatefulSetSpec.
func (in *StatefulSetSpec) DeepCopy() *StatefulSetSpec {
if in == nil {
return nil
}
out := new(StatefulSetSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StatefulSetStatus) DeepCopyInto(out *StatefulSetStatus) {
*out = *in
if in.CollisionCount != nil {
in, out := &in.CollisionCount, &out.CollisionCount
*out = new(int32)
**out = **in
}
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]appsv1.StatefulSetCondition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatefulSetStatus.
func (in *StatefulSetStatus) DeepCopy() *StatefulSetStatus {
if in == nil {
return nil
}
out := new(StatefulSetStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StatefulSetUpdateStrategy) DeepCopyInto(out *StatefulSetUpdateStrategy) {
*out = *in
if in.RollingUpdate != nil {
in, out := &in.RollingUpdate, &out.RollingUpdate
*out = new(RollingUpdateStatefulSetStrategy)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatefulSetUpdateStrategy.
func (in *StatefulSetUpdateStrategy) DeepCopy() *StatefulSetUpdateStrategy {
if in == nil {
return nil
}
out := new(StatefulSetUpdateStrategy)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UnorderedUpdateStrategy) DeepCopyInto(out *UnorderedUpdateStrategy) {
*out = *in
if in.PriorityStrategy != nil {
in, out := &in.PriorityStrategy, &out.PriorityStrategy
*out = new(pub.UpdatePriorityStrategy)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UnorderedUpdateStrategy.
func (in *UnorderedUpdateStrategy) DeepCopy() *UnorderedUpdateStrategy {
if in == nil {
return nil
}
out := new(UnorderedUpdateStrategy)
in.DeepCopyInto(out)
return out
}

View File

@ -0,0 +1,21 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

View File

@ -0,0 +1,17 @@
apiVersion: v1
name: kruise
description: Helm chart for all kruise-manager components
version: 0.7.0
appVersion: 0.7.0
icon: http://openkruise.io/img/kruise_white.png
keywords:
- kubernetes
- kruise
- workload
- statefulset
- sidecar
- job
- deployment
home: https://openkruise.io
sources:
- https://github.com/openkruise/kruise

View File

@ -0,0 +1,65 @@
# Kruise
## Install
Install with Helm 3:
Note that Kruise v0.7+ will only support Kubernetes 1.13+ and 1.13/1.14 must enable `CustomResourceWebhookConversion` feature-gate.
If your Kubernetes version is lower than 1.15, you'll need Helm v3.1.0+ that has the flag --disable-openapi-validation.
```bash
# Kubernetes 1.13 and 1.14
helm install kruise https://github.com/openkruise/kruise/releases/download/v0.7.0/kruise-chart.tgz --disable-openapi-validation
# Kubernetes 1.15 and newer versions
helm install kruise https://github.com/openkruise/kruise/releases/download/v0.7.0/kruise-chart.tgz
```
you will see follow:
```
NAME: kruise
LAST DEPLOYED: Mon Jan 6 14:47:48 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
```
## Uninstall
```bash
$ helm delete kruise
release "kruise" uninstalled
```
## Configuration
The following table lists the configurable parameters of the kruise chart and their default values.
| Parameter | Description | Default |
| ----------------------------------------- | ------------------------------------------------------------ | ----------------------------- |
| `log.level` | Log level that kruise-manager printed | `4` |
| `revisionHistoryLimit` | Limit of revision history | `3` |
| `manager.replicas` | Replicas of kruise-controller-manager deployment | `2` |
| `manager.image.repository` | Repository for kruise-manager image | `openkruise/kruise-manager` |
| `manager.image.tag` | Tag for kruise-manager image | `v0.6.1` |
| `manager.resources.limits.cpu` | CPU resource limit of kruise-manager container | `100m` |
| `manager.resources.limits.memory` | Memory resource limit of kruise-manager container | `256Mi` |
| `manager.resources.requests.cpu` | CPU resource request of kruise-manager container | `100m` |
| `manager.resources.requests.memory` | Memory resource request of kruise-manager container | `256Mi` |
| `manager.metrics.addr` | Addr of metrics served | `localhost` |
| `manager.metrics.port` | Port of metrics served | `8080` |
| `manager.webhook.port` | Port of webhook served | `9443` |
| `manager.custom_resource_enable` | Custom resources enabled by kruise-manager | `""(empty means all enabled)` |
| `manager.allowPrivileged` | Allow privileged for workloads template | `false` |
| `spec.nodeAffinity` | Node affinity policy for kruise-manager pod | `{}` |
| `spec.nodeSelector` | Node labels for kruise-manager pod | `{}` |
| `spec.tolerations` | Tolerations for kruise-manager pod | `[]` |
| `webhookConfiguration.failurePolicy.pods` | The failurePolicy for pods in mutating webhook configuration | `Ignore` |
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
```bash
# helm install kruise https://github.com/openkruise/kruise/releases/download/v0.7.0/kruise-chart.tgz --set manager.log.level=5,manager.custom_resource_enable="CloneSet\,SidecarSet"
```

View File

@ -0,0 +1,32 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "kruise.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "kruise.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "kruise.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@ -0,0 +1,209 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.9
creationTimestamp: null
name: broadcastjobs.apps.kruise.io
spec:
additionalPrinterColumns:
- JSONPath: .status.desired
description: The desired number of pods. This is typically equal to the number
of nodes satisfied to run pods.
name: Desired
type: integer
- JSONPath: .status.active
description: The number of actively running pods.
name: Active
type: integer
- JSONPath: .status.succeeded
description: The number of pods which reached phase Succeeded.
name: Succeeded
type: integer
- JSONPath: .status.failed
description: The number of pods which reached phase Failed.
name: Failed
type: integer
- JSONPath: .metadata.creationTimestamp
description: CreationTimestamp is a timestamp representing the server time when
this object was created. It is not guaranteed to be set in happens-before order
across separate operations. Clients may not set this value. It is represented
in RFC3339 form and is in UTC.
name: AGE
type: date
group: apps.kruise.io
names:
kind: BroadcastJob
listKind: BroadcastJobList
plural: broadcastjobs
shortNames:
- bcj
singular: broadcastjob
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: BroadcastJob is the Schema for the broadcastjobs 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: BroadcastJobSpec defines the desired state of BroadcastJob
properties:
completionPolicy:
description: CompletionPolicy indicates the completion policy of the
job. Default is Always CompletionPolicyType
properties:
activeDeadlineSeconds:
description: ActiveDeadlineSeconds specifies the duration in seconds
relative to the startTime that the job may be active before the
system tries to terminate it; value must be positive integer.
Only works for Always type.
format: int64
type: integer
ttlSecondsAfterFinished:
description: ttlSecondsAfterFinished limits the lifetime of a Job
that has finished execution (either Complete or Failed). If this
field is set, ttlSecondsAfterFinished after the Job finishes,
it is eligible to be automatically deleted. When the Job is being
deleted, its lifecycle guarantees (e.g. finalizers) will be honored.
If this field is unset, the Job won't be automatically deleted.
If this field is set to zero, the Job becomes eligible to be deleted
immediately after it finishes. This field is alpha-level and is
only honored by servers that enable the TTLAfterFinished feature.
Only works for Always type
format: int32
type: integer
type:
description: Type indicates the type of the CompletionPolicy Default
is Always
type: string
type: object
failurePolicy:
description: FailurePolicy indicates the behavior of the job, when failed
pod is found.
properties:
restartLimit:
description: RestartLimit specifies the number of retries before
marking the pod failed.
format: int32
type: integer
type:
description: Type indicates the type of FailurePolicyType.
type: string
type: object
parallelism:
anyOf:
- type: integer
- type: string
description: Parallelism specifies the maximum desired number of pods
the job should run at any given time. The actual number of pods running
in steady state will be less than this number when the work left to
do is less than max parallelism. Not setting this value means no limit.
x-kubernetes-int-or-string: true
paused:
description: Paused will pause the job.
type: boolean
template:
description: Template describes the pod that will be created when executing
a job.
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- template
type: object
status:
description: BroadcastJobStatus defines the observed state of BroadcastJob
properties:
active:
description: The number of actively running pods.
format: int32
type: integer
completionTime:
description: Represents time when the job was completed. It is not guaranteed
to be set in happens-before order across separate operations. It is
represented in RFC3339 form and is in UTC.
format: date-time
type: string
conditions:
description: The latest available observations of an object's current
state.
items:
description: JobCondition describes current state of a job.
properties:
lastProbeTime:
description: Last time the condition was checked.
format: date-time
type: string
lastTransitionTime:
description: Last time the condition transit from one status to
another.
format: date-time
type: string
message:
description: Human readable message indicating details about last
transition.
type: string
reason:
description: (brief) reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of job condition, Complete or Failed.
type: string
required:
- status
- type
type: object
type: array
desired:
description: The desired number of pods, this is typically equal to
the number of nodes satisfied to run pods.
format: int32
type: integer
failed:
description: The number of pods which reached phase Failed.
format: int32
type: integer
phase:
description: The phase of the job.
type: string
startTime:
description: Represents time when the job was acknowledged by the job
controller. It is not guaranteed to be set in happens-before order
across separate operations. It is represented in RFC3339 form and
is in UTC.
format: date-time
type: string
succeeded:
description: The number of pods which reached phase Succeeded.
format: int32
type: integer
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@ -0,0 +1,455 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.9
creationTimestamp: null
name: clonesets.apps.kruise.io
spec:
additionalPrinterColumns:
- JSONPath: .spec.replicas
description: The desired number of pods.
name: DESIRED
type: integer
- JSONPath: .status.updatedReplicas
description: The number of pods updated.
name: UPDATED
type: integer
- JSONPath: .status.updatedReadyReplicas
description: The number of pods updated and ready.
name: UPDATED_READY
type: integer
- JSONPath: .status.readyReplicas
description: The number of pods ready.
name: READY
type: integer
- JSONPath: .status.replicas
description: The number of currently all pods.
name: TOTAL
type: integer
- JSONPath: .metadata.creationTimestamp
description: CreationTimestamp is a timestamp representing the server time when
this object was created. It is not guaranteed to be set in happens-before order
across separate operations. Clients may not set this value. It is represented
in RFC3339 form and is in UTC.
name: AGE
type: date
group: apps.kruise.io
names:
kind: CloneSet
listKind: CloneSetList
plural: clonesets
shortNames:
- clone
singular: cloneset
scope: Namespaced
subresources:
scale:
labelSelectorPath: .status.labelSelector
specReplicasPath: .spec.replicas
statusReplicasPath: .status.replicas
status: {}
validation:
openAPIV3Schema:
description: CloneSet is the Schema for the clonesets 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: CloneSetSpec defines the desired state of CloneSet
properties:
lifecycle:
description: Lifecycle defines the lifecycle hooks for Pods pre-delete,
in-place update.
properties:
inPlaceUpdate:
description: InPlaceUpdate is the hook before Pod to update and
after Pod has been updated.
properties:
finalizersHandler:
items:
type: string
type: array
labelsHandler:
additionalProperties:
type: string
type: object
type: object
preDelete:
description: PreDelete is the hook before Pod to be deleted.
properties:
finalizersHandler:
items:
type: string
type: array
labelsHandler:
additionalProperties:
type: string
type: object
type: object
type: object
minReadySeconds:
description: Minimum number of seconds for which a newly created pod
should be ready without any of its container crashing, for it to be
considered available. Defaults to 0 (pod will be considered available
as soon as it is ready)
format: int32
type: integer
replicas:
description: Replicas is the desired number of replicas of the given
Template. These are replicas in the sense that they are instantiations
of the same Template. If unspecified, defaults to 1.
format: int32
type: integer
revisionHistoryLimit:
description: RevisionHistoryLimit is the maximum number of revisions
that will be maintained in the CloneSet's revision history. The revision
history consists of all revisions not represented by a currently applied
CloneSetSpec version. The default value is 10.
format: int32
type: integer
scaleStrategy:
description: ScaleStrategy indicates the ScaleStrategy that will be
employed to create and delete Pods in the CloneSet.
properties:
podsToDelete:
description: PodsToDelete is the names of Pod should be deleted.
Note that this list will be truncated for non-existing pod names.
items:
type: string
type: array
type: object
selector:
description: 'Selector is a label query over pods that should match
the replica count. It must match the pod template''s labels. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors'
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements.
The requirements are ANDed.
items:
description: A label selector requirement is a selector that contains
values, a key, and an operator that relates the key and values.
properties:
key:
description: key is the label key that the selector applies
to.
type: string
operator:
description: operator represents a key's relationship to a
set of values. Valid operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
is In or NotIn, the values array must be non-empty. If the
operator is Exists or DoesNotExist, the values array must
be empty. This array is replaced during a strategic merge
patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs. A single
{key,value} in the matchLabels map is equivalent to an element
of matchExpressions, whose key field is "key", the operator is
"In", and the values array contains only "value". The requirements
are ANDed.
type: object
type: object
template:
description: Template describes the pods that will be created.
type: object
x-kubernetes-preserve-unknown-fields: true
updateStrategy:
description: UpdateStrategy indicates the UpdateStrategy that will be
employed to update Pods in the CloneSet when a revision is made to
Template.
properties:
inPlaceUpdateStrategy:
description: InPlaceUpdateStrategy contains strategies for in-place
update.
properties:
gracePeriodSeconds:
description: GracePeriodSeconds is the timespan between set
Pod status to not-ready and update images in Pod spec when
in-place update a Pod.
format: int32
type: integer
type: object
maxSurge:
anyOf:
- type: integer
- type: string
description: 'The maximum number of pods that can be scheduled above
the desired replicas during the update. Value can be an absolute
number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute
number is calculated from percentage by rounding up. Defaults
to 0.'
x-kubernetes-int-or-string: true
maxUnavailable:
anyOf:
- type: integer
- type: string
description: 'The maximum number of pods that can be unavailable
during the update. Value can be an absolute number (ex: 5) or
a percentage of desired pods (ex: 10%). Absolute number is calculated
from percentage by rounding up by default. When maxSurge > 0,
absolute number is calculated from percentage by rounding down.
Defaults to 20%.'
x-kubernetes-int-or-string: true
partition:
description: Partition is the desired number of pods in old revisions.
It means when partition is set during pods updating, (replicas
- partition) number of pods will be updated. Default value is
0.
format: int32
type: integer
paused:
description: Paused indicates that the CloneSet is paused. Default
value is false
type: boolean
priorityStrategy:
description: Priorities are the rules for calculating the priority
of updating pods. Each pod to be updated, will pass through these
terms and get a sum of weights.
properties:
orderPriority:
description: 'Order priority terms, pods will be sorted by the
value of orderedKey. For example: ``` orderPriority: - orderedKey:
key1 - orderedKey: key2 ``` First, all pods which have key1
in labels will be sorted by the value of key1. Then, the left
pods which have no key1 but have key2 in labels will be sorted
by the value of key2 and put behind those pods have key1.'
items:
description: UpdatePriorityOrder defines order priority.
properties:
orderedKey:
description: Calculate priority by value of this key.
Values of this key, will be sorted by GetInt(val). GetInt
method will find the last int in value, such as getting
5 in value '5', getting 10 in value 'sts-10'.
type: string
required:
- orderedKey
type: object
type: array
weightPriority:
description: Weight priority terms, pods will be sorted by the
sum of all terms weight.
items:
description: UpdatePriorityWeightTerm defines weight priority.
properties:
matchSelector:
description: MatchSelector is used to select by pod's
labels.
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: A label selector requirement is a selector
that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In,
NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values.
If the operator is In or NotIn, the values
array must be non-empty. If the operator is
Exists or DoesNotExist, the values array must
be empty. This array is replaced during a
strategic merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs.
A single {key,value} in the matchLabels map is equivalent
to an element of matchExpressions, whose key field
is "key", the operator is "In", and the values array
contains only "value". The requirements are ANDed.
type: object
type: object
weight:
description: Weight associated with matching the corresponding
matchExpressions, in the range 1-100.
format: int32
type: integer
required:
- matchSelector
- weight
type: object
type: array
type: object
scatterStrategy:
description: ScatterStrategy defines the scatter rules to make pods
been scattered when update. This will avoid pods with the same
key-value to be updated in one batch. - Note that pods will be
scattered after priority sort. So, although priority strategy
and scatter strategy can be applied together, we suggest to use
either one of them. - If scatterStrategy is used, we suggest to
just use one term. Otherwise, the update order can be hard to
understand.
items:
properties:
key:
type: string
value:
type: string
required:
- key
- value
type: object
type: array
type:
description: Type indicates the type of the CloneSetUpdateStrategy.
Default is ReCreate.
type: string
type: object
volumeClaimTemplates:
description: VolumeClaimTemplates is a list of claims that pods are
allowed to reference. Note that PVC will be deleted when its pod has
been deleted.
items:
description: PersistentVolumeClaim is a user's request for and claim
to a persistent volume
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
required:
- selector
- template
type: object
status:
description: CloneSetStatus defines the observed state of CloneSet
properties:
availableReplicas:
description: AvailableReplicas is the number of Pods created by the
CloneSet controller that have a Ready Condition for at least minReadySeconds.
format: int32
type: integer
collisionCount:
description: CollisionCount is the count of hash collisions for the
CloneSet. The CloneSet controller uses this field as a collision avoidance
mechanism when it needs to create the name for the newest ControllerRevision.
format: int32
type: integer
conditions:
description: Conditions represents the latest available observations
of a CloneSet's current state.
items:
description: CloneSetCondition describes the state of a CloneSet at
a certain point.
properties:
lastTransitionTime:
description: Last time the condition transitioned from one status
to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of CloneSet condition.
type: string
required:
- status
- type
type: object
type: array
labelSelector:
description: LabelSelector is label selectors for query over pods that
should match the replica count used by HPA.
type: string
observedGeneration:
description: ObservedGeneration is the most recent generation observed
for this CloneSet. It corresponds to the CloneSet's generation, which
is updated on mutation by the API Server.
format: int64
type: integer
readyReplicas:
description: ReadyReplicas is the number of Pods created by the CloneSet
controller that have a Ready Condition.
format: int32
type: integer
replicas:
description: Replicas is the number of Pods created by the CloneSet
controller.
format: int32
type: integer
updateRevision:
description: UpdateRevision, if not empty, indicates the latest revision
of the CloneSet.
type: string
updatedReadyReplicas:
description: UpdatedReadyReplicas is the number of Pods created by the
CloneSet controller from the CloneSet version indicated by updateRevision
and have a Ready Condition.
format: int32
type: integer
updatedReplicas:
description: UpdatedReplicas is the number of Pods created by the CloneSet
controller from the CloneSet version indicated by updateRevision.
format: int32
type: integer
required:
- availableReplicas
- readyReplicas
- replicas
- updatedReadyReplicas
- updatedReplicas
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@ -0,0 +1,353 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.9
creationTimestamp: null
name: daemonsets.apps.kruise.io
spec:
additionalPrinterColumns:
- JSONPath: .status.desiredNumberScheduled
description: The desired number of pods.
name: DesiredNumber
type: integer
- JSONPath: .status.currentNumberScheduled
description: The current number of pods.
name: CurrentNumber
type: integer
- JSONPath: .status.updatedNumberScheduled
description: The updated number of pods.
name: UpdatedNumberScheduled
type: integer
- JSONPath: .metadata.creationTimestamp
description: CreationTimestamp is a timestamp representing the server time when
this object was created. It is not guaranteed to be set in happens-before order
across separate operations. Clients may not set this value. It is represented
in RFC3339 form and is in UTC.
name: AGE
type: date
group: apps.kruise.io
names:
kind: DaemonSet
listKind: DaemonSetList
plural: daemonsets
shortNames:
- daemon
singular: daemonset
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: DaemonSet is the Schema for the daemonsets 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: DaemonSetSpec defines the desired state of DaemonSet
properties:
burstReplicas:
anyOf:
- type: integer
- type: string
description: BurstReplicas is a rate limiter for booting pods on a lot
of pods. The default value is 250
x-kubernetes-int-or-string: true
minReadySeconds:
description: The minimum number of seconds for which a newly created
DaemonSet pod should be ready without any of its container crashing,
for it to be considered available. Defaults to 0 (pod will be considered
available as soon as it is ready).
format: int32
type: integer
revisionHistoryLimit:
description: The number of old history to retain to allow rollback.
This is a pointer to distinguish between explicit zero and not specified.
Defaults to 10.
format: int32
type: integer
selector:
description: 'A label query over pods that are managed by the daemon
set. Must match in order to be controlled. It must match the pod template''s
labels. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors'
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements.
The requirements are ANDed.
items:
description: A label selector requirement is a selector that contains
values, a key, and an operator that relates the key and values.
properties:
key:
description: key is the label key that the selector applies
to.
type: string
operator:
description: operator represents a key's relationship to a
set of values. Valid operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
is In or NotIn, the values array must be non-empty. If the
operator is Exists or DoesNotExist, the values array must
be empty. This array is replaced during a strategic merge
patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs. A single
{key,value} in the matchLabels map is equivalent to an element
of matchExpressions, whose key field is "key", the operator is
"In", and the values array contains only "value". The requirements
are ANDed.
type: object
type: object
template:
description: 'An object that describes the pod that will be created.
The DaemonSet will create exactly one copy of this pod on every node
that matches the template''s node selector (or on every node if no
node selector is specified). More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template'
type: object
x-kubernetes-preserve-unknown-fields: true
updateStrategy:
description: An update strategy to replace existing DaemonSet pods with
new pods.
properties:
rollingUpdate:
description: Rolling update config params. Present only if type
= "RollingUpdate".
properties:
maxSurge:
anyOf:
- type: integer
- type: string
description: 'Only when type=SurgingRollingUpdateType, it works.
The maximum number of DaemonSet pods that can be scheduled
above the desired number of pods during the update. Value
can be an absolute number (ex: 5) or a percentage of the total
number of DaemonSet pods at the start of the update (ex: 10%).
The absolute number is calculated from the percentage by rounding
up. This cannot be 0. The default value is 1. Example: when
this is set to 30%, at most 30% of the total number of nodes
that should be running the daemon pod (i.e. status.desiredNumberScheduled)
can have 2 pods running at any given time. The update starts
by starting replacements for at most 30% of those DaemonSet
pods. Once the new pods are available it then stops the existing
pods before proceeding onto other DaemonSet pods, thus ensuring
that at most 130% of the desired final number of DaemonSet pods
are running at all times during the update.'
x-kubernetes-int-or-string: true
maxUnavailable:
anyOf:
- type: integer
- type: string
description: 'The maximum number of DaemonSet pods that can
be unavailable during the update. Value can be an absolute
number (ex: 5) or a percentage of total number of DaemonSet
pods at the start of the update (ex: 10%). Absolute number
is calculated from percentage by rounding up. This cannot
be 0. Default value is 1. Example: when this is set to 30%,
at most 30% of the total number of nodes that should be running
the daemon pod (i.e. status.desiredNumberScheduled) can have
their pods stopped for an update at any given time. The update
starts by stopping at most 30% of those DaemonSet pods and
then brings up new DaemonSet pods in their place. Once the
new pods are available, it then proceeds onto other DaemonSet
pods, thus ensuring that at least 70% of original number of
DaemonSet pods are available at all times during the update.'
x-kubernetes-int-or-string: true
partition:
description: The number of DaemonSet pods remained to be old
version. Default value is 0. Maximum value is status.DesiredNumberScheduled,
which means no pod will be updated.
format: int32
type: integer
paused:
description: Indicates that the daemon set is paused and will
not be processed by the daemon set controller.
type: boolean
rollingUpdateType:
description: Type is to specify which kind of rollingUpdate.
type: string
selector:
description: A label query over nodes that are managed by the
daemon set RollingUpdate. Must match in order to be controlled.
It must match the node's labels.
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: A label selector requirement is a selector
that contains values, a key, and an operator that relates
the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, NotIn,
Exists and DoesNotExist.
type: string
values:
description: values is an array of string values.
If the operator is In or NotIn, the values array
must be non-empty. If the operator is Exists or
DoesNotExist, the values array must be empty. This
array is replaced during a strategic merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs.
A single {key,value} in the matchLabels map is equivalent
to an element of matchExpressions, whose key field is
"key", the operator is "In", and the values array contains
only "value". The requirements are ANDed.
type: object
type: object
type: object
type:
description: Type of daemon set update. Can be "RollingUpdate" or
"OnDelete". Default is RollingUpdate.
type: string
type: object
required:
- selector
- template
type: object
status:
description: DaemonSetStatus defines the observed state of DaemonSet
properties:
collisionCount:
description: Count of hash collisions for the DaemonSet. The DaemonSet
controller uses this field as a collision avoidance mechanism when
it needs to create the name for the newest ControllerRevision.
format: int32
type: integer
conditions:
description: Represents the latest available observations of a DaemonSet's
current state.
items:
description: DaemonSetCondition describes the state of a DaemonSet
at a certain point.
properties:
lastTransitionTime:
description: Last time the condition transitioned from one status
to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of DaemonSet condition.
type: string
required:
- status
- type
type: object
type: array
currentNumberScheduled:
description: 'The number of nodes that are running at least 1 daemon
pod and are supposed to run the daemon pod. More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/'
format: int32
type: integer
daemonSetHash:
description: DaemonSetHash is the controller-revision-hash, which represents
the latest version of the DaemonSet.
type: string
desiredNumberScheduled:
description: 'The total number of nodes that should be running the daemon
pod (including nodes correctly running the daemon pod). More info:
https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/'
format: int32
type: integer
numberAvailable:
description: The number of nodes that should be running the daemon pod
and have one or more of the daemon pod running and available (ready
for at least spec.minReadySeconds)
format: int32
type: integer
numberMisscheduled:
description: 'The number of nodes that are running the daemon pod, but
are not supposed to run the daemon pod. More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/'
format: int32
type: integer
numberReady:
description: The number of nodes that should be running the daemon pod
and have one or more of the daemon pod running and ready.
format: int32
type: integer
numberUnavailable:
description: The number of nodes that should be running the daemon pod
and have none of the daemon pod running and available (ready for at
least spec.minReadySeconds)
format: int32
type: integer
observedGeneration:
description: The most recent generation observed by the daemon set controller.
format: int64
type: integer
updatedNumberScheduled:
description: The total number of nodes that are running updated daemon
pod
format: int32
type: integer
required:
- currentNumberScheduled
- daemonSetHash
- desiredNumberScheduled
- numberMisscheduled
- numberReady
- updatedNumberScheduled
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@ -0,0 +1,187 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.9
creationTimestamp: null
name: sidecarsets.apps.kruise.io
spec:
additionalPrinterColumns:
- JSONPath: .status.matchedPods
description: The number of pods matched.
name: MATCHED
type: integer
- JSONPath: .status.updatedPods
description: The number of pods matched and updated.
name: UPDATED
type: integer
- JSONPath: .status.readyPods
description: The number of pods matched and ready.
name: READY
type: integer
- JSONPath: .metadata.creationTimestamp
description: CreationTimestamp is a timestamp representing the server time when
this object was created. It is not guaranteed to be set in happens-before order
across separate operations. Clients may not set this value. It is represented
in RFC3339 form and is in UTC.
name: AGE
type: date
group: apps.kruise.io
names:
kind: SidecarSet
listKind: SidecarSetList
plural: sidecarsets
singular: sidecarset
scope: Cluster
subresources:
status: {}
validation:
openAPIV3Schema:
description: SidecarSet is the Schema for the sidecarsets 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: SidecarSetSpec defines the desired state of SidecarSet
properties:
containers:
description: Containers is the list of sidecar containers to be injected
into the selected pod
items:
description: SidecarContainer defines the container of Sidecar
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
initContainers:
description: Containers is the list of init containers to be injected
into the selected pod We will inject those containers by their name
in ascending order We only inject init containers when a new pod is
created, it does not apply to any existing pod
items:
description: SidecarContainer defines the container of Sidecar
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
paused:
description: Paused indicates that the sidecarset is paused and will
not be processed by the sidecarset controller.
type: boolean
selector:
description: selector is a label query over pods that should be injected
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements.
The requirements are ANDed.
items:
description: A label selector requirement is a selector that contains
values, a key, and an operator that relates the key and values.
properties:
key:
description: key is the label key that the selector applies
to.
type: string
operator:
description: operator represents a key's relationship to a
set of values. Valid operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
is In or NotIn, the values array must be non-empty. If the
operator is Exists or DoesNotExist, the values array must
be empty. This array is replaced during a strategic merge
patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs. A single
{key,value} in the matchLabels map is equivalent to an element
of matchExpressions, whose key field is "key", the operator is
"In", and the values array contains only "value". The requirements
are ANDed.
type: object
type: object
strategy:
description: The sidecarset strategy to use to replace existing pods
with new ones.
properties:
rollingUpdate:
description: RollingUpdateSidecarSet is used to communicate parameter
properties:
maxUnavailable:
anyOf:
- type: integer
- type: string
x-kubernetes-int-or-string: true
type: object
type: object
volumes:
description: List of volumes that can be mounted by sidecar containers
items:
description: Volume represents a named volume in a pod that may be
accessed by any container in the pod.
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
type: object
status:
description: SidecarSetStatus defines the observed state of SidecarSet
properties:
matchedPods:
description: matchedPods is the number of Pods whose labels are matched
with this SidecarSet's selector and are created after sidecarset creates
format: int32
type: integer
observedGeneration:
description: observedGeneration is the most recent generation observed
for this SidecarSet. It corresponds to the SidecarSet's generation,
which is updated on mutation by the API Server.
format: int64
type: integer
readyPods:
description: readyPods is the number of matched Pods that have a ready
condition
format: int32
type: integer
updatedPods:
description: updatedPods is the number of matched Pods that are injected
with the latest SidecarSet's containers
format: int32
type: integer
required:
- matchedPods
- readyPods
- updatedPods
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@ -0,0 +1,433 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.9
creationTimestamp: null
name: statefulsets.apps.kruise.io
spec:
additionalPrinterColumns:
- JSONPath: .spec.replicas
description: The desired number of pods.
name: DESIRED
type: integer
- JSONPath: .status.replicas
description: The number of currently all pods.
name: CURRENT
type: integer
- JSONPath: .status.updatedReplicas
description: The number of pods updated.
name: UPDATED
type: integer
- JSONPath: .status.readyReplicas
description: The number of pods ready.
name: READY
type: integer
- JSONPath: .metadata.creationTimestamp
description: CreationTimestamp is a timestamp representing the server time when
this object was created. It is not guaranteed to be set in happens-before order
across separate operations. Clients may not set this value. It is represented
in RFC3339 form and is in UTC.
name: AGE
type: date
group: apps.kruise.io
names:
kind: StatefulSet
listKind: StatefulSetList
plural: statefulsets
shortNames:
- sts
- asts
singular: statefulset
scope: Namespaced
subresources:
scale:
labelSelectorPath: .status.labelSelector
specReplicasPath: .spec.replicas
statusReplicasPath: .status.replicas
status: {}
conversion:
strategy: Webhook
webhookClientConfig:
caBundle: Cg==
service:
namespace: kruise-system
name: kruise-webhook-service
path: /convert
preserveUnknownFields: false
validation:
openAPIV3Schema:
description: StatefulSet is the Schema for the statefulsets 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: StatefulSetSpec defines the desired state of StatefulSet
properties:
podManagementPolicy:
description: podManagementPolicy controls how pods are created during
initial scale up, when replacing pods on nodes, or when scaling down.
The default policy is `OrderedReady`, where pods are created in increasing
order (pod-0, then pod-1, etc) and the controller will wait until
each pod is ready before continuing. When scaling down, the pods are
removed in the opposite order. The alternative policy is `Parallel`
which will create pods in parallel to match the desired scale without
waiting, and on scale down will delete all pods at once.
type: string
replicas:
description: 'replicas is the desired number of replicas of the given
Template. These are replicas in the sense that they are instantiations
of the same Template, but individual replicas also have a consistent
identity. If unspecified, defaults to 1. TODO: Consider a rename of
this field.'
format: int32
type: integer
revisionHistoryLimit:
description: revisionHistoryLimit is the maximum number of revisions
that will be maintained in the StatefulSet's revision history. The
revision history consists of all revisions not represented by a currently
applied StatefulSetSpec version. The default value is 10.
format: int32
type: integer
selector:
description: 'selector is a label query over pods that should match
the replica count. It must match the pod template''s labels. More
info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors'
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements.
The requirements are ANDed.
items:
description: A label selector requirement is a selector that contains
values, a key, and an operator that relates the key and values.
properties:
key:
description: key is the label key that the selector applies
to.
type: string
operator:
description: operator represents a key's relationship to a
set of values. Valid operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
is In or NotIn, the values array must be non-empty. If the
operator is Exists or DoesNotExist, the values array must
be empty. This array is replaced during a strategic merge
patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs. A single
{key,value} in the matchLabels map is equivalent to an element
of matchExpressions, whose key field is "key", the operator is
"In", and the values array contains only "value". The requirements
are ANDed.
type: object
type: object
serviceName:
description: 'serviceName is the name of the service that governs this
StatefulSet. This service must exist before the StatefulSet, and is
responsible for the network identity of the set. Pods get DNS/hostnames
that follow the pattern: pod-specific-string.serviceName.default.svc.cluster.local
where "pod-specific-string" is managed by the StatefulSet controller.'
type: string
template:
description: template is the object that describes the pod that will
be created if insufficient replicas are detected. Each pod stamped
out by the StatefulSet will fulfill this Template, but have a unique
identity from the rest of the StatefulSet.
type: object
x-kubernetes-preserve-unknown-fields: true
updateStrategy:
description: updateStrategy indicates the StatefulSetUpdateStrategy
that will be employed to update Pods in the StatefulSet when a revision
is made to Template.
properties:
rollingUpdate:
description: RollingUpdate is used to communicate parameters when
Type is RollingUpdateStatefulSetStrategyType.
properties:
inPlaceUpdateStrategy:
description: InPlaceUpdateStrategy contains strategies for in-place
update.
properties:
gracePeriodSeconds:
description: GracePeriodSeconds is the timespan between
set Pod status to not-ready and update images in Pod spec
when in-place update a Pod.
format: int32
type: integer
type: object
maxUnavailable:
anyOf:
- type: integer
- type: string
description: 'The maximum number of pods that can be unavailable
during the update. Value can be an absolute number (ex: 5)
or a percentage of desired pods (ex: 10%). Absolute number
is calculated from percentage by rounding down. Also, maxUnavailable
can just be allowed to work with Parallel podManagementPolicy.
Defaults to 1.'
x-kubernetes-int-or-string: true
minReadySeconds:
description: MinReadySeconds indicates how long will the pod
be considered ready after it's updated. MinReadySeconds works
with both OrderedReady and Parallel podManagementPolicy. It
affects the pod scale up speed when the podManagementPolicy
is set to be OrderedReady. Combined with MaxUnavailable, it
affects the pod update speed regardless of podManagementPolicy.
Default value is 0, max is 300.
format: int32
type: integer
partition:
description: 'Partition indicates the ordinal at which the StatefulSet
should be partitioned by default. But if unorderedUpdate has
been set: - Partition indicates the number of pods with
non-updated revisions when rolling update. - It means controller
will update $(replicas - partition) number of pod. Default
value is 0.'
format: int32
type: integer
paused:
description: Paused indicates that the StatefulSet is paused.
Default value is false
type: boolean
podUpdatePolicy:
description: PodUpdatePolicy indicates how pods should be updated
Default value is "ReCreate"
type: string
unorderedUpdate:
description: UnorderedUpdate contains strategies for non-ordered
update. If it is not nil, pods will be updated with non-ordered
sequence. Noted that UnorderedUpdate can only be allowed to
work with Parallel podManagementPolicy
properties:
priorityStrategy:
description: Priorities are the rules for calculating the
priority of updating pods. Each pod to be updated, will
pass through these terms and get a sum of weights.
properties:
orderPriority:
description: 'Order priority terms, pods will be sorted
by the value of orderedKey. For example: ``` orderPriority:
- orderedKey: key1 - orderedKey: key2 ``` First, all
pods which have key1 in labels will be sorted by the
value of key1. Then, the left pods which have no key1
but have key2 in labels will be sorted by the value
of key2 and put behind those pods have key1.'
items:
description: UpdatePriorityOrder defines order priority.
properties:
orderedKey:
description: Calculate priority by value of this
key. Values of this key, will be sorted by GetInt(val).
GetInt method will find the last int in value,
such as getting 5 in value '5', getting 10 in
value 'sts-10'.
type: string
required:
- orderedKey
type: object
type: array
weightPriority:
description: Weight priority terms, pods will be sorted
by the sum of all terms weight.
items:
description: UpdatePriorityWeightTerm defines weight
priority.
properties:
matchSelector:
description: MatchSelector is used to select by
pod's labels.
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
weight:
description: Weight associated with matching the
corresponding matchExpressions, in the range
1-100.
format: int32
type: integer
required:
- matchSelector
- weight
type: object
type: array
type: object
type: object
type: object
type:
description: Type indicates the type of the StatefulSetUpdateStrategy.
Default is RollingUpdate.
type: string
type: object
volumeClaimTemplates:
description: 'volumeClaimTemplates is a list of claims that pods are
allowed to reference. The StatefulSet controller is responsible for
mapping network identities to claims in a way that maintains the identity
of a pod. Every claim in this list must have at least one matching
(by name) volumeMount in one container in the template. A claim in
this list takes precedence over any volumes in the template, with
the same name. TODO: Define the behavior if a claim already exists
with the same name.'
items:
description: PersistentVolumeClaim is a user's request for and claim
to a persistent volume
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
required:
- selector
- template
type: object
status:
description: StatefulSetStatus defines the observed state of StatefulSet
properties:
availableReplicas:
description: AvailableReplicas is the number of Pods created by the
StatefulSet controller that have been ready for minReadySeconds.
format: int32
type: integer
collisionCount:
description: collisionCount is the count of hash collisions for the
StatefulSet. The StatefulSet controller uses this field as a collision
avoidance mechanism when it needs to create the name for the newest
ControllerRevision.
format: int32
type: integer
conditions:
description: Represents the latest available observations of a statefulset's
current state.
items:
description: StatefulSetCondition describes the state of a statefulset
at a certain point.
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
currentReplicas:
description: currentReplicas is the number of Pods created by the StatefulSet
controller from the StatefulSet version indicated by currentRevision.
format: int32
type: integer
currentRevision:
description: currentRevision, if not empty, indicates the version of
the StatefulSet used to generate Pods in the sequence [0,currentReplicas).
type: string
labelSelector:
description: LabelSelector is label selectors for query over pods that
should match the replica count used by HPA.
type: string
observedGeneration:
description: observedGeneration is the most recent generation observed
for this StatefulSet. It corresponds to the StatefulSet's generation,
which is updated on mutation by the API Server.
format: int64
type: integer
readyReplicas:
description: readyReplicas is the number of Pods created by the StatefulSet
controller that have a Ready Condition.
format: int32
type: integer
replicas:
description: replicas is the number of Pods created by the StatefulSet
controller.
format: int32
type: integer
updateRevision:
description: updateRevision, if not empty, indicates the version of
the StatefulSet used to generate Pods in the sequence [replicas-updatedReplicas,replicas)
type: string
updatedReplicas:
description: updatedReplicas is the number of Pods created by the StatefulSet
controller from the StatefulSet version indicated by updateRevision.
format: int32
type: integer
required:
- availableReplicas
- currentReplicas
- readyReplicas
- replicas
- updatedReplicas
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: false
- name: v1beta1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@ -0,0 +1,949 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.9
creationTimestamp: null
name: uniteddeployments.apps.kruise.io
spec:
additionalPrinterColumns:
- JSONPath: .spec.replicas
description: The desired number of pods.
name: DESIRED
type: integer
- JSONPath: .status.replicas
description: The number of currently all pods.
name: CURRENT
type: integer
- JSONPath: .status.updatedReplicas
description: The number of pods updated.
name: UPDATED
type: integer
- JSONPath: .status.readyReplicas
description: The number of pods ready.
name: READY
type: integer
- JSONPath: .metadata.creationTimestamp
description: CreationTimestamp is a timestamp representing the server time when
this object was created. It is not guaranteed to be set in happens-before order
across separate operations. Clients may not set this value. It is represented
in RFC3339 form and is in UTC.
name: AGE
type: date
group: apps.kruise.io
names:
kind: UnitedDeployment
listKind: UnitedDeploymentList
plural: uniteddeployments
shortNames:
- ud
singular: uniteddeployment
scope: Namespaced
subresources:
scale:
labelSelectorPath: .status.selector
specReplicasPath: .spec.replicas
statusReplicasPath: .status.replicas
status: {}
validation:
openAPIV3Schema:
description: UnitedDeployment is the Schema for the uniteddeployments 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: UnitedDeploymentSpec defines the desired state of UnitedDeployment.
properties:
replicas:
description: Replicas is the total desired replicas of all the subsets.
If unspecified, defaults to 1.
format: int32
type: integer
revisionHistoryLimit:
description: Indicates the number of histories to be conserved. If unspecified,
defaults to 10.
format: int32
type: integer
selector:
description: Selector is a label query over pods that should match the
replica count. It must match the pod template's labels.
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements.
The requirements are ANDed.
items:
description: A label selector requirement is a selector that contains
values, a key, and an operator that relates the key and values.
properties:
key:
description: key is the label key that the selector applies
to.
type: string
operator:
description: operator represents a key's relationship to a
set of values. Valid operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
is In or NotIn, the values array must be non-empty. If the
operator is Exists or DoesNotExist, the values array must
be empty. This array is replaced during a strategic merge
patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs. A single
{key,value} in the matchLabels map is equivalent to an element
of matchExpressions, whose key field is "key", the operator is
"In", and the values array contains only "value". The requirements
are ANDed.
type: object
type: object
template:
description: Template describes the subset that will be created.
properties:
advancedStatefulSetTemplate:
description: AdvancedStatefulSet template
properties:
metadata:
type: object
x-kubernetes-preserve-unknown-fields: true
spec:
description: StatefulSetSpec defines the desired state of StatefulSet
properties:
podManagementPolicy:
description: podManagementPolicy controls how pods are created
during initial scale up, when replacing pods on nodes,
or when scaling down. The default policy is `OrderedReady`,
where pods are created in increasing order (pod-0, then
pod-1, etc) and the controller will wait until each pod
is ready before continuing. When scaling down, the pods
are removed in the opposite order. The alternative policy
is `Parallel` which will create pods in parallel to match
the desired scale without waiting, and on scale down will
delete all pods at once.
type: string
replicas:
description: 'replicas is the desired number of replicas
of the given Template. These are replicas in the sense
that they are instantiations of the same Template, but
individual replicas also have a consistent identity. If
unspecified, defaults to 1. TODO: Consider a rename of
this field.'
format: int32
type: integer
revisionHistoryLimit:
description: revisionHistoryLimit is the maximum number
of revisions that will be maintained in the StatefulSet's
revision history. The revision history consists of all
revisions not represented by a currently applied StatefulSetSpec
version. The default value is 10.
format: int32
type: integer
selector:
description: 'selector is a label query over pods that should
match the replica count. It must match the pod template''s
labels. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors'
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: A label selector requirement is a selector
that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In,
NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values.
If the operator is In or NotIn, the values array
must be non-empty. If the operator is Exists
or DoesNotExist, the values array must be empty.
This array is replaced during a strategic merge
patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs.
A single {key,value} in the matchLabels map is equivalent
to an element of matchExpressions, whose key field
is "key", the operator is "In", and the values array
contains only "value". The requirements are ANDed.
type: object
type: object
serviceName:
description: 'serviceName is the name of the service that
governs this StatefulSet. This service must exist before
the StatefulSet, and is responsible for the network identity
of the set. Pods get DNS/hostnames that follow the pattern:
pod-specific-string.serviceName.default.svc.cluster.local
where "pod-specific-string" is managed by the StatefulSet
controller.'
type: string
template:
description: template is the object that describes the pod
that will be created if insufficient replicas are detected.
Each pod stamped out by the StatefulSet will fulfill this
Template, but have a unique identity from the rest of
the StatefulSet.
type: object
x-kubernetes-preserve-unknown-fields: true
updateStrategy:
description: updateStrategy indicates the StatefulSetUpdateStrategy
that will be employed to update Pods in the StatefulSet
when a revision is made to Template.
properties:
rollingUpdate:
description: RollingUpdate is used to communicate parameters
when Type is RollingUpdateStatefulSetStrategyType.
properties:
inPlaceUpdateStrategy:
description: InPlaceUpdateStrategy contains strategies
for in-place update.
properties:
gracePeriodSeconds:
description: GracePeriodSeconds is the timespan
between set Pod status to not-ready and update
images in Pod spec when in-place update a
Pod.
format: int32
type: integer
type: object
maxUnavailable:
anyOf:
- type: integer
- type: string
description: 'The maximum number of pods that can
be unavailable during the update. Value can be
an absolute number (ex: 5) or a percentage of
desired pods (ex: 10%). Absolute number is calculated
from percentage by rounding down. Also, maxUnavailable
can just be allowed to work with Parallel podManagementPolicy.
Defaults to 1.'
x-kubernetes-int-or-string: true
minReadySeconds:
description: MinReadySeconds indicates how long
will the pod be considered ready after it's updated.
MinReadySeconds works with both OrderedReady and
Parallel podManagementPolicy. It affects the pod
scale up speed when the podManagementPolicy is
set to be OrderedReady. Combined with MaxUnavailable,
it affects the pod update speed regardless of
podManagementPolicy. Default value is 0, max is
300.
format: int32
type: integer
partition:
description: 'Partition indicates the ordinal at
which the StatefulSet should be partitioned by
default. But if unorderedUpdate has been set: -
Partition indicates the number of pods with non-updated
revisions when rolling update. - It means controller
will update $(replicas - partition) number of
pod. Default value is 0.'
format: int32
type: integer
paused:
description: Paused indicates that the StatefulSet
is paused. Default value is false
type: boolean
podUpdatePolicy:
description: PodUpdatePolicy indicates how pods
should be updated Default value is "ReCreate"
type: string
unorderedUpdate:
description: UnorderedUpdate contains strategies
for non-ordered update. If it is not nil, pods
will be updated with non-ordered sequence. Noted
that UnorderedUpdate can only be allowed to work
with Parallel podManagementPolicy
properties:
priorityStrategy:
description: Priorities are the rules for calculating
the priority of updating pods. Each pod to
be updated, will pass through these terms
and get a sum of weights.
properties:
orderPriority:
description: 'Order priority terms, pods
will be sorted by the value of orderedKey.
For example: ``` orderPriority: - orderedKey:
key1 - orderedKey: key2 ``` First, all
pods which have key1 in labels will be
sorted by the value of key1. Then, the
left pods which have no key1 but have
key2 in labels will be sorted by the value
of key2 and put behind those pods have
key1.'
items:
description: UpdatePriorityOrder defines
order priority.
properties:
orderedKey:
description: Calculate priority by
value of this key. Values of this
key, will be sorted by GetInt(val).
GetInt method will find the last
int in value, such as getting 5
in value '5', getting 10 in value
'sts-10'.
type: string
required:
- orderedKey
type: object
type: array
weightPriority:
description: Weight priority terms, pods
will be sorted by the sum of all terms
weight.
items:
description: UpdatePriorityWeightTerm
defines weight priority.
properties:
matchSelector:
description: MatchSelector is used
to select by pod's labels.
properties:
matchExpressions:
description: matchExpressions
is a list of label selector
requirements. The requirements
are ANDed.
items:
description: A label selector
requirement is a selector
that contains values, a key,
and an operator that relates
the key and values.
properties:
key:
description: key is the
label key that the selector
applies to.
type: string
operator:
description: operator represents
a key's relationship to
a set of values. Valid
operators are In, NotIn,
Exists and DoesNotExist.
type: string
values:
description: values is an
array of string values.
If the operator is In
or NotIn, the values array
must be non-empty. If
the operator is Exists
or DoesNotExist, the values
array must be empty. This
array is replaced during
a strategic merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a
map of {key,value} pairs. A
single {key,value} in the matchLabels
map is equivalent to an element
of matchExpressions, whose key
field is "key", the operator
is "In", and the values array
contains only "value". The requirements
are ANDed.
type: object
type: object
weight:
description: Weight associated with
matching the corresponding matchExpressions,
in the range 1-100.
format: int32
type: integer
required:
- matchSelector
- weight
type: object
type: array
type: object
type: object
type: object
type:
description: Type indicates the type of the StatefulSetUpdateStrategy.
Default is RollingUpdate.
type: string
type: object
volumeClaimTemplates:
description: 'volumeClaimTemplates is a list of claims that
pods are allowed to reference. The StatefulSet controller
is responsible for mapping network identities to claims
in a way that maintains the identity of a pod. Every claim
in this list must have at least one matching (by name)
volumeMount in one container in the template. A claim
in this list takes precedence over any volumes in the
template, with the same name. TODO: Define the behavior
if a claim already exists with the same name.'
items:
description: PersistentVolumeClaim is a user's request
for and claim to a persistent volume
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
required:
- selector
- template
type: object
required:
- spec
type: object
cloneSetTemplate:
description: CloneSet template
properties:
metadata:
type: object
x-kubernetes-preserve-unknown-fields: true
spec:
description: CloneSetSpec defines the desired state of CloneSet
properties:
lifecycle:
description: Lifecycle defines the lifecycle hooks for Pods
pre-delete, in-place update.
properties:
inPlaceUpdate:
description: InPlaceUpdate is the hook before Pod to
update and after Pod has been updated.
properties:
finalizersHandler:
items:
type: string
type: array
labelsHandler:
additionalProperties:
type: string
type: object
type: object
preDelete:
description: PreDelete is the hook before Pod to be
deleted.
properties:
finalizersHandler:
items:
type: string
type: array
labelsHandler:
additionalProperties:
type: string
type: object
type: object
type: object
minReadySeconds:
description: Minimum number of seconds for which a newly
created pod should be ready without any of its container
crashing, for it to be considered available. Defaults
to 0 (pod will be considered available as soon as it is
ready)
format: int32
type: integer
replicas:
description: Replicas is the desired number of replicas
of the given Template. These are replicas in the sense
that they are instantiations of the same Template. If
unspecified, defaults to 1.
format: int32
type: integer
revisionHistoryLimit:
description: RevisionHistoryLimit is the maximum number
of revisions that will be maintained in the CloneSet's
revision history. The revision history consists of all
revisions not represented by a currently applied CloneSetSpec
version. The default value is 10.
format: int32
type: integer
scaleStrategy:
description: ScaleStrategy indicates the ScaleStrategy that
will be employed to create and delete Pods in the CloneSet.
properties:
podsToDelete:
description: PodsToDelete is the names of Pod should
be deleted. Note that this list will be truncated
for non-existing pod names.
items:
type: string
type: array
type: object
selector:
description: 'Selector is a label query over pods that should
match the replica count. It must match the pod template''s
labels. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors'
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: A label selector requirement is a selector
that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In,
NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values.
If the operator is In or NotIn, the values array
must be non-empty. If the operator is Exists
or DoesNotExist, the values array must be empty.
This array is replaced during a strategic merge
patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs.
A single {key,value} in the matchLabels map is equivalent
to an element of matchExpressions, whose key field
is "key", the operator is "In", and the values array
contains only "value". The requirements are ANDed.
type: object
type: object
template:
description: Template describes the pods that will be created.
type: object
x-kubernetes-preserve-unknown-fields: true
updateStrategy:
description: UpdateStrategy indicates the UpdateStrategy
that will be employed to update Pods in the CloneSet when
a revision is made to Template.
properties:
inPlaceUpdateStrategy:
description: InPlaceUpdateStrategy contains strategies
for in-place update.
properties:
gracePeriodSeconds:
description: GracePeriodSeconds is the timespan
between set Pod status to not-ready and update
images in Pod spec when in-place update a Pod.
format: int32
type: integer
type: object
maxSurge:
anyOf:
- type: integer
- type: string
description: 'The maximum number of pods that can be
scheduled above the desired replicas during the update.
Value can be an absolute number (ex: 5) or a percentage
of desired pods (ex: 10%). Absolute number is calculated
from percentage by rounding up. Defaults to 0.'
x-kubernetes-int-or-string: true
maxUnavailable:
anyOf:
- type: integer
- type: string
description: 'The maximum number of pods that can be
unavailable during the update. Value can be an absolute
number (ex: 5) or a percentage of desired pods (ex:
10%). Absolute number is calculated from percentage
by rounding up by default. When maxSurge > 0, absolute
number is calculated from percentage by rounding down.
Defaults to 20%.'
x-kubernetes-int-or-string: true
partition:
description: Partition is the desired number of pods
in old revisions. It means when partition is set during
pods updating, (replicas - partition) number of pods
will be updated. Default value is 0.
format: int32
type: integer
paused:
description: Paused indicates that the CloneSet is paused.
Default value is false
type: boolean
priorityStrategy:
description: Priorities are the rules for calculating
the priority of updating pods. Each pod to be updated,
will pass through these terms and get a sum of weights.
properties:
orderPriority:
description: 'Order priority terms, pods will be
sorted by the value of orderedKey. For example:
``` orderPriority: - orderedKey: key1 - orderedKey:
key2 ``` First, all pods which have key1 in labels
will be sorted by the value of key1. Then, the
left pods which have no key1 but have key2 in
labels will be sorted by the value of key2 and
put behind those pods have key1.'
items:
description: UpdatePriorityOrder defines order
priority.
properties:
orderedKey:
description: Calculate priority by value of
this key. Values of this key, will be sorted
by GetInt(val). GetInt method will find
the last int in value, such as getting 5
in value '5', getting 10 in value 'sts-10'.
type: string
required:
- orderedKey
type: object
type: array
weightPriority:
description: Weight priority terms, pods will be
sorted by the sum of all terms weight.
items:
description: UpdatePriorityWeightTerm defines
weight priority.
properties:
matchSelector:
description: MatchSelector is used to select
by pod's labels.
properties:
matchExpressions:
description: matchExpressions is a list
of label selector requirements. The
requirements are ANDed.
items:
description: A label selector requirement
is a selector that contains values,
a key, and an operator that relates
the key and values.
properties:
key:
description: key is the label key
that the selector applies to.
type: string
operator:
description: operator represents
a key's relationship to a set
of values. Valid operators are
In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array
of string values. If the operator
is In or NotIn, the values array
must be non-empty. If the operator
is Exists or DoesNotExist, the
values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator
is "In", and the values array contains
only "value". The requirements are ANDed.
type: object
type: object
weight:
description: Weight associated with matching
the corresponding matchExpressions, in the
range 1-100.
format: int32
type: integer
required:
- matchSelector
- weight
type: object
type: array
type: object
scatterStrategy:
description: ScatterStrategy defines the scatter rules
to make pods been scattered when update. This will
avoid pods with the same key-value to be updated in
one batch. - Note that pods will be scattered after
priority sort. So, although priority strategy and
scatter strategy can be applied together, we suggest
to use either one of them. - If scatterStrategy is
used, we suggest to just use one term. Otherwise,
the update order can be hard to understand.
items:
properties:
key:
type: string
value:
type: string
required:
- key
- value
type: object
type: array
type:
description: Type indicates the type of the CloneSetUpdateStrategy.
Default is ReCreate.
type: string
type: object
volumeClaimTemplates:
description: VolumeClaimTemplates is a list of claims that
pods are allowed to reference. Note that PVC will be deleted
when its pod has been deleted.
items:
description: PersistentVolumeClaim is a user's request
for and claim to a persistent volume
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
required:
- selector
- template
type: object
required:
- spec
type: object
statefulSetTemplate:
description: StatefulSet template
properties:
metadata:
type: object
x-kubernetes-preserve-unknown-fields: true
spec:
description: A StatefulSetSpec is the specification of a StatefulSet.
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- spec
type: object
type: object
topology:
description: Topology describes the pods distribution detail between
each of subsets.
properties:
subsets:
description: Contains the details of each subset. Each element in
this array represents one subset which will be provisioned and
managed by UnitedDeployment.
items:
description: Subset defines the detail of a subset.
properties:
name:
description: Indicates subset name as a DNS_LABEL, which will
be used to generate subset workload name prefix in the format
'<deployment-name>-<subset-name>-'. Name should be unique
between all of the subsets under one UnitedDeployment.
type: string
nodeSelectorTerm:
description: Indicates the node selector to form the subset.
Depending on the node selector, pods provisioned could be
distributed across multiple groups of nodes. A subset's
nodeSelectorTerm is not allowed to be updated.
type: object
x-kubernetes-preserve-unknown-fields: true
replicas:
anyOf:
- type: integer
- type: string
description: Indicates the number of the pod to be created
under this subset. Replicas could also be percentage like
'10%', which means 10% of UnitedDeployment replicas of pods
will be distributed under this subset. If nil, the number
of replicas in this subset is determined by controller.
Controller will try to keep all the subsets with nil replicas
have average pods.
x-kubernetes-int-or-string: true
tolerations:
description: Indicates the tolerations the pods under this
subset have. A subset's tolerations is not allowed to be
updated.
items:
description: The pod this Toleration is attached to tolerates
any taint that matches the triple <key,value,effect> using
the matching operator <operator>.
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
required:
- name
type: object
type: array
type: object
updateStrategy:
description: UpdateStrategy indicates the strategy the UnitedDeployment
use to preform the update, when template is changed.
properties:
manualUpdate:
description: Includes all of the parameters a Manual update strategy
needs.
properties:
partitions:
additionalProperties:
format: int32
type: integer
description: Indicates number of subset partition.
type: object
type: object
type:
description: Type of UnitedDeployment update strategy. Default is
Manual.
type: string
type: object
required:
- selector
type: object
status:
description: UnitedDeploymentStatus defines the observed state of UnitedDeployment.
properties:
collisionCount:
description: Count of hash collisions for the UnitedDeployment. The
UnitedDeployment controller uses this field as a collision avoidance
mechanism when it needs to create the name for the newest ControllerRevision.
format: int32
type: integer
conditions:
description: Represents the latest available observations of a UnitedDeployment's
current state.
items:
description: UnitedDeploymentCondition describes current state of
a UnitedDeployment.
properties:
lastTransitionTime:
description: Last time the condition transitioned from one status
to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of in place set condition.
type: string
type: object
type: array
currentRevision:
description: CurrentRevision, if not empty, indicates the current version
of the UnitedDeployment.
type: string
observedGeneration:
description: ObservedGeneration is the most recent generation observed
for this UnitedDeployment. It corresponds to the UnitedDeployment's
generation, which is updated on mutation by the API Server.
format: int64
type: integer
readyReplicas:
description: The number of ready replicas.
format: int32
type: integer
replicas:
description: Replicas is the most recently observed number of replicas.
format: int32
type: integer
subsetReplicas:
additionalProperties:
format: int32
type: integer
description: Records the topology detail information of the replicas
of each subset.
type: object
updateStatus:
description: Records the information of update progress.
properties:
currentPartitions:
additionalProperties:
format: int32
type: integer
description: Records the current partition.
type: object
updatedRevision:
description: Records the latest revision.
type: string
type: object
updatedReadyReplicas:
description: The number of ready current revision replicas for this
UnitedDeployment.
format: int32
type: integer
updatedReplicas:
description: The number of pods in current version.
format: int32
type: integer
required:
- currentRevision
- replicas
- updatedReplicas
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@ -0,0 +1,111 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
control-plane: controller-manager
name: kruise-system
---
apiVersion: v1
kind: Service
metadata:
name: kruise-webhook-service
namespace: kruise-system
spec:
ports:
- port: 443
targetPort: {{ .Values.manager.webhook.port }}
selector:
control-plane: controller-manager
---
apiVersion: v1
kind: Secret
metadata:
name: kruise-webhook-certs
namespace: kruise-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
control-plane: controller-manager
name: kruise-controller-manager
namespace: kruise-system
spec:
replicas: {{ .Values.manager.replicas }}
selector:
matchLabels:
control-plane: controller-manager
template:
metadata:
labels:
control-plane: controller-manager
spec:
containers:
- args:
- --enable-leader-election
- --metrics-addr={{ .Values.manager.metrics.addr }}:{{ .Values.manager.metrics.port }}
- --health-probe-addr=:{{ .Values.manager.healthProbe.port }}
- --logtostderr=true
- --v={{ .Values.manager.log.level }}
{{- if .Values.manager.allowPrivileged }}
- --allow-privileged=true
{{- end }}
command:
- /manager
image: {{ .Values.manager.image.repository }}:{{.Values.manager.image.tag}}
imagePullPolicy: Always
name: manager
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: WEBHOOK_PORT
value: "{{ .Values.manager.webhook.port }}"
- name: CUSTOM_RESOURCE_ENABLE
value: {{ .Values.manager.custom_resource_enable }}
- name: WEBHOOK_CONFIGURATION_FAILURE_POLICY_PODS
value: {{ .Values.webhookConfiguration.failurePolicy.pods }}
ports:
- containerPort: {{ .Values.manager.webhook.port }}
name: webhook-server
protocol: TCP
- containerPort: {{ .Values.manager.metrics.port }}
name: metrics
protocol: TCP
- containerPort: {{ .Values.manager.healthProbe.port }}
name: health
protocol: TCP
readinessProbe:
httpGet:
path: readyz
port: {{ .Values.manager.healthProbe.port }}
resources:
{{- toYaml .Values.manager.resources | nindent 12 }}
terminationGracePeriodSeconds: 10
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchExpressions:
- key: control-plane
operator: In
values:
- controller-manager
topologyKey: kubernetes.io/hostname
weight: 100
{{- with .Values.spec.nodeAffinity }}
nodeAffinity:
{{ toYaml . | indent 10 }}
{{- end }}
{{- if .Values.spec.nodeSelector }}
nodeSelector:
{{ toYaml .Values.spec.nodeSelector | indent 8 }}
{{- end }}
{{- if .Values.spec.tolerations }}
tolerations:
{{ toYaml .Values.spec.tolerations | indent 8 }}
{{- end }}

View File

@ -0,0 +1,316 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: kruise-leader-election-role
namespace: kruise-system
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- configmaps/status
verbs:
- get
- update
- patch
- apiGroups:
- ""
resources:
- events
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
name: kruise-manager-role
rules:
- apiGroups:
- admissionregistration.k8s.io
resources:
- mutatingwebhookconfigurations
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- admissionregistration.k8s.io
resources:
- validatingwebhookconfigurations
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- get
- list
- patch
- update
- watch
- apiGroups:
- apps
resources:
- controllerrevisions
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apps
resources:
- statefulsets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apps
resources:
- statefulsets/status
verbs:
- get
- patch
- update
- apiGroups:
- apps.kruise.io
resources:
- broadcastjobs
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apps.kruise.io
resources:
- broadcastjobs/status
verbs:
- get
- patch
- update
- apiGroups:
- apps.kruise.io
resources:
- clonesets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apps.kruise.io
resources:
- clonesets/status
verbs:
- get
- patch
- update
- apiGroups:
- apps.kruise.io
resources:
- daemonsets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apps.kruise.io
resources:
- daemonsets/status
verbs:
- get
- patch
- update
- apiGroups:
- apps.kruise.io
resources:
- sidecarsets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apps.kruise.io
resources:
- sidecarsets/status
verbs:
- get
- patch
- update
- apiGroups:
- apps.kruise.io
resources:
- statefulsets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apps.kruise.io
resources:
- statefulsets/status
verbs:
- get
- patch
- update
- apiGroups:
- apps.kruise.io
resources:
- uniteddeployments
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apps.kruise.io
resources:
- uniteddeployments/status
verbs:
- get
- patch
- update
- apiGroups:
- ""
resources:
- events
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- persistentvolumeclaims
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- pods/status
verbs:
- get
- patch
- update
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: kruise-leader-election-rolebinding
namespace: kruise-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kruise-leader-election-role
subjects:
- kind: ServiceAccount
name: default
namespace: kruise-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kruise-manager-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kruise-manager-role
subjects:
- kind: ServiceAccount
name: default
namespace: kruise-system

View File

@ -0,0 +1,238 @@
apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
creationTimestamp: null
name: kruise-mutating-webhook-configuration
annotations:
template: ""
webhooks:
- clientConfig:
caBundle: Cg==
service:
name: kruise-webhook-service
namespace: kruise-system
path: /mutate-apps-kruise-io-v1alpha1-sidecarset
failurePolicy: Fail
name: msidecarset.kb.io
rules:
- apiGroups:
- apps.kruise.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- sidecarsets
- clientConfig:
caBundle: Cg==
service:
name: kruise-webhook-service
namespace: kruise-system
path: /mutate-pod
failurePolicy: {{ .Values.webhookConfiguration.failurePolicy.pods }}
name: mpod.kb.io
namespaceSelector:
matchExpressions:
- key: control-plane
operator: DoesNotExist
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
resources:
- pods
- clientConfig:
caBundle: Cg==
service:
name: kruise-webhook-service
namespace: kruise-system
path: /mutate-apps-kruise-io-v1alpha1-broadcastjob
failurePolicy: Fail
name: mbroadcastjob.kb.io
rules:
- apiGroups:
- apps.kruise.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- broadcastjobs
- clientConfig:
caBundle: Cg==
service:
name: kruise-webhook-service
namespace: kruise-system
path: /mutate-apps-kruise-io-v1alpha1-cloneset
failurePolicy: Fail
name: mcloneset.kb.io
rules:
- apiGroups:
- apps.kruise.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- clonesets
- clientConfig:
caBundle: Cg==
service:
name: kruise-webhook-service
namespace: kruise-system
path: /mutate-apps-kruise-io-v1alpha1-daemonset
failurePolicy: Fail
name: mdaemonset.kb.io
rules:
- apiGroups:
- apps.kruise.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- daemonsets
- clientConfig:
caBundle: Cg==
service:
name: kruise-webhook-service
namespace: kruise-system
path: /mutate-apps-kruise-io-statefulset
failurePolicy: Fail
name: mstatefulset.kb.io
rules:
- apiGroups:
- apps.kruise.io
apiVersions:
- v1alpha1
- v1beta1
operations:
- CREATE
- UPDATE
resources:
- statefulsets
- clientConfig:
caBundle: Cg==
service:
name: kruise-webhook-service
namespace: kruise-system
path: /mutate-apps-kruise-io-v1alpha1-uniteddeployment
failurePolicy: Fail
name: muniteddeployment.kb.io
rules:
- apiGroups:
- apps.kruise.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- uniteddeployments
---
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
creationTimestamp: null
name: kruise-validating-webhook-configuration
annotations:
template: ""
webhooks:
- clientConfig:
caBundle: Cg==
service:
name: kruise-webhook-service
namespace: kruise-system
path: /validate-apps-kruise-io-v1alpha1-broadcastjob
failurePolicy: Fail
name: vbroadcastjob.kb.io
rules:
- apiGroups:
- apps.kruise.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- broadcastjobs
- clientConfig:
caBundle: Cg==
service:
name: kruise-webhook-service
namespace: kruise-system
path: /validate-apps-kruise-io-v1alpha1-cloneset
failurePolicy: Fail
name: vcloneset.kb.io
rules:
- apiGroups:
- apps.kruise.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- clonesets
- clientConfig:
caBundle: Cg==
service:
name: kruise-webhook-service
namespace: kruise-system
path: /validate-apps-kruise-io-v1alpha1-sidecarset
failurePolicy: Fail
name: vsidecarset.kb.io
rules:
- apiGroups:
- apps.kruise.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- sidecarsets
- clientConfig:
caBundle: Cg==
service:
name: kruise-webhook-service
namespace: kruise-system
path: /validate-apps-kruise-io-statefulset
failurePolicy: Fail
name: vstatefulset.kb.io
rules:
- apiGroups:
- apps.kruise.io
apiVersions:
- v1alpha1
- v1beta1
operations:
- CREATE
- UPDATE
resources:
- statefulsets
- clientConfig:
caBundle: Cg==
service:
name: kruise-webhook-service
namespace: kruise-system
path: /validate-apps-kruise-io-v1alpha1-uniteddeployment
failurePolicy: Fail
name: vuniteddeployment.kb.io
rules:
- apiGroups:
- apps.kruise.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- uniteddeployments

View File

@ -0,0 +1,45 @@
# Default values for kruise.
revisionHistoryLimit: 3
spec:
nodeAffinity: {}
nodeSelector: {}
tolerations: []
manager:
# settings for log print
log:
# log level for kruise-manager
level: "4"
replicas: 2
image:
repository: openkruise/kruise-manager
tag: v0.7.0
webhook:
port: 9876
# resources of kruise-manager container
resources:
limits:
cpu: 100m
memory: 256Mi
requests:
cpu: 100m
memory: 256Mi
metrics:
addr: 0.0.0.0
port: 8080
healthProbe:
port: 8000
custom_resource_enable:
allowPrivileged: false
webhookConfiguration:
failurePolicy:
pods: Ignore

View File

@ -121,6 +121,7 @@ spec:
description: Template describes the pod that will be created when executing
a job.
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- template
type: object

View File

@ -179,6 +179,7 @@ spec:
template:
description: Template describes the pods that will be created.
type: object
x-kubernetes-preserve-unknown-fields: true
updateStrategy:
description: UpdateStrategy indicates the UpdateStrategy that will be
employed to update Pods in the CloneSet when a revision is made to
@ -348,6 +349,7 @@ spec:
description: PersistentVolumeClaim is a user's request for and claim
to a persistent volume
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
required:
- selector

View File

@ -129,6 +129,7 @@ spec:
that matches the template''s node selector (or on every node if no
node selector is specified). More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template'
type: object
x-kubernetes-preserve-unknown-fields: true
updateStrategy:
description: An update strategy to replace existing DaemonSet pods with
new pods.

View File

@ -98,6 +98,7 @@ spec:
description: ObjectReference contains enough information
to let you inspect or modify the referred object.
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
pullPolicy:
description: PullPolicy is an optional field to set parameters

View File

@ -62,6 +62,7 @@ spec:
items:
description: SidecarContainer defines the container of Sidecar
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
initContainers:
description: Containers is the list of init containers to be injected
@ -71,6 +72,7 @@ spec:
items:
description: SidecarContainer defines the container of Sidecar
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
paused:
description: Paused indicates that the sidecarset is paused and will
@ -139,6 +141,7 @@ spec:
description: Volume represents a named volume in a pod that may be
accessed by any container in the pod.
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
type: object
status:

View File

@ -150,6 +150,7 @@ spec:
out by the StatefulSet will fulfill this Template, but have a unique
identity from the rest of the StatefulSet.
type: object
x-kubernetes-preserve-unknown-fields: true
updateStrategy:
description: updateStrategy indicates the StatefulSetUpdateStrategy
that will be employed to update Pods in the StatefulSet when a revision
@ -331,6 +332,7 @@ spec:
description: PersistentVolumeClaim is a user's request for and claim
to a persistent volume
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
required:
- selector
@ -358,6 +360,7 @@ spec:
description: StatefulSetCondition describes the state of a statefulset
at a certain point.
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
currentReplicas:
description: currentReplicas is the number of Pods created by the StatefulSet
@ -408,6 +411,9 @@ spec:
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: false
- name: v1beta1
served: true
storage: true
status:

View File

@ -128,6 +128,7 @@ spec:
properties:
metadata:
type: object
x-kubernetes-preserve-unknown-fields: true
spec:
description: StatefulSetSpec defines the desired state of StatefulSet
properties:
@ -223,6 +224,7 @@ spec:
Template, but have a unique identity from the rest of
the StatefulSet.
type: object
x-kubernetes-preserve-unknown-fields: true
updateStrategy:
description: updateStrategy indicates the StatefulSetUpdateStrategy
that will be employed to update Pods in the StatefulSet
@ -429,6 +431,7 @@ spec:
description: PersistentVolumeClaim is a user's request
for and claim to a persistent volume
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
required:
- selector
@ -442,6 +445,7 @@ spec:
properties:
metadata:
type: object
x-kubernetes-preserve-unknown-fields: true
spec:
description: CloneSetSpec defines the desired state of CloneSet
properties:
@ -561,6 +565,7 @@ spec:
template:
description: Template describes the pods that will be created.
type: object
x-kubernetes-preserve-unknown-fields: true
updateStrategy:
description: UpdateStrategy indicates the UpdateStrategy
that will be employed to update Pods in the CloneSet when
@ -744,6 +749,7 @@ spec:
description: PersistentVolumeClaim is a user's request
for and claim to a persistent volume
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
required:
- selector
@ -757,9 +763,11 @@ spec:
properties:
metadata:
type: object
x-kubernetes-preserve-unknown-fields: true
spec:
description: A StatefulSetSpec is the specification of a StatefulSet.
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- spec
type: object
@ -787,6 +795,7 @@ spec:
distributed across multiple groups of nodes. A subset's
nodeSelectorTerm is not allowed to be updated.
type: object
x-kubernetes-preserve-unknown-fields: true
replicas:
anyOf:
- type: integer
@ -808,6 +817,7 @@ spec:
any taint that matches the triple <key,value,effect> using
the matching operator <operator>.
type: object
x-kubernetes-preserve-unknown-fields: true
type: array
required:
- name

View File

@ -18,7 +18,7 @@ patchesStrategicMerge:
#- patches/webhook_in_clonesets.yaml
#- patches/webhook_in_broadcastjobs.yaml
#- patches/webhook_in_sidecarsets.yaml
#- patches/webhook_in_statefulsets.yaml
- patches/webhook_in_statefulsets.yaml
#- patches/webhook_in_uniteddeployments.yaml
#- patches/webhook_in_daemonsets.yaml
#- patches/webhook_in_nodeimages.yaml

View File

@ -8,10 +8,9 @@ spec:
conversion:
strategy: Webhook
webhookClientConfig:
# this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank,
# but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager)
caBundle: Cg==
service:
namespace: system
name: webhook-service
path: /convert
preserveUnknownFields: false

View File

@ -30,6 +30,16 @@ rules:
- patch
- update
- watch
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- get
- list
- patch
- update
- watch
- apiGroups:
- apps
resources:

View File

@ -0,0 +1,7 @@
apiVersion: apps.kruise.io/v1beta1
kind: StatefulSet
metadata:
name: statefulset-sample
spec:
# Add fields here
foo: bar

View File

@ -100,7 +100,7 @@ webhooks:
service:
name: webhook-service
namespace: system
path: /mutate-apps-kruise-io-v1alpha1-statefulset
path: /mutate-apps-kruise-io-statefulset
failurePolicy: Fail
name: mstatefulset.kb.io
rules:
@ -108,6 +108,7 @@ webhooks:
- apps.kruise.io
apiVersions:
- v1alpha1
- v1beta1
operations:
- CREATE
- UPDATE
@ -198,7 +199,7 @@ webhooks:
service:
name: webhook-service
namespace: system
path: /validate-apps-kruise-io-v1alpha1-statefulset
path: /validate-apps-kruise-io-statefulset
failurePolicy: Fail
name: vstatefulset.kb.io
rules:
@ -206,6 +207,7 @@ webhooks:
- apps.kruise.io
apiVersions:
- v1alpha1
- v1beta1
operations:
- CREATE
- UPDATE

1
go.mod
View File

@ -14,6 +14,7 @@ require (
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7
gomodules.xyz/jsonpatch/v2 v2.0.1
k8s.io/api v0.17.7
k8s.io/apiextensions-apiserver v0.17.7
k8s.io/apimachinery v0.17.7
k8s.io/apiserver v0.16.6
k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible

13
main.go
View File

@ -22,20 +22,21 @@ import (
_ "net/http/pprof"
"os"
"k8s.io/kubernetes/pkg/capabilities"
extclient "github.com/openkruise/kruise/pkg/client"
"github.com/openkruise/kruise/pkg/util/fieldindex"
"github.com/openkruise/kruise/pkg/webhook"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/rest"
"k8s.io/klog"
"k8s.io/klog/klogr"
"k8s.io/kubernetes/pkg/capabilities"
ctrl "sigs.k8s.io/controller-runtime"
extclient "github.com/openkruise/kruise/pkg/client"
"github.com/openkruise/kruise/pkg/util/fieldindex"
"github.com/openkruise/kruise/pkg/webhook"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
"github.com/openkruise/kruise/pkg/controller"
// +kubebuilder:scaffold:imports
)
@ -51,8 +52,10 @@ var (
func init() {
_ = clientgoscheme.AddToScheme(scheme)
_ = appsv1alpha1.AddToScheme(clientgoscheme.Scheme)
_ = appsv1beta1.AddToScheme(clientgoscheme.Scheme)
_ = appsv1alpha1.AddToScheme(scheme)
_ = appsv1beta1.AddToScheme(scheme)
// +kubebuilder:scaffold:scheme
}

View File

@ -21,6 +21,7 @@ import (
"fmt"
appsv1alpha1 "github.com/openkruise/kruise/pkg/client/clientset/versioned/typed/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/pkg/client/clientset/versioned/typed/apps/v1beta1"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"
flowcontrol "k8s.io/client-go/util/flowcontrol"
@ -29,6 +30,7 @@ import (
type Interface interface {
Discovery() discovery.DiscoveryInterface
AppsV1alpha1() appsv1alpha1.AppsV1alpha1Interface
AppsV1beta1() appsv1beta1.AppsV1beta1Interface
}
// Clientset contains the clients for groups. Each group has exactly one
@ -36,6 +38,7 @@ type Interface interface {
type Clientset struct {
*discovery.DiscoveryClient
appsV1alpha1 *appsv1alpha1.AppsV1alpha1Client
appsV1beta1 *appsv1beta1.AppsV1beta1Client
}
// AppsV1alpha1 retrieves the AppsV1alpha1Client
@ -43,6 +46,11 @@ func (c *Clientset) AppsV1alpha1() appsv1alpha1.AppsV1alpha1Interface {
return c.appsV1alpha1
}
// AppsV1beta1 retrieves the AppsV1beta1Client
func (c *Clientset) AppsV1beta1() appsv1beta1.AppsV1beta1Interface {
return c.appsV1beta1
}
// Discovery retrieves the DiscoveryClient
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
if c == nil {
@ -68,6 +76,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
if err != nil {
return nil, err
}
cs.appsV1beta1, err = appsv1beta1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
if err != nil {
@ -81,6 +93,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
func NewForConfigOrDie(c *rest.Config) *Clientset {
var cs Clientset
cs.appsV1alpha1 = appsv1alpha1.NewForConfigOrDie(c)
cs.appsV1beta1 = appsv1beta1.NewForConfigOrDie(c)
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
return &cs
@ -90,6 +103,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
func New(c rest.Interface) *Clientset {
var cs Clientset
cs.appsV1alpha1 = appsv1alpha1.New(c)
cs.appsV1beta1 = appsv1beta1.New(c)
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
return &cs

View File

@ -21,6 +21,8 @@ import (
clientset "github.com/openkruise/kruise/pkg/client/clientset/versioned"
appsv1alpha1 "github.com/openkruise/kruise/pkg/client/clientset/versioned/typed/apps/v1alpha1"
fakeappsv1alpha1 "github.com/openkruise/kruise/pkg/client/clientset/versioned/typed/apps/v1alpha1/fake"
appsv1beta1 "github.com/openkruise/kruise/pkg/client/clientset/versioned/typed/apps/v1beta1"
fakeappsv1beta1 "github.com/openkruise/kruise/pkg/client/clientset/versioned/typed/apps/v1beta1/fake"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/discovery"
@ -79,3 +81,8 @@ var _ clientset.Interface = &Clientset{}
func (c *Clientset) AppsV1alpha1() appsv1alpha1.AppsV1alpha1Interface {
return &fakeappsv1alpha1.FakeAppsV1alpha1{Fake: &c.Fake}
}
// AppsV1beta1 retrieves the AppsV1beta1Client
func (c *Clientset) AppsV1beta1() appsv1beta1.AppsV1beta1Interface {
return &fakeappsv1beta1.FakeAppsV1beta1{Fake: &c.Fake}
}

View File

@ -19,6 +19,7 @@ package fake
import (
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
@ -31,6 +32,7 @@ var codecs = serializer.NewCodecFactory(scheme)
var parameterCodec = runtime.NewParameterCodec(scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
appsv1alpha1.AddToScheme,
appsv1beta1.AddToScheme,
}
// AddToScheme adds all types of this clientset into the given scheme. This allows composition

View File

@ -19,6 +19,7 @@ package scheme
import (
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
@ -31,6 +32,7 @@ var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
appsv1alpha1.AddToScheme,
appsv1beta1.AddToScheme,
}
// AddToScheme adds all types of this clientset into the given scheme. This allows composition

View File

@ -0,0 +1,88 @@
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1beta1
import (
v1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
"github.com/openkruise/kruise/pkg/client/clientset/versioned/scheme"
rest "k8s.io/client-go/rest"
)
type AppsV1beta1Interface interface {
RESTClient() rest.Interface
StatefulSetsGetter
}
// AppsV1beta1Client is used to interact with features provided by the apps.kruise.io group.
type AppsV1beta1Client struct {
restClient rest.Interface
}
func (c *AppsV1beta1Client) StatefulSets(namespace string) StatefulSetInterface {
return newStatefulSets(c, namespace)
}
// NewForConfig creates a new AppsV1beta1Client for the given config.
func NewForConfig(c *rest.Config) (*AppsV1beta1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &AppsV1beta1Client{client}, nil
}
// NewForConfigOrDie creates a new AppsV1beta1Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *AppsV1beta1Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new AppsV1beta1Client for the given RESTClient.
func New(c rest.Interface) *AppsV1beta1Client {
return &AppsV1beta1Client{c}
}
func setConfigDefaults(config *rest.Config) error {
gv := v1beta1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *AppsV1beta1Client) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}

View File

@ -0,0 +1,19 @@
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by client-gen. DO NOT EDIT.
// This package has the automatically generated typed clients.
package v1beta1

View File

@ -0,0 +1,19 @@
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by client-gen. DO NOT EDIT.
// Package fake has the automatically generated clients.
package fake

View File

@ -0,0 +1,39 @@
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v1beta1 "github.com/openkruise/kruise/pkg/client/clientset/versioned/typed/apps/v1beta1"
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
type FakeAppsV1beta1 struct {
*testing.Fake
}
func (c *FakeAppsV1beta1) StatefulSets(namespace string) v1beta1.StatefulSetInterface {
return &FakeStatefulSets{c, namespace}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeAppsV1beta1) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}

View File

@ -0,0 +1,139 @@
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
)
// FakeStatefulSets implements StatefulSetInterface
type FakeStatefulSets struct {
Fake *FakeAppsV1beta1
ns string
}
var statefulsetsResource = schema.GroupVersionResource{Group: "apps.kruise.io", Version: "v1beta1", Resource: "statefulsets"}
var statefulsetsKind = schema.GroupVersionKind{Group: "apps.kruise.io", Version: "v1beta1", Kind: "StatefulSet"}
// Get takes name of the statefulSet, and returns the corresponding statefulSet object, and an error if there is any.
func (c *FakeStatefulSets) Get(name string, options v1.GetOptions) (result *v1beta1.StatefulSet, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(statefulsetsResource, c.ns, name), &v1beta1.StatefulSet{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.StatefulSet), err
}
// List takes label and field selectors, and returns the list of StatefulSets that match those selectors.
func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *v1beta1.StatefulSetList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(statefulsetsResource, statefulsetsKind, c.ns, opts), &v1beta1.StatefulSetList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1beta1.StatefulSetList{ListMeta: obj.(*v1beta1.StatefulSetList).ListMeta}
for _, item := range obj.(*v1beta1.StatefulSetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested statefulSets.
func (c *FakeStatefulSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(statefulsetsResource, c.ns, opts))
}
// Create takes the representation of a statefulSet and creates it. Returns the server's representation of the statefulSet, and an error, if there is any.
func (c *FakeStatefulSets) Create(statefulSet *v1beta1.StatefulSet) (result *v1beta1.StatefulSet, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(statefulsetsResource, c.ns, statefulSet), &v1beta1.StatefulSet{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.StatefulSet), err
}
// Update takes the representation of a statefulSet and updates it. Returns the server's representation of the statefulSet, and an error, if there is any.
func (c *FakeStatefulSets) Update(statefulSet *v1beta1.StatefulSet) (result *v1beta1.StatefulSet, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(statefulsetsResource, c.ns, statefulSet), &v1beta1.StatefulSet{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.StatefulSet), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeStatefulSets) UpdateStatus(statefulSet *v1beta1.StatefulSet) (*v1beta1.StatefulSet, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(statefulsetsResource, "status", c.ns, statefulSet), &v1beta1.StatefulSet{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.StatefulSet), err
}
// Delete takes name of the statefulSet and deletes it. Returns an error if one occurs.
func (c *FakeStatefulSets) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(statefulsetsResource, c.ns, name), &v1beta1.StatefulSet{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeStatefulSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(statefulsetsResource, c.ns, listOptions)
_, err := c.Fake.Invokes(action, &v1beta1.StatefulSetList{})
return err
}
// Patch applies the patch and returns the patched statefulSet.
func (c *FakeStatefulSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.StatefulSet, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(statefulsetsResource, c.ns, name, pt, data, subresources...), &v1beta1.StatefulSet{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.StatefulSet), err
}

View File

@ -0,0 +1,20 @@
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1beta1
type StatefulSetExpansion interface{}

View File

@ -0,0 +1,190 @@
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1beta1
import (
"time"
v1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
scheme "github.com/openkruise/kruise/pkg/client/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// StatefulSetsGetter has a method to return a StatefulSetInterface.
// A group's client should implement this interface.
type StatefulSetsGetter interface {
StatefulSets(namespace string) StatefulSetInterface
}
// StatefulSetInterface has methods to work with StatefulSet resources.
type StatefulSetInterface interface {
Create(*v1beta1.StatefulSet) (*v1beta1.StatefulSet, error)
Update(*v1beta1.StatefulSet) (*v1beta1.StatefulSet, error)
UpdateStatus(*v1beta1.StatefulSet) (*v1beta1.StatefulSet, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1beta1.StatefulSet, error)
List(opts v1.ListOptions) (*v1beta1.StatefulSetList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.StatefulSet, err error)
StatefulSetExpansion
}
// statefulSets implements StatefulSetInterface
type statefulSets struct {
client rest.Interface
ns string
}
// newStatefulSets returns a StatefulSets
func newStatefulSets(c *AppsV1beta1Client, namespace string) *statefulSets {
return &statefulSets{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the statefulSet, and returns the corresponding statefulSet object, and an error if there is any.
func (c *statefulSets) Get(name string, options v1.GetOptions) (result *v1beta1.StatefulSet, err error) {
result = &v1beta1.StatefulSet{}
err = c.client.Get().
Namespace(c.ns).
Resource("statefulsets").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of StatefulSets that match those selectors.
func (c *statefulSets) List(opts v1.ListOptions) (result *v1beta1.StatefulSetList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1beta1.StatefulSetList{}
err = c.client.Get().
Namespace(c.ns).
Resource("statefulsets").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested statefulSets.
func (c *statefulSets) Watch(opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("statefulsets").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
// Create takes the representation of a statefulSet and creates it. Returns the server's representation of the statefulSet, and an error, if there is any.
func (c *statefulSets) Create(statefulSet *v1beta1.StatefulSet) (result *v1beta1.StatefulSet, err error) {
result = &v1beta1.StatefulSet{}
err = c.client.Post().
Namespace(c.ns).
Resource("statefulsets").
Body(statefulSet).
Do().
Into(result)
return
}
// Update takes the representation of a statefulSet and updates it. Returns the server's representation of the statefulSet, and an error, if there is any.
func (c *statefulSets) Update(statefulSet *v1beta1.StatefulSet) (result *v1beta1.StatefulSet, err error) {
result = &v1beta1.StatefulSet{}
err = c.client.Put().
Namespace(c.ns).
Resource("statefulsets").
Name(statefulSet.Name).
Body(statefulSet).
Do().
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *statefulSets) UpdateStatus(statefulSet *v1beta1.StatefulSet) (result *v1beta1.StatefulSet, err error) {
result = &v1beta1.StatefulSet{}
err = c.client.Put().
Namespace(c.ns).
Resource("statefulsets").
Name(statefulSet.Name).
SubResource("status").
Body(statefulSet).
Do().
Into(result)
return
}
// Delete takes name of the statefulSet and deletes it. Returns an error if one occurs.
func (c *statefulSets) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("statefulsets").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *statefulSets) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("statefulsets").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched statefulSet.
func (c *statefulSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.StatefulSet, err error) {
result = &v1beta1.StatefulSet{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("statefulsets").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

View File

@ -19,6 +19,7 @@ package apps
import (
v1alpha1 "github.com/openkruise/kruise/pkg/client/informers/externalversions/apps/v1alpha1"
v1beta1 "github.com/openkruise/kruise/pkg/client/informers/externalversions/apps/v1beta1"
internalinterfaces "github.com/openkruise/kruise/pkg/client/informers/externalversions/internalinterfaces"
)
@ -26,6 +27,8 @@ import (
type Interface interface {
// V1alpha1 provides access to shared informers for resources in V1alpha1.
V1alpha1() v1alpha1.Interface
// V1beta1 provides access to shared informers for resources in V1beta1.
V1beta1() v1beta1.Interface
}
type group struct {
@ -43,3 +46,8 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
func (g *group) V1alpha1() v1alpha1.Interface {
return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
}
// V1beta1 returns a new v1beta1.Interface.
func (g *group) V1beta1() v1beta1.Interface {
return v1beta1.New(g.factory, g.namespace, g.tweakListOptions)
}

View File

@ -0,0 +1,44 @@
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1beta1
import (
internalinterfaces "github.com/openkruise/kruise/pkg/client/informers/externalversions/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// StatefulSets returns a StatefulSetInformer.
StatefulSets() StatefulSetInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// StatefulSets returns a StatefulSetInformer.
func (v *version) StatefulSets() StatefulSetInformer {
return &statefulSetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}

View File

@ -0,0 +1,88 @@
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1beta1
import (
time "time"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
versioned "github.com/openkruise/kruise/pkg/client/clientset/versioned"
internalinterfaces "github.com/openkruise/kruise/pkg/client/informers/externalversions/internalinterfaces"
v1beta1 "github.com/openkruise/kruise/pkg/client/listers/apps/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
// StatefulSetInformer provides access to a shared informer and lister for
// StatefulSets.
type StatefulSetInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1beta1.StatefulSetLister
}
type statefulSetInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewStatefulSetInformer constructs a new informer for StatefulSet type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewStatefulSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredStatefulSetInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredStatefulSetInformer constructs a new informer for StatefulSet type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredStatefulSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta1().StatefulSets(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta1().StatefulSets(namespace).Watch(options)
},
},
&appsv1beta1.StatefulSet{},
resyncPeriod,
indexers,
)
}
func (f *statefulSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredStatefulSetInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *statefulSetInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&appsv1beta1.StatefulSet{}, f.defaultInformer)
}
func (f *statefulSetInformer) Lister() v1beta1.StatefulSetLister {
return v1beta1.NewStatefulSetLister(f.Informer().GetIndexer())
}

View File

@ -21,6 +21,7 @@ import (
"fmt"
v1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
v1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
schema "k8s.io/apimachinery/pkg/runtime/schema"
cache "k8s.io/client-go/tools/cache"
)
@ -69,6 +70,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
case v1alpha1.SchemeGroupVersion.WithResource("uniteddeployments"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Apps().V1alpha1().UnitedDeployments().Informer()}, nil
// Group=apps.kruise.io, Version=v1beta1
case v1beta1.SchemeGroupVersion.WithResource("statefulsets"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Apps().V1beta1().StatefulSets().Informer()}, nil
}
return nil, fmt.Errorf("no informer found for %v", resource)

View File

@ -0,0 +1,26 @@
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v1beta1
// StatefulSetListerExpansion allows custom methods to be added to
// StatefulSetLister.
type StatefulSetListerExpansion interface{}
// StatefulSetNamespaceListerExpansion allows custom methods to be added to
// StatefulSetNamespaceLister.
type StatefulSetNamespaceListerExpansion interface{}

View File

@ -0,0 +1,93 @@
/*
Copyright 2020 The Kruise 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.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v1beta1
import (
v1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
)
// StatefulSetLister helps list StatefulSets.
type StatefulSetLister interface {
// List lists all StatefulSets in the indexer.
List(selector labels.Selector) (ret []*v1beta1.StatefulSet, err error)
// StatefulSets returns an object that can list and get StatefulSets.
StatefulSets(namespace string) StatefulSetNamespaceLister
StatefulSetListerExpansion
}
// statefulSetLister implements the StatefulSetLister interface.
type statefulSetLister struct {
indexer cache.Indexer
}
// NewStatefulSetLister returns a new StatefulSetLister.
func NewStatefulSetLister(indexer cache.Indexer) StatefulSetLister {
return &statefulSetLister{indexer: indexer}
}
// List lists all StatefulSets in the indexer.
func (s *statefulSetLister) List(selector labels.Selector) (ret []*v1beta1.StatefulSet, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1beta1.StatefulSet))
})
return ret, err
}
// StatefulSets returns an object that can list and get StatefulSets.
func (s *statefulSetLister) StatefulSets(namespace string) StatefulSetNamespaceLister {
return statefulSetNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// StatefulSetNamespaceLister helps list and get StatefulSets.
type StatefulSetNamespaceLister interface {
// List lists all StatefulSets in the indexer for a given namespace.
List(selector labels.Selector) (ret []*v1beta1.StatefulSet, err error)
// Get retrieves the StatefulSet from the indexer for a given namespace and name.
Get(name string) (*v1beta1.StatefulSet, error)
StatefulSetNamespaceListerExpansion
}
// statefulSetNamespaceLister implements the StatefulSetNamespaceLister
// interface.
type statefulSetNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all StatefulSets in the indexer for a given namespace.
func (s statefulSetNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.StatefulSet, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1beta1.StatefulSet))
})
return ret, err
}
// Get retrieves the StatefulSet from the indexer for a given namespace and name.
func (s statefulSetNamespaceLister) Get(name string) (*v1beta1.StatefulSet, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1beta1.Resource("statefulset"), name)
}
return obj.(*v1beta1.StatefulSet), nil
}

View File

@ -6,6 +6,7 @@ import (
"sync"
"sync/atomic"
appspub "github.com/openkruise/kruise/apis/apps/pub"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
clonesetcore "github.com/openkruise/kruise/pkg/controller/cloneset/core"
clonesetutils "github.com/openkruise/kruise/pkg/controller/cloneset/utils"
@ -55,6 +56,7 @@ func (r *realControl) Manage(
if updateCS.Spec.Replicas == nil {
return false, fmt.Errorf("spec.Replicas is nil")
}
klog.Infof("DEBUG start scale for %v", util.DumpJSON(updateCS))
controllerKey := clonesetutils.GetControllerKey(updateCS)
coreControl := clonesetcore.New(updateCS)
@ -134,7 +136,7 @@ func (r *realControl) managePreparingDelete(cs *appsv1alpha1.CloneSet, pods, pod
klog.V(3).Infof("CloneSet %s patch pod %s lifecycle from PreparingDelete to Normal",
clonesetutils.GetControllerKey(cs), pod.Name)
if patched, err := lifecycle.PatchPodLifecycle(r, pod, appsv1alpha1.LifecycleStateNormal); err != nil {
if patched, err := lifecycle.PatchPodLifecycle(r, pod, appspub.LifecycleStateNormal); err != nil {
return modified, err
} else if patched {
modified = true
@ -174,7 +176,7 @@ func (r *realControl) createPods(
if pod.Labels[apps.ControllerRevisionHashLabelKey] == currentRevision {
cs = currentCS
}
lifecycle.SetPodLifecycle(appsv1alpha1.LifecycleStateNormal)(pod)
lifecycle.SetPodLifecycle(appspub.LifecycleStateNormal)(pod)
var createErr error
if createErr = r.createOnePod(cs, pod, existingPVCNames); createErr != nil {
@ -227,7 +229,7 @@ func (r *realControl) deletePods(cs *appsv1alpha1.CloneSet, podsToDelete []*v1.P
var modified bool
for _, pod := range podsToDelete {
if cs.Spec.Lifecycle != nil && lifecycle.IsPodHooked(cs.Spec.Lifecycle.PreDelete, pod) {
if patched, err := lifecycle.PatchPodLifecycle(r, pod, appsv1alpha1.LifecycleStatePreparingDelete); err != nil {
if patched, err := lifecycle.PatchPodLifecycle(r, pod, appspub.LifecycleStatePreparingDelete); err != nil {
return false, err
} else if patched {
klog.V(3).Infof("CloneSet %s scaling patch pod %s lifecycle to PreparingDelete",

View File

@ -6,6 +6,7 @@ import (
"sort"
"testing"
appspub "github.com/openkruise/kruise/apis/apps/pub"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
clonesettest "github.com/openkruise/kruise/pkg/controller/cloneset/test"
clonesetutils "github.com/openkruise/kruise/pkg/controller/cloneset/utils"
@ -67,7 +68,7 @@ func TestCreatePods(t *testing.T) {
appsv1alpha1.CloneSetInstanceID: "id1",
apps.ControllerRevisionHashLabelKey: "revision-abc",
"foo": "bar",
appsv1alpha1.LifecycleStateKey: string(appsv1alpha1.LifecycleStateNormal),
appspub.LifecycleStateKey: string(appspub.LifecycleStateNormal),
},
OwnerReferences: []metav1.OwnerReference{
{
@ -82,7 +83,7 @@ func TestCreatePods(t *testing.T) {
ResourceVersion: "1",
},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{
{
Name: "nginx",
@ -123,7 +124,7 @@ func TestCreatePods(t *testing.T) {
appsv1alpha1.CloneSetInstanceID: "id3",
apps.ControllerRevisionHashLabelKey: "revision-xyz",
"foo": "bar",
appsv1alpha1.LifecycleStateKey: string(appsv1alpha1.LifecycleStateNormal),
appspub.LifecycleStateKey: string(appspub.LifecycleStateNormal),
},
OwnerReferences: []metav1.OwnerReference{
{
@ -138,7 +139,7 @@ func TestCreatePods(t *testing.T) {
ResourceVersion: "1",
},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{
{
Name: "nginx",
@ -180,7 +181,7 @@ func TestCreatePods(t *testing.T) {
appsv1alpha1.CloneSetInstanceID: "id4",
apps.ControllerRevisionHashLabelKey: "revision-xyz",
"foo": "bar",
appsv1alpha1.LifecycleStateKey: string(appsv1alpha1.LifecycleStateNormal),
appspub.LifecycleStateKey: string(appspub.LifecycleStateNormal),
},
OwnerReferences: []metav1.OwnerReference{
{
@ -195,7 +196,7 @@ func TestCreatePods(t *testing.T) {
ResourceVersion: "1",
},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{
{
Name: "nginx",
@ -237,11 +238,11 @@ func TestCreatePods(t *testing.T) {
for i := range expectedPods {
appsv1alpha1.SetDefaultPod(&expectedPods[i])
if v, ok := pods.Items[i].Annotations[appsv1alpha1.LifecycleTimestampKey]; ok {
if v, ok := pods.Items[i].Annotations[appspub.LifecycleTimestampKey]; ok {
if expectedPods[i].Annotations == nil {
expectedPods[i].Annotations = make(map[string]string)
}
expectedPods[i].Annotations[appsv1alpha1.LifecycleTimestampKey] = v
expectedPods[i].Annotations[appspub.LifecycleTimestampKey] = v
}
}

View File

@ -3,6 +3,7 @@ package scale
import (
"sort"
appspub "github.com/openkruise/kruise/apis/apps/pub"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
"github.com/openkruise/kruise/pkg/util/lifecycle"
"github.com/openkruise/kruise/pkg/util/specifieddelete"
@ -34,7 +35,7 @@ func getPlannedDeletedPods(cs *appsv1alpha1.CloneSet, pods []*v1.Pod) ([]*v1.Pod
if isPodSpecifiedDelete(cs, pod) {
podsSpecifiedToDelete = append(podsSpecifiedToDelete, pod)
}
if lifecycle.GetPodLifecycleState(pod) == appsv1alpha1.LifecycleStatePreparingDelete {
if lifecycle.GetPodLifecycleState(pod) == appspub.LifecycleStatePreparingDelete {
podsInPreDelete = append(podsInPreDelete, pod)
}
}

View File

@ -21,6 +21,7 @@ import (
"sort"
"time"
appspub "github.com/openkruise/kruise/apis/apps/pub"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
clonesetcore "github.com/openkruise/kruise/pkg/controller/cloneset/core"
clonesetutils "github.com/openkruise/kruise/pkg/controller/cloneset/utils"
@ -97,7 +98,7 @@ func (c *realControl) Manage(cs *appsv1alpha1.CloneSet,
if clonesetutils.GetPodRevision(pods[i]) != updateRevision.Name {
switch lifecycle.GetPodLifecycleState(pods[i]) {
case appsv1alpha1.LifecycleStatePreparingDelete, appsv1alpha1.LifecycleStateUpdated:
case appspub.LifecycleStatePreparingDelete, appspub.LifecycleStateUpdated:
klog.V(3).Infof("CloneSet %s/%s find pod %s in state %s, so skip to update it",
cs.Namespace, cs.Name, pods[i].Name, lifecycle.GetPodLifecycleState(pods[i]))
default:
@ -137,25 +138,25 @@ func (c *realControl) refreshPodState(cs *appsv1alpha1.CloneSet, coreControl clo
return false, 0, res.RefreshErr
}
var state appsv1alpha1.LifecycleStateType
var state appspub.LifecycleStateType
switch lifecycle.GetPodLifecycleState(pod) {
case appsv1alpha1.LifecycleStateUpdating:
case appspub.LifecycleStateUpdating:
checkFunc := inplaceupdate.CheckInPlaceUpdateCompleted
if opts != nil && opts.CustomizeCheckUpdateCompleted != nil {
checkFunc = opts.CustomizeCheckUpdateCompleted
}
if checkFunc(pod) == nil {
if cs.Spec.Lifecycle != nil && !lifecycle.IsPodHooked(cs.Spec.Lifecycle.InPlaceUpdate, pod) {
state = appsv1alpha1.LifecycleStateUpdated
state = appspub.LifecycleStateUpdated
} else {
state = appsv1alpha1.LifecycleStateNormal
state = appspub.LifecycleStateNormal
}
}
case appsv1alpha1.LifecycleStateUpdated:
case appspub.LifecycleStateUpdated:
if cs.Spec.Lifecycle == nil ||
cs.Spec.Lifecycle.InPlaceUpdate == nil ||
lifecycle.IsPodHooked(cs.Spec.Lifecycle.InPlaceUpdate, pod) {
state = appsv1alpha1.LifecycleStateNormal
state = appspub.LifecycleStateNormal
}
}
@ -186,8 +187,8 @@ func sortUpdateIndexes(coreControl clonesetcore.Control, strategy appsv1alpha1.C
// PreparingUpdate first
sort.Slice(waitUpdateIndexes, func(i, j int) bool {
preparingUpdateI := lifecycle.GetPodLifecycleState(pods[waitUpdateIndexes[i]]) == appsv1alpha1.LifecycleStatePreparingUpdate
preparingUpdateJ := lifecycle.GetPodLifecycleState(pods[waitUpdateIndexes[j]]) == appsv1alpha1.LifecycleStatePreparingUpdate
preparingUpdateI := lifecycle.GetPodLifecycleState(pods[waitUpdateIndexes[i]]) == appspub.LifecycleStatePreparingUpdate
preparingUpdateJ := lifecycle.GetPodLifecycleState(pods[waitUpdateIndexes[j]]) == appspub.LifecycleStatePreparingUpdate
if preparingUpdateI != preparingUpdateJ {
return preparingUpdateI
}
@ -238,7 +239,7 @@ func calculateUpdateCount(coreControl clonesetcore.Control, strategy appsv1alpha
func isPodReady(coreControl clonesetcore.Control, pod *v1.Pod, minReadySeconds int32) bool {
state := lifecycle.GetPodLifecycleState(pod)
if state != "" && state != appsv1alpha1.LifecycleStateNormal {
if state != "" && state != appspub.LifecycleStateNormal {
return false
}
return coreControl.IsPodUpdateReady(pod, minReadySeconds)
@ -261,7 +262,7 @@ func (c *realControl) updatePod(cs *appsv1alpha1.CloneSet, coreControl clonesetc
if c.inplaceControl.CanUpdateInPlace(oldRevision, updateRevision, coreControl.GetUpdateOptions()) {
if cs.Spec.Lifecycle != nil && lifecycle.IsPodHooked(cs.Spec.Lifecycle.InPlaceUpdate, pod) {
if patched, err := lifecycle.PatchPodLifecycle(c, pod, appsv1alpha1.LifecycleStatePreparingUpdate); err != nil {
if patched, err := lifecycle.PatchPodLifecycle(c, pod, appspub.LifecycleStatePreparingUpdate); err != nil {
return 0, err
} else if patched {
clonesetutils.ResourceVersionExpectations.Expect(pod)
@ -272,7 +273,7 @@ func (c *realControl) updatePod(cs *appsv1alpha1.CloneSet, coreControl clonesetc
}
opts := coreControl.GetUpdateOptions()
opts.AdditionalFuncs = append(opts.AdditionalFuncs, lifecycle.SetPodLifecycle(appsv1alpha1.LifecycleStateUpdating))
opts.AdditionalFuncs = append(opts.AdditionalFuncs, lifecycle.SetPodLifecycle(appspub.LifecycleStateUpdating))
res := c.inplaceControl.Update(pod, oldRevision, updateRevision, opts)
if res.InPlaceUpdate {
if res.UpdateErr == nil {

View File

@ -23,6 +23,7 @@ import (
"time"
"github.com/openkruise/kruise/apis"
appspub "github.com/openkruise/kruise/apis/apps/pub"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
clonesetcore "github.com/openkruise/kruise/pkg/controller/cloneset/core"
"github.com/openkruise/kruise/pkg/util"
@ -81,20 +82,20 @@ func TestMange(t *testing.T) {
pods: []*v1.Pod{
{
ObjectMeta: metav1.ObjectMeta{Name: "pod-0", Labels: map[string]string{apps.ControllerRevisionHashLabelKey: "rev-new"}},
Spec: v1.PodSpec{ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}}},
Spec: v1.PodSpec{ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}}},
Status: v1.PodStatus{Phase: v1.PodRunning, Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionTrue},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionTrue},
}},
},
},
expectedPods: []*v1.Pod{
{
ObjectMeta: metav1.ObjectMeta{Name: "pod-0", Labels: map[string]string{apps.ControllerRevisionHashLabelKey: "rev-new"}},
Spec: v1.PodSpec{ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}}},
Spec: v1.PodSpec{ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}}},
Status: v1.PodStatus{Phase: v1.PodRunning, Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionTrue},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionTrue},
}},
},
},
@ -106,7 +107,7 @@ func TestMange(t *testing.T) {
pods: []*v1.Pod{
{
ObjectMeta: metav1.ObjectMeta{Name: "pod-0", Labels: map[string]string{apps.ControllerRevisionHashLabelKey: "rev-new"}},
Spec: v1.PodSpec{ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}}},
Spec: v1.PodSpec{ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}}},
Status: v1.PodStatus{Phase: v1.PodRunning, Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
}},
@ -115,10 +116,10 @@ func TestMange(t *testing.T) {
expectedPods: []*v1.Pod{
{
ObjectMeta: metav1.ObjectMeta{Name: "pod-0", Labels: map[string]string{apps.ControllerRevisionHashLabelKey: "rev-new"}, ResourceVersion: "1"},
Spec: v1.PodSpec{ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}}},
Spec: v1.PodSpec{ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}}},
Status: v1.PodStatus{Phase: v1.PodRunning, Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, LastTransitionTime: now, Status: v1.ConditionTrue},
{Type: appspub.InPlaceUpdateReady, LastTransitionTime: now, Status: v1.ConditionTrue},
}},
},
},
@ -136,10 +137,10 @@ func TestMange(t *testing.T) {
apps.ControllerRevisionHashLabelKey: "rev-old",
appsv1alpha1.CloneSetInstanceID: "id-0",
}},
Spec: v1.PodSpec{ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}}},
Spec: v1.PodSpec{ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}}},
Status: v1.PodStatus{Phase: v1.PodRunning, Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionTrue},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionTrue},
}},
},
},
@ -155,10 +156,10 @@ func TestMange(t *testing.T) {
appsv1alpha1.CloneSetInstanceID: "id-0",
appsv1alpha1.SpecifiedDeleteKey: "true",
}},
Spec: v1.PodSpec{ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}}},
Spec: v1.PodSpec{ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}}},
Status: v1.PodStatus{Phase: v1.PodRunning, Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionTrue},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionTrue},
}},
},
},
@ -191,14 +192,14 @@ func TestMange(t *testing.T) {
appsv1alpha1.CloneSetInstanceID: "id-0",
}},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{{Name: "c1", Image: "foo1"}},
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionTrue},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionTrue},
},
ContainerStatuses: []v1.ContainerStatus{{Name: "c1", ImageID: "image-id-xyz"}},
},
@ -217,14 +218,14 @@ func TestMange(t *testing.T) {
appsv1alpha1.SpecifiedDeleteKey: "true",
}},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{{Name: "c1", Image: "foo1"}},
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionTrue},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionTrue},
},
ContainerStatuses: []v1.ContainerStatus{{Name: "c1", ImageID: "image-id-xyz"}},
},
@ -259,14 +260,14 @@ func TestMange(t *testing.T) {
appsv1alpha1.CloneSetInstanceID: "id-0",
}},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{{Name: "c1", Image: "foo1"}},
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionTrue},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionTrue},
},
ContainerStatuses: []v1.ContainerStatus{{Name: "c1", ImageID: "image-id-xyz"}},
},
@ -283,24 +284,24 @@ func TestMange(t *testing.T) {
Labels: map[string]string{
apps.ControllerRevisionHashLabelKey: "rev-new",
appsv1alpha1.CloneSetInstanceID: "id-0",
appsv1alpha1.LifecycleStateKey: string(appsv1alpha1.LifecycleStateUpdating),
appspub.LifecycleStateKey: string(appspub.LifecycleStateUpdating),
},
Annotations: map[string]string{appsv1alpha1.InPlaceUpdateStateKey: util.DumpJSON(appsv1alpha1.InPlaceUpdateState{
Annotations: map[string]string{appspub.InPlaceUpdateStateKey: util.DumpJSON(appspub.InPlaceUpdateState{
Revision: "rev-new",
UpdateTimestamp: now,
LastContainerStatuses: map[string]appsv1alpha1.InPlaceUpdateContainerStatus{"c1": {ImageID: "image-id-xyz"}},
LastContainerStatuses: map[string]appspub.InPlaceUpdateContainerStatus{"c1": {ImageID: "image-id-xyz"}},
})},
ResourceVersion: "2",
},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{{Name: "c1", Image: "foo2"}},
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionFalse, Reason: "StartInPlaceUpdate", LastTransitionTime: now},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionFalse, Reason: "StartInPlaceUpdate", LastTransitionTime: now},
},
ContainerStatuses: []v1.ContainerStatus{{Name: "c1", ImageID: "image-id-xyz"}},
},
@ -316,7 +317,7 @@ func TestMange(t *testing.T) {
name: "inplace update with grace period",
cs: &appsv1alpha1.CloneSet{Spec: appsv1alpha1.CloneSetSpec{
Replicas: getInt32Pointer(1),
UpdateStrategy: appsv1alpha1.CloneSetUpdateStrategy{Type: appsv1alpha1.InPlaceIfPossibleCloneSetUpdateStrategyType, InPlaceUpdateStrategy: &appsv1alpha1.InPlaceUpdateStrategy{GracePeriodSeconds: 3630}},
UpdateStrategy: appsv1alpha1.CloneSetUpdateStrategy{Type: appsv1alpha1.InPlaceIfPossibleCloneSetUpdateStrategyType, InPlaceUpdateStrategy: &appspub.InPlaceUpdateStrategy{GracePeriodSeconds: 3630}},
}},
updateRevision: &apps.ControllerRevision{
ObjectMeta: metav1.ObjectMeta{Name: "rev-new"},
@ -335,14 +336,14 @@ func TestMange(t *testing.T) {
appsv1alpha1.CloneSetInstanceID: "id-0",
}},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{{Name: "c1", Image: "foo1"}},
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionTrue},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionTrue},
},
ContainerStatuses: []v1.ContainerStatus{{Name: "c1", ImageID: "image-id-xyz"}},
},
@ -359,27 +360,27 @@ func TestMange(t *testing.T) {
Labels: map[string]string{
apps.ControllerRevisionHashLabelKey: "rev-new",
appsv1alpha1.CloneSetInstanceID: "id-0",
appsv1alpha1.LifecycleStateKey: string(appsv1alpha1.LifecycleStateUpdating),
appspub.LifecycleStateKey: string(appspub.LifecycleStateUpdating),
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: util.DumpJSON(appsv1alpha1.InPlaceUpdateState{
appspub.InPlaceUpdateStateKey: util.DumpJSON(appspub.InPlaceUpdateState{
Revision: "rev-new",
UpdateTimestamp: now,
LastContainerStatuses: map[string]appsv1alpha1.InPlaceUpdateContainerStatus{"c1": {ImageID: "image-id-xyz"}},
LastContainerStatuses: map[string]appspub.InPlaceUpdateContainerStatus{"c1": {ImageID: "image-id-xyz"}},
}),
appsv1alpha1.InPlaceUpdateGraceKey: `{"revision":"rev-new","containerImages":{"c1":"foo2"},"graceSeconds":3630}`,
appspub.InPlaceUpdateGraceKey: `{"revision":"rev-new","containerImages":{"c1":"foo2"},"graceSeconds":3630}`,
},
ResourceVersion: "2",
},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{{Name: "c1", Image: "foo1"}},
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionFalse, Reason: "StartInPlaceUpdate", LastTransitionTime: now},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionFalse, Reason: "StartInPlaceUpdate", LastTransitionTime: now},
},
ContainerStatuses: []v1.ContainerStatus{{Name: "c1", ImageID: "image-id-xyz"}},
},
@ -395,7 +396,7 @@ func TestMange(t *testing.T) {
name: "inplace update during grace period",
cs: &appsv1alpha1.CloneSet{Spec: appsv1alpha1.CloneSetSpec{
Replicas: getInt32Pointer(1),
UpdateStrategy: appsv1alpha1.CloneSetUpdateStrategy{Type: appsv1alpha1.InPlaceIfPossibleCloneSetUpdateStrategyType, InPlaceUpdateStrategy: &appsv1alpha1.InPlaceUpdateStrategy{GracePeriodSeconds: 3630}},
UpdateStrategy: appsv1alpha1.CloneSetUpdateStrategy{Type: appsv1alpha1.InPlaceIfPossibleCloneSetUpdateStrategyType, InPlaceUpdateStrategy: &appspub.InPlaceUpdateStrategy{GracePeriodSeconds: 3630}},
}},
updateRevision: &apps.ControllerRevision{
ObjectMeta: metav1.ObjectMeta{Name: "rev-new"},
@ -412,23 +413,23 @@ func TestMange(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "pod-0",
Labels: map[string]string{apps.ControllerRevisionHashLabelKey: "rev-new", appsv1alpha1.CloneSetInstanceID: "id-0"},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: util.DumpJSON(appsv1alpha1.InPlaceUpdateState{
appspub.InPlaceUpdateStateKey: util.DumpJSON(appspub.InPlaceUpdateState{
Revision: "rev-new",
UpdateTimestamp: metav1.NewTime(now.Add(-time.Second * 10)),
LastContainerStatuses: map[string]appsv1alpha1.InPlaceUpdateContainerStatus{"c1": {ImageID: "image-id-xyz"}},
LastContainerStatuses: map[string]appspub.InPlaceUpdateContainerStatus{"c1": {ImageID: "image-id-xyz"}},
}),
appsv1alpha1.InPlaceUpdateGraceKey: `{"revision":"rev-new","containerImages":{"c1":"foo2"},"graceSeconds":3630}`,
appspub.InPlaceUpdateGraceKey: `{"revision":"rev-new","containerImages":{"c1":"foo2"},"graceSeconds":3630}`,
},
},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{{Name: "c1", Image: "foo1"}},
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionFalse, Reason: "StartInPlaceUpdate", LastTransitionTime: now},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionFalse, Reason: "StartInPlaceUpdate", LastTransitionTime: now},
},
ContainerStatuses: []v1.ContainerStatus{{Name: "c1", ImageID: "image-id-xyz"}},
},
@ -447,23 +448,23 @@ func TestMange(t *testing.T) {
appsv1alpha1.CloneSetInstanceID: "id-0",
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: util.DumpJSON(appsv1alpha1.InPlaceUpdateState{
appspub.InPlaceUpdateStateKey: util.DumpJSON(appspub.InPlaceUpdateState{
Revision: "rev-new",
UpdateTimestamp: metav1.NewTime(now.Add(-time.Second * 10)),
LastContainerStatuses: map[string]appsv1alpha1.InPlaceUpdateContainerStatus{"c1": {ImageID: "image-id-xyz"}},
LastContainerStatuses: map[string]appspub.InPlaceUpdateContainerStatus{"c1": {ImageID: "image-id-xyz"}},
}),
appsv1alpha1.InPlaceUpdateGraceKey: `{"revision":"rev-new","containerImages":{"c1":"foo2"},"graceSeconds":3630}`,
appspub.InPlaceUpdateGraceKey: `{"revision":"rev-new","containerImages":{"c1":"foo2"},"graceSeconds":3630}`,
},
},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{{Name: "c1", Image: "foo1"}},
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionFalse, Reason: "StartInPlaceUpdate", LastTransitionTime: now},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionFalse, Reason: "StartInPlaceUpdate", LastTransitionTime: now},
},
ContainerStatuses: []v1.ContainerStatus{{Name: "c1", ImageID: "image-id-xyz"}},
},
@ -479,7 +480,7 @@ func TestMange(t *testing.T) {
name: "inplace update continuously after grace period",
cs: &appsv1alpha1.CloneSet{Spec: appsv1alpha1.CloneSetSpec{
Replicas: getInt32Pointer(1),
UpdateStrategy: appsv1alpha1.CloneSetUpdateStrategy{Type: appsv1alpha1.InPlaceIfPossibleCloneSetUpdateStrategyType, InPlaceUpdateStrategy: &appsv1alpha1.InPlaceUpdateStrategy{GracePeriodSeconds: 3630}},
UpdateStrategy: appsv1alpha1.CloneSetUpdateStrategy{Type: appsv1alpha1.InPlaceIfPossibleCloneSetUpdateStrategyType, InPlaceUpdateStrategy: &appspub.InPlaceUpdateStrategy{GracePeriodSeconds: 3630}},
}},
updateRevision: &apps.ControllerRevision{
ObjectMeta: metav1.ObjectMeta{Name: "rev-new"},
@ -496,23 +497,23 @@ func TestMange(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "pod-0",
Labels: map[string]string{apps.ControllerRevisionHashLabelKey: "rev-new", appsv1alpha1.CloneSetInstanceID: "id-0"},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: util.DumpJSON(appsv1alpha1.InPlaceUpdateState{
appspub.InPlaceUpdateStateKey: util.DumpJSON(appspub.InPlaceUpdateState{
Revision: "rev-new",
UpdateTimestamp: metav1.NewTime(now.Add(-time.Minute)),
LastContainerStatuses: map[string]appsv1alpha1.InPlaceUpdateContainerStatus{"c1": {ImageID: "image-id-xyz"}},
LastContainerStatuses: map[string]appspub.InPlaceUpdateContainerStatus{"c1": {ImageID: "image-id-xyz"}},
}),
appsv1alpha1.InPlaceUpdateGraceKey: `{"revision":"rev-new","containerImages":{"c1":"foo2"},"graceSeconds":3630}`,
appspub.InPlaceUpdateGraceKey: `{"revision":"rev-new","containerImages":{"c1":"foo2"},"graceSeconds":3630}`,
},
},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{{Name: "c1", Image: "foo1"}},
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionFalse, Reason: "StartInPlaceUpdate", LastTransitionTime: now},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionFalse, Reason: "StartInPlaceUpdate", LastTransitionTime: now},
},
ContainerStatuses: []v1.ContainerStatus{{Name: "c1", ImageID: "image-id-xyz"}},
},
@ -531,23 +532,23 @@ func TestMange(t *testing.T) {
appsv1alpha1.CloneSetInstanceID: "id-0",
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: util.DumpJSON(appsv1alpha1.InPlaceUpdateState{
appspub.InPlaceUpdateStateKey: util.DumpJSON(appspub.InPlaceUpdateState{
Revision: "rev-new",
UpdateTimestamp: metav1.NewTime(now.Add(-time.Minute)),
LastContainerStatuses: map[string]appsv1alpha1.InPlaceUpdateContainerStatus{"c1": {ImageID: "image-id-xyz"}},
LastContainerStatuses: map[string]appspub.InPlaceUpdateContainerStatus{"c1": {ImageID: "image-id-xyz"}},
}),
},
ResourceVersion: "1",
},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
Containers: []v1.Container{{Name: "c1", Image: "foo2"}},
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
Conditions: []v1.PodCondition{
{Type: v1.PodReady, Status: v1.ConditionTrue},
{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionFalse, Reason: "StartInPlaceUpdate", LastTransitionTime: now},
{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionFalse, Reason: "StartInPlaceUpdate", LastTransitionTime: now},
},
ContainerStatuses: []v1.ContainerStatus{{Name: "c1", ImageID: "image-id-xyz"}},
},
@ -589,11 +590,11 @@ func TestMange(t *testing.T) {
t.Fatalf("Failed to test %s, get pod %s error: %v", mc.name, p.Name, err)
}
if v, ok := gotPod.Annotations[appsv1alpha1.LifecycleTimestampKey]; ok {
if v, ok := gotPod.Annotations[appspub.LifecycleTimestampKey]; ok {
if p.Annotations == nil {
p.Annotations = map[string]string{}
}
p.Annotations[appsv1alpha1.LifecycleTimestampKey] = v
p.Annotations[appspub.LifecycleTimestampKey] = v
}
if !reflect.DeepEqual(gotPod, p) {

View File

@ -21,8 +21,8 @@ import (
"fmt"
"strings"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
kruiseappslisters "github.com/openkruise/kruise/pkg/client/listers/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
kruiseappslisters "github.com/openkruise/kruise/pkg/client/listers/apps/v1beta1"
v1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
errorutils "k8s.io/apimachinery/pkg/util/errors"
@ -40,15 +40,15 @@ import (
type StatefulPodControlInterface interface {
// CreateStatefulPod create a Pod in a StatefulSet. Any PVCs necessary for the Pod are created prior to creating
// the Pod. If the returned error is nil the Pod and its PVCs have been created.
CreateStatefulPod(set *appsv1alpha1.StatefulSet, pod *v1.Pod) error
CreateStatefulPod(set *appsv1beta1.StatefulSet, pod *v1.Pod) error
// UpdateStatefulPod Updates a Pod in a StatefulSet. If the Pod already has the correct identity and stable
// storage this method is a no-op. If the Pod must be mutated to conform to the Set, it is mutated and updated.
// pod is an in-out parameter, and any updates made to the pod are reflected as mutations to this parameter. If
// the create is successful, the returned error is nil.
UpdateStatefulPod(set *appsv1alpha1.StatefulSet, pod *v1.Pod) error
UpdateStatefulPod(set *appsv1beta1.StatefulSet, pod *v1.Pod) error
// DeleteStatefulPod deletes a Pod in a StatefulSet. The pods PVCs are not deleted. If the delete is successful,
// the returned error is nil.
DeleteStatefulPod(set *appsv1alpha1.StatefulSet, pod *v1.Pod) error
DeleteStatefulPod(set *appsv1beta1.StatefulSet, pod *v1.Pod) error
}
// NewRealStatefulPodControl returns a new realStatefulPodControl
@ -72,7 +72,7 @@ type realStatefulPodControl struct {
recorder record.EventRecorder
}
func (spc *realStatefulPodControl) CreateStatefulPod(set *appsv1alpha1.StatefulSet, pod *v1.Pod) error {
func (spc *realStatefulPodControl) CreateStatefulPod(set *appsv1beta1.StatefulSet, pod *v1.Pod) error {
// Create the Pod's PVCs prior to creating the Pod
if err := spc.createPersistentVolumeClaims(set, pod); err != nil {
spc.recordPodEvent("create", set, pod, err)
@ -88,7 +88,7 @@ func (spc *realStatefulPodControl) CreateStatefulPod(set *appsv1alpha1.StatefulS
return err
}
func (spc *realStatefulPodControl) UpdateStatefulPod(set *appsv1alpha1.StatefulSet, pod *v1.Pod) error {
func (spc *realStatefulPodControl) UpdateStatefulPod(set *appsv1beta1.StatefulSet, pod *v1.Pod) error {
attemptedUpdate := false
err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
// assume the Pod is consistent
@ -135,7 +135,7 @@ func (spc *realStatefulPodControl) UpdateStatefulPod(set *appsv1alpha1.StatefulS
return err
}
func (spc *realStatefulPodControl) DeleteStatefulPod(set *appsv1alpha1.StatefulSet, pod *v1.Pod) error {
func (spc *realStatefulPodControl) DeleteStatefulPod(set *appsv1beta1.StatefulSet, pod *v1.Pod) error {
err := spc.client.CoreV1().Pods(set.Namespace).Delete(pod.Name, nil)
spc.recordPodEvent("delete", set, pod, err)
return err
@ -143,7 +143,7 @@ func (spc *realStatefulPodControl) DeleteStatefulPod(set *appsv1alpha1.StatefulS
// recordPodEvent records an event for verb applied to a Pod in a StatefulSet. If err is nil the generated event will
// have a reason of v1.EventTypeNormal. If err is not nil the generated event will have a reason of v1.EventTypeWarning.
func (spc *realStatefulPodControl) recordPodEvent(verb string, set *appsv1alpha1.StatefulSet, pod *v1.Pod, err error) {
func (spc *realStatefulPodControl) recordPodEvent(verb string, set *appsv1beta1.StatefulSet, pod *v1.Pod, err error) {
if err == nil {
reason := fmt.Sprintf("Successful%s", strings.Title(verb))
message := fmt.Sprintf("%s Pod %s in StatefulSet %s successful",
@ -160,7 +160,7 @@ func (spc *realStatefulPodControl) recordPodEvent(verb string, set *appsv1alpha1
// recordClaimEvent records an event for verb applied to the PersistentVolumeClaim of a Pod in a StatefulSet. If err is
// nil the generated event will have a reason of v1.EventTypeNormal. If err is not nil the generated event will have a
// reason of v1.EventTypeWarning.
func (spc *realStatefulPodControl) recordClaimEvent(verb string, set *appsv1alpha1.StatefulSet, pod *v1.Pod, claim *v1.PersistentVolumeClaim, err error) {
func (spc *realStatefulPodControl) recordClaimEvent(verb string, set *appsv1beta1.StatefulSet, pod *v1.Pod, claim *v1.PersistentVolumeClaim, err error) {
if err == nil {
reason := fmt.Sprintf("Successful%s", strings.Title(verb))
message := fmt.Sprintf("%s Claim %s Pod %s in StatefulSet %s success",
@ -178,7 +178,7 @@ func (spc *realStatefulPodControl) recordClaimEvent(verb string, set *appsv1alph
// set. If all of the claims for Pod are successfully created, the returned error is nil. If creation fails, this method
// may be called again until no error is returned, indicating the PersistentVolumeClaims for pod are consistent with
// set's Spec.
func (spc *realStatefulPodControl) createPersistentVolumeClaims(set *appsv1alpha1.StatefulSet, pod *v1.Pod) error {
func (spc *realStatefulPodControl) createPersistentVolumeClaims(set *appsv1beta1.StatefulSet, pod *v1.Pod) error {
var errs []error
for _, claim := range getPersistentVolumeClaims(set, pod) {
pvc, err := spc.pvcLister.PersistentVolumeClaims(claim.Namespace).Get(claim.Name)

View File

@ -33,7 +33,7 @@ import (
"k8s.io/kubernetes/pkg/controller/history"
utilpointer "k8s.io/utils/pointer"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
"github.com/openkruise/kruise/pkg/util/inplaceupdate"
)
@ -45,13 +45,13 @@ type ControlInterface interface {
// If an implementation returns a non-nil error, the invocation will be retried using a rate-limited strategy.
// Implementors should sink any errors that they do not wish to trigger a retry, and they may feel free to
// exit exceptionally at any point provided they wish the update to be re-run at a later point in time.
UpdateStatefulSet(set *appsv1alpha1.StatefulSet, pods []*v1.Pod) error
UpdateStatefulSet(set *appsv1beta1.StatefulSet, pods []*v1.Pod) error
// ListRevisions returns a array of the ControllerRevisions that represent the revisions of set. If the returned
// error is nil, the returns slice of ControllerRevisions is valid.
ListRevisions(set *appsv1alpha1.StatefulSet) ([]*apps.ControllerRevision, error)
ListRevisions(set *appsv1beta1.StatefulSet) ([]*apps.ControllerRevision, error)
// AdoptOrphanRevisions adopts any orphaned ControllerRevisions that match set's Selector. If all adoptions are
// successful the returned error is nil.
AdoptOrphanRevisions(set *appsv1alpha1.StatefulSet, revisions []*apps.ControllerRevision) error
AdoptOrphanRevisions(set *appsv1beta1.StatefulSet, revisions []*apps.ControllerRevision) error
}
// NewDefaultStatefulSetControl returns a new instance of the default implementation ControlInterface that
@ -91,7 +91,7 @@ type defaultStatefulSetControl struct {
// strategy allows these constraints to be relaxed - pods will be created and deleted eagerly and
// in no particular order. Clients using the burst strategy should be careful to ensure they
// understand the consistency implications of having unpredictable numbers of pods available.
func (ssc *defaultStatefulSetControl) UpdateStatefulSet(set *appsv1alpha1.StatefulSet, pods []*v1.Pod) error {
func (ssc *defaultStatefulSetControl) UpdateStatefulSet(set *appsv1beta1.StatefulSet, pods []*v1.Pod) error {
// list all revisions and sort them
revisions, err := ssc.ListRevisions(set)
@ -141,7 +141,7 @@ func (ssc *defaultStatefulSetControl) UpdateStatefulSet(set *appsv1alpha1.Statef
return ssc.truncateHistory(set, pods, revisions, currentRevision, updateRevision)
}
func (ssc *defaultStatefulSetControl) ListRevisions(set *appsv1alpha1.StatefulSet) ([]*apps.ControllerRevision, error) {
func (ssc *defaultStatefulSetControl) ListRevisions(set *appsv1beta1.StatefulSet) ([]*apps.ControllerRevision, error) {
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
if err != nil {
return nil, err
@ -150,7 +150,7 @@ func (ssc *defaultStatefulSetControl) ListRevisions(set *appsv1alpha1.StatefulSe
}
func (ssc *defaultStatefulSetControl) AdoptOrphanRevisions(
set *appsv1alpha1.StatefulSet,
set *appsv1beta1.StatefulSet,
revisions []*apps.ControllerRevision) error {
for i := range revisions {
adopted, err := ssc.controllerHistory.AdoptControllerRevision(set, controllerKind, revisions[i])
@ -168,7 +168,7 @@ func (ssc *defaultStatefulSetControl) AdoptOrphanRevisions(
// only RevisionHistoryLimit revisions remain. If the returned error is nil the operation was successful. This method
// expects that revisions is sorted when supplied.
func (ssc *defaultStatefulSetControl) truncateHistory(
set *appsv1alpha1.StatefulSet,
set *appsv1beta1.StatefulSet,
pods []*v1.Pod,
revisions []*apps.ControllerRevision,
current *apps.ControllerRevision,
@ -207,7 +207,7 @@ func (ssc *defaultStatefulSetControl) truncateHistory(
// a new revision, or modify the Revision of an existing revision if an update to set is detected.
// This method expects that revisions is sorted when supplied.
func (ssc *defaultStatefulSetControl) getStatefulSetRevisions(
set *appsv1alpha1.StatefulSet,
set *appsv1beta1.StatefulSet,
revisions []*apps.ControllerRevision) (*apps.ControllerRevision, *apps.ControllerRevision, int32, error) {
var currentRevision, updateRevision *apps.ControllerRevision
@ -280,12 +280,12 @@ func (ssc *defaultStatefulSetControl) getStatefulSetRevisions(
// TODO (RZ): Break the below spaghetti code into smaller chucks with unit tests
func (ssc *defaultStatefulSetControl) updateStatefulSet(
set *appsv1alpha1.StatefulSet,
set *appsv1beta1.StatefulSet,
currentRevision *apps.ControllerRevision,
updateRevision *apps.ControllerRevision,
collisionCount int32,
pods []*v1.Pod,
revisions []*apps.ControllerRevision) (*appsv1alpha1.StatefulSetStatus, error) {
revisions []*apps.ControllerRevision) (*appsv1beta1.StatefulSetStatus, error) {
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
if err != nil {
return set.Status.DeepCopy(), err
@ -302,7 +302,7 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
}
// set the generation, and revisions in the returned status
status := appsv1alpha1.StatefulSetStatus{}
status := appsv1beta1.StatefulSetStatus{}
status.ObservedGeneration = set.Generation
status.CurrentRevision = currentRevision.Name
status.UpdateRevision = updateRevision.Name
@ -433,7 +433,7 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
if !isCreated(replicas[i]) {
if err := ssc.podControl.CreateStatefulPod(set, replicas[i]); err != nil {
msg := fmt.Sprintf("StatefulPodControl failed to create Pod error: %s", err)
condition := NewStatefulsetCondition(appsv1alpha1.FailedCreatePod, v1.ConditionTrue, "", msg)
condition := NewStatefulsetCondition(appsv1beta1.FailedCreatePod, v1.ConditionTrue, "", msg)
SetStatefulsetCondition(&status, condition)
return &status, err
}
@ -504,7 +504,7 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
replica := replicas[i].DeepCopy()
if err := ssc.podControl.UpdateStatefulPod(updateSet, replica); err != nil {
msg := fmt.Sprintf("StatefulPodControl failed to update Pod error: %s", err)
condition := NewStatefulsetCondition(appsv1alpha1.FailedUpdatePod, v1.ConditionTrue, "", msg)
condition := NewStatefulsetCondition(appsv1beta1.FailedUpdatePod, v1.ConditionTrue, "", msg)
SetStatefulsetCondition(&status, condition)
return &status, err
}
@ -590,7 +590,7 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
var unavailablePods []string
updateIndexes := sortPodsToUpdate(set.Spec.UpdateStrategy.RollingUpdate, updateRevision.Name, replicas)
klog.V(5).Infof("Prepare to update pods indexes %v for StatefulSet %s", updateIndexes, getStatefulSetKey(set))
minWaitTime := appsv1alpha1.MaxMinReadySeconds * time.Second
minWaitTime := appsv1beta1.MaxMinReadySeconds * time.Second
// update pods in sequence
for _, target := range updateIndexes {
@ -661,14 +661,14 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
}
func (ssc *defaultStatefulSetControl) inPlaceUpdatePod(
set *appsv1alpha1.StatefulSet, pod *v1.Pod,
set *appsv1beta1.StatefulSet, pod *v1.Pod,
updateRevision *apps.ControllerRevision, revisions []*apps.ControllerRevision,
) (bool, error) {
if set.Spec.UpdateStrategy.RollingUpdate == nil {
return false, nil
}
if set.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy != appsv1alpha1.InPlaceIfPossiblePodUpdateStrategyType &&
set.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy != appsv1alpha1.InPlaceOnlyPodUpdateStrategyType {
if set.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy != appsv1beta1.InPlaceIfPossiblePodUpdateStrategyType &&
set.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy != appsv1beta1.InPlaceOnlyPodUpdateStrategyType {
return false, nil
}
@ -703,8 +703,8 @@ func (ssc *defaultStatefulSetControl) inPlaceUpdatePod(
// mutated to indicate completion. If status is semantically equivalent to set's Status no update is performed. If the
// returned error is nil, the update is successful.
func (ssc *defaultStatefulSetControl) updateStatefulSetStatus(
set *appsv1alpha1.StatefulSet,
status *appsv1alpha1.StatefulSetStatus) error {
set *appsv1beta1.StatefulSet,
status *appsv1beta1.StatefulSetStatus) error {
// complete any in progress rolling update if necessary
completeRollingUpdate(set, status)

File diff suppressed because it is too large Load Diff

View File

@ -20,9 +20,9 @@ package statefulset
import (
"fmt"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
clientset "github.com/openkruise/kruise/pkg/client/clientset/versioned"
appslisters "github.com/openkruise/kruise/pkg/client/listers/apps/v1alpha1"
appslisters "github.com/openkruise/kruise/pkg/client/listers/apps/v1beta1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/util/retry"
)
@ -32,7 +32,7 @@ import (
type StatusUpdaterInterface interface {
// UpdateStatefulSetStatus sets the set's Status to status. Implementations are required to retry on conflicts,
// but fail on other errors. If the returned error is nil set's Status has been successfully set to status.
UpdateStatefulSetStatus(set *appsv1alpha1.StatefulSet, status *appsv1alpha1.StatefulSetStatus) error
UpdateStatefulSetStatus(set *appsv1beta1.StatefulSet, status *appsv1beta1.StatefulSetStatus) error
}
// NewRealStatefulSetStatusUpdater returns a StatusUpdaterInterface that updates the Status of a StatefulSet,
@ -49,12 +49,12 @@ type realStatefulSetStatusUpdater struct {
}
func (ssu *realStatefulSetStatusUpdater) UpdateStatefulSetStatus(
set *appsv1alpha1.StatefulSet,
status *appsv1alpha1.StatefulSetStatus) error {
set *appsv1beta1.StatefulSet,
status *appsv1beta1.StatefulSetStatus) error {
// don't wait due to limited number of clients, but backoff after the default number of steps
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
set.Status = *status
_, updateErr := ssu.client.AppsV1alpha1().StatefulSets(set.Namespace).UpdateStatus(set)
_, updateErr := ssu.client.AppsV1beta1().StatefulSets(set.Namespace).UpdateStatus(set)
if updateErr == nil {
return nil
}

View File

@ -21,9 +21,9 @@ import (
"errors"
"testing"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
"github.com/openkruise/kruise/pkg/client/clientset/versioned/fake"
kruiseappslisters "github.com/openkruise/kruise/pkg/client/listers/apps/v1alpha1"
kruiseappslisters "github.com/openkruise/kruise/pkg/client/listers/apps/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
core "k8s.io/client-go/testing"
@ -32,7 +32,7 @@ import (
func TestStatefulSetUpdaterUpdatesSetStatus(t *testing.T) {
set := newStatefulSet(3)
status := appsv1alpha1.StatefulSetStatus{ObservedGeneration: 1, Replicas: 2}
status := appsv1beta1.StatefulSetStatus{ObservedGeneration: 1, Replicas: 2}
fakeClient := &fake.Clientset{}
updater := NewRealStatefulSetStatusUpdater(fakeClient, nil)
fakeClient.AddReactor("update", "statefulsets", func(action core.Action) (bool, runtime.Object, error) {
@ -49,12 +49,12 @@ func TestStatefulSetUpdaterUpdatesSetStatus(t *testing.T) {
func TestStatefulSetStatusUpdaterUpdatesObservedGeneration(t *testing.T) {
set := newStatefulSet(3)
status := appsv1alpha1.StatefulSetStatus{ObservedGeneration: 3, Replicas: 2}
status := appsv1beta1.StatefulSetStatus{ObservedGeneration: 3, Replicas: 2}
fakeClient := &fake.Clientset{}
updater := NewRealStatefulSetStatusUpdater(fakeClient, nil)
fakeClient.AddReactor("update", "statefulsets", func(action core.Action) (bool, runtime.Object, error) {
update := action.(core.UpdateAction)
sts := update.GetObject().(*appsv1alpha1.StatefulSet)
sts := update.GetObject().(*appsv1beta1.StatefulSet)
if sts.Status.ObservedGeneration != 3 {
t.Errorf("expected observedGeneration to be synced with generation for statefulset %q", sts.Name)
}
@ -67,7 +67,7 @@ func TestStatefulSetStatusUpdaterUpdatesObservedGeneration(t *testing.T) {
func TestStatefulSetStatusUpdaterUpdateReplicasFailure(t *testing.T) {
set := newStatefulSet(3)
status := appsv1alpha1.StatefulSetStatus{ObservedGeneration: 3, Replicas: 2}
status := appsv1beta1.StatefulSetStatus{ObservedGeneration: 3, Replicas: 2}
fakeClient := &fake.Clientset{}
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
indexer.Add(set)
@ -83,7 +83,7 @@ func TestStatefulSetStatusUpdaterUpdateReplicasFailure(t *testing.T) {
func TestStatefulSetStatusUpdaterUpdateReplicasConflict(t *testing.T) {
set := newStatefulSet(3)
status := appsv1alpha1.StatefulSetStatus{ObservedGeneration: 3, Replicas: 2}
status := appsv1beta1.StatefulSetStatus{ObservedGeneration: 3, Replicas: 2}
conflict := false
fakeClient := &fake.Clientset{}
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
@ -108,7 +108,7 @@ func TestStatefulSetStatusUpdaterUpdateReplicasConflict(t *testing.T) {
func TestStatefulSetStatusUpdaterUpdateReplicasConflictFailure(t *testing.T) {
set := newStatefulSet(3)
status := appsv1alpha1.StatefulSetStatus{ObservedGeneration: 3, Replicas: 2}
status := appsv1beta1.StatefulSetStatus{ObservedGeneration: 3, Replicas: 2}
fakeClient := &fake.Clientset{}
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
indexer.Add(set)

View File

@ -35,10 +35,10 @@ import (
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/history"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
)
var patchCodec = scheme.Codecs.LegacyCodec(appsv1alpha1.SchemeGroupVersion)
var patchCodec = scheme.Codecs.LegacyCodec(appsv1beta1.SchemeGroupVersion)
// statefulPodRegex is a regular expression that extracts the parent StatefulSet and ordinal from the Name of a Pod
var statefulPodRegex = regexp.MustCompile("(.*)-([0-9]+)$")
@ -73,24 +73,24 @@ func getOrdinal(pod *v1.Pod) int {
}
// getPodName gets the name of set's child Pod with an ordinal index of ordinal
func getPodName(set *appsv1alpha1.StatefulSet, ordinal int) string {
func getPodName(set *appsv1beta1.StatefulSet, ordinal int) string {
return fmt.Sprintf("%s-%d", set.Name, ordinal)
}
// getPersistentVolumeClaimName gets the name of PersistentVolumeClaim for a Pod with an ordinal index of ordinal. claim
// must be a PersistentVolumeClaim from set's VolumeClaims template.
func getPersistentVolumeClaimName(set *appsv1alpha1.StatefulSet, claim *v1.PersistentVolumeClaim, ordinal int) string {
func getPersistentVolumeClaimName(set *appsv1beta1.StatefulSet, claim *v1.PersistentVolumeClaim, ordinal int) string {
// NOTE: This name format is used by the heuristics for zone spreading in ChooseZoneForVolume
return fmt.Sprintf("%s-%s-%d", claim.Name, set.Name, ordinal)
}
// isMemberOf tests if pod is a member of set.
func isMemberOf(set *appsv1alpha1.StatefulSet, pod *v1.Pod) bool {
func isMemberOf(set *appsv1beta1.StatefulSet, pod *v1.Pod) bool {
return getParentName(pod) == set.Name
}
// identityMatches returns true if pod has a valid identity and network identity for a member of set.
func identityMatches(set *appsv1alpha1.StatefulSet, pod *v1.Pod) bool {
func identityMatches(set *appsv1beta1.StatefulSet, pod *v1.Pod) bool {
parent, ordinal := getParentNameAndOrdinal(pod)
return ordinal >= 0 &&
set.Name == parent &&
@ -100,7 +100,7 @@ func identityMatches(set *appsv1alpha1.StatefulSet, pod *v1.Pod) bool {
}
// storageMatches returns true if pod's Volumes cover the set of PersistentVolumeClaims
func storageMatches(set *appsv1alpha1.StatefulSet, pod *v1.Pod) bool {
func storageMatches(set *appsv1beta1.StatefulSet, pod *v1.Pod) bool {
ordinal := getOrdinal(pod)
if ordinal < 0 {
return false
@ -124,7 +124,7 @@ func storageMatches(set *appsv1alpha1.StatefulSet, pod *v1.Pod) bool {
// getPersistentVolumeClaims gets a map of PersistentVolumeClaims to their template names, as defined in set. The
// returned PersistentVolumeClaims are each constructed with a the name specific to the Pod. This name is determined
// by getPersistentVolumeClaimName.
func getPersistentVolumeClaims(set *appsv1alpha1.StatefulSet, pod *v1.Pod) map[string]v1.PersistentVolumeClaim {
func getPersistentVolumeClaims(set *appsv1beta1.StatefulSet, pod *v1.Pod) map[string]v1.PersistentVolumeClaim {
ordinal := getOrdinal(pod)
templates := set.Spec.VolumeClaimTemplates
claims := make(map[string]v1.PersistentVolumeClaim, len(templates))
@ -140,7 +140,7 @@ func getPersistentVolumeClaims(set *appsv1alpha1.StatefulSet, pod *v1.Pod) map[s
// updateStorage updates pod's Volumes to conform with the PersistentVolumeClaim of set's templates. If pod has
// conflicting local Volumes these are replaced with Volumes that conform to the set's templates.
func updateStorage(set *appsv1alpha1.StatefulSet, pod *v1.Pod) {
func updateStorage(set *appsv1beta1.StatefulSet, pod *v1.Pod) {
currentVolumes := pod.Spec.Volumes
claims := getPersistentVolumeClaims(set, pod)
newVolumes := make([]v1.Volume, 0, len(claims))
@ -164,7 +164,7 @@ func updateStorage(set *appsv1alpha1.StatefulSet, pod *v1.Pod) {
pod.Spec.Volumes = newVolumes
}
func initIdentity(set *appsv1alpha1.StatefulSet, pod *v1.Pod) {
func initIdentity(set *appsv1beta1.StatefulSet, pod *v1.Pod) {
updateIdentity(set, pod)
// Set these immutable fields only on initial Pod creation, not updates.
pod.Spec.Hostname = pod.Name
@ -173,7 +173,7 @@ func initIdentity(set *appsv1alpha1.StatefulSet, pod *v1.Pod) {
// updateIdentity updates pod's name, hostname, and subdomain, and StatefulSetPodNameLabel to conform to set's name
// and headless service.
func updateIdentity(set *appsv1alpha1.StatefulSet, pod *v1.Pod) {
func updateIdentity(set *appsv1beta1.StatefulSet, pod *v1.Pod) {
pod.Name = getPodName(set, getOrdinal(pod))
pod.Namespace = set.Namespace
if pod.Labels == nil {
@ -232,12 +232,12 @@ func isHealthy(pod *v1.Pod) bool {
}
// allowsBurst is true if the alpha burst annotation is set.
func allowsBurst(set *appsv1alpha1.StatefulSet) bool {
func allowsBurst(set *appsv1beta1.StatefulSet) bool {
return set.Spec.PodManagementPolicy == apps.ParallelPodManagement
}
// getMinReadySeconds returns the minReadySeconds set in the rollingUpdate, default is 0
func getMinReadySeconds(set *appsv1alpha1.StatefulSet) int32 {
func getMinReadySeconds(set *appsv1beta1.StatefulSet) int32 {
if set.Spec.UpdateStrategy.RollingUpdate == nil ||
set.Spec.UpdateStrategy.RollingUpdate.MinReadySeconds == nil {
return 0
@ -263,7 +263,7 @@ func getPodRevision(pod *v1.Pod) string {
}
// newStatefulSetPod returns a new Pod conforming to the set's Spec with an identity generated from ordinal.
func newStatefulSetPod(set *appsv1alpha1.StatefulSet, ordinal int) *v1.Pod {
func newStatefulSetPod(set *appsv1beta1.StatefulSet, ordinal int) *v1.Pod {
pod, _ := controller.GetPodFromTemplate(&set.Spec.Template, set, metav1.NewControllerRef(set, controllerKind))
pod.Name = getPodName(set, ordinal)
initIdentity(set, pod)
@ -275,7 +275,7 @@ func newStatefulSetPod(set *appsv1alpha1.StatefulSet, ordinal int) *v1.Pod {
// current revision. updateSet is the representation of the set at the updateRevision. currentRevision is the name of
// the current revision. updateRevision is the name of the update revision. ordinal is the ordinal of the Pod. If the
// returned error is nil, the returned Pod is valid.
func newVersionedStatefulSetPod(currentSet, updateSet *appsv1alpha1.StatefulSet, currentRevision, updateRevision string,
func newVersionedStatefulSetPod(currentSet, updateSet *appsv1beta1.StatefulSet, currentRevision, updateRevision string,
ordinal int, replicas []*v1.Pod,
) *v1.Pod {
if isCurrentRevisionNeeded(currentSet, updateRevision, ordinal, replicas) {
@ -289,7 +289,7 @@ func newVersionedStatefulSetPod(currentSet, updateSet *appsv1alpha1.StatefulSet,
}
// isCurrentRevisionNeeded calculate if the 'ordinal' Pod should be current revision.
func isCurrentRevisionNeeded(set *appsv1alpha1.StatefulSet, updateRevision string, ordinal int, replicas []*v1.Pod) bool {
func isCurrentRevisionNeeded(set *appsv1beta1.StatefulSet, updateRevision string, ordinal int, replicas []*v1.Pod) bool {
if set.Spec.UpdateStrategy.Type != apps.RollingUpdateStatefulSetStrategyType {
return false
}
@ -313,7 +313,7 @@ func isCurrentRevisionNeeded(set *appsv1alpha1.StatefulSet, updateRevision strin
}
// Match check if the given StatefulSet's template matches the template stored in the given history.
func Match(ss *appsv1alpha1.StatefulSet, history *apps.ControllerRevision) (bool, error) {
func Match(ss *appsv1beta1.StatefulSet, history *apps.ControllerRevision) (bool, error) {
patch, err := getPatch(ss)
if err != nil {
return false, err
@ -325,7 +325,7 @@ func Match(ss *appsv1alpha1.StatefulSet, history *apps.ControllerRevision) (bool
// previous version. If the returned error is nil the patch is valid. The current state that we save is just the
// PodSpecTemplate. We can modify this later to encompass more state (or less) and remain compatible with previously
// recorded patches.
func getPatch(set *appsv1alpha1.StatefulSet) ([]byte, error) {
func getPatch(set *appsv1beta1.StatefulSet) ([]byte, error) {
str, err := runtime.Encode(patchCodec, set)
if err != nil {
return nil, err
@ -350,7 +350,7 @@ func getPatch(set *appsv1alpha1.StatefulSet) ([]byte, error) {
// The Revision of the returned ControllerRevision is set to revision. If the returned error is nil, the returned
// ControllerRevision is valid. StatefulSet revisions are stored as patches that re-apply the current state of set
// to a new StatefulSet using a strategic merge patch to replace the saved state of the new StatefulSet.
func newRevision(set *appsv1alpha1.StatefulSet, revision int64, collisionCount *int32) (*apps.ControllerRevision, error) {
func newRevision(set *appsv1beta1.StatefulSet, revision int64, collisionCount *int32) (*apps.ControllerRevision, error) {
patch, err := getPatch(set)
if err != nil {
return nil, err
@ -375,13 +375,13 @@ func newRevision(set *appsv1alpha1.StatefulSet, revision int64, collisionCount *
// ApplyRevision returns a new StatefulSet constructed by restoring the state in revision to set. If the returned error
// is nil, the returned StatefulSet is valid.
func ApplyRevision(set *appsv1alpha1.StatefulSet, revision *apps.ControllerRevision) (*appsv1alpha1.StatefulSet, error) {
func ApplyRevision(set *appsv1beta1.StatefulSet, revision *apps.ControllerRevision) (*appsv1beta1.StatefulSet, error) {
clone := set.DeepCopy()
patched, err := strategicpatch.StrategicMergePatch([]byte(runtime.EncodeOrDie(patchCodec, clone)), revision.Data.Raw, clone)
if err != nil {
return nil, err
}
restoredSet := &appsv1alpha1.StatefulSet{}
restoredSet := &appsv1beta1.StatefulSet{}
err = json.Unmarshal(patched, restoredSet)
if err != nil {
return nil, err
@ -402,7 +402,7 @@ func nextRevision(revisions []*apps.ControllerRevision) int64 {
// inconsistentStatus returns true if the ObservedGeneration of status is greater than set's
// Generation or if any of the status's fields do not match those of set's status.
func inconsistentStatus(set *appsv1alpha1.StatefulSet, status *appsv1alpha1.StatefulSetStatus) bool {
func inconsistentStatus(set *appsv1beta1.StatefulSet, status *appsv1beta1.StatefulSetStatus) bool {
return status.ObservedGeneration > set.Status.ObservedGeneration ||
status.Replicas != set.Status.Replicas ||
status.CurrentReplicas != set.Status.CurrentReplicas ||
@ -418,7 +418,7 @@ func inconsistentStatus(set *appsv1alpha1.StatefulSet, status *appsv1alpha1.Stat
// to the updateRevision. status's currentRevision is set to updateRevision and its' updateRevision
// is set to the empty string. status's currentReplicas is set to updateReplicas and its updateReplicas
// are set to 0.
func completeRollingUpdate(set *appsv1alpha1.StatefulSet, status *appsv1alpha1.StatefulSetStatus) {
func completeRollingUpdate(set *appsv1beta1.StatefulSet, status *appsv1beta1.StatefulSetStatus) {
if set.Spec.UpdateStrategy.Type == apps.RollingUpdateStatefulSetStrategyType &&
status.UpdatedReplicas == status.Replicas &&
status.ReadyReplicas == status.Replicas {
@ -456,7 +456,7 @@ func NewStatefulsetCondition(conditionType apps.StatefulSetConditionType, condit
}
// GetStatefulsetConditition returns the condition with the provided type.
func GetStatefulsetConditition(status appsv1alpha1.StatefulSetStatus, condType apps.StatefulSetConditionType) *apps.StatefulSetCondition {
func GetStatefulsetConditition(status appsv1beta1.StatefulSetStatus, condType apps.StatefulSetConditionType) *apps.StatefulSetCondition {
for i := range status.Conditions {
c := status.Conditions[i]
if c.Type == condType {
@ -467,7 +467,7 @@ func GetStatefulsetConditition(status appsv1alpha1.StatefulSetStatus, condType a
}
// SetStatefulsetCondition updates the statefulset to include the provided condition. If the condition that
func SetStatefulsetCondition(status *appsv1alpha1.StatefulSetStatus, condition apps.StatefulSetCondition) {
func SetStatefulsetCondition(status *appsv1beta1.StatefulSetStatus, condition apps.StatefulSetCondition) {
currentCond := GetStatefulsetConditition(*status, condition.Type)
if currentCond != nil && currentCond.Status == condition.Status && currentCond.Reason == condition.Reason {
return
@ -495,7 +495,7 @@ func getStatefulSetKey(o metav1.Object) string {
return o.GetNamespace() + "/" + o.GetName()
}
func isInPlaceOnly(set *appsv1alpha1.StatefulSet) bool {
func isInPlaceOnly(set *appsv1beta1.StatefulSet) bool {
return set.Spec.UpdateStrategy.RollingUpdate != nil &&
set.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy == appsv1alpha1.InPlaceOnlyPodUpdateStrategyType
set.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy == appsv1beta1.InPlaceOnlyPodUpdateStrategyType
}

View File

@ -36,12 +36,12 @@ import (
"k8s.io/kubernetes/pkg/controller/history"
utilpointer "k8s.io/utils/pointer"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
)
// overlappingStatefulSets sorts a list of StatefulSets by creation timestamp, using their names as a tie breaker.
// Generally used to tie break between StatefulSets that have overlapping selectors.
type overlappingStatefulSets []*appsv1alpha1.StatefulSet
type overlappingStatefulSets []*appsv1beta1.StatefulSet
func (o overlappingStatefulSets) Len() int { return len(o) }
@ -221,7 +221,7 @@ func TestGetMinReadySeconds(t *testing.T) {
if getMinReadySeconds(set) != 0 {
t.Error("getMinReadySeconds should be zero")
}
set.Spec.UpdateStrategy.RollingUpdate = &appsv1alpha1.RollingUpdateStatefulSetStrategy{}
set.Spec.UpdateStrategy.RollingUpdate = &appsv1beta1.RollingUpdateStatefulSetStrategy{}
if getMinReadySeconds(set) != 0 {
t.Error("getMinReadySeconds should be zero")
}
@ -286,7 +286,7 @@ func TestAscendingOrdinal(t *testing.T) {
}
func TestOverlappingStatefulSets(t *testing.T) {
sets := make([]*appsv1alpha1.StatefulSet, 10)
sets := make([]*appsv1beta1.StatefulSet, 10)
perm := rand.Perm(10)
for i, v := range perm {
sets[i] = newStatefulSet(10)
@ -313,7 +313,7 @@ func TestNewPodControllerRef(t *testing.T) {
if controllerRef == nil {
t.Fatalf("No ControllerRef found on new pod")
}
if got, want := controllerRef.APIVersion, appsv1alpha1.SchemeGroupVersion.String(); got != want {
if got, want := controllerRef.APIVersion, appsv1beta1.SchemeGroupVersion.String(); got != want {
t.Errorf("controllerRef.APIVersion = %q, want %q", got, want)
}
if got, want := controllerRef.Kind, "StatefulSet"; got != want {
@ -412,7 +412,7 @@ func newPVC(name string) v1.PersistentVolumeClaim {
}
}
func newStatefulSetWithVolumes(replicas int, name string, petMounts []v1.VolumeMount, podMounts []v1.VolumeMount) *appsv1alpha1.StatefulSet {
func newStatefulSetWithVolumes(replicas int, name string, petMounts []v1.VolumeMount, podMounts []v1.VolumeMount) *appsv1beta1.StatefulSet {
mounts := append(petMounts, podMounts...)
claims := []v1.PersistentVolumeClaim{}
for _, m := range petMounts {
@ -446,7 +446,7 @@ func newStatefulSetWithVolumes(replicas int, name string, petMounts []v1.VolumeM
template.Labels = map[string]string{"foo": "bar"}
return &appsv1alpha1.StatefulSet{
return &appsv1beta1.StatefulSet{
TypeMeta: metav1.TypeMeta{
Kind: "StatefulSet",
APIVersion: "apps/v1",
@ -456,7 +456,7 @@ func newStatefulSetWithVolumes(replicas int, name string, petMounts []v1.VolumeM
Namespace: v1.NamespaceDefault,
UID: types.UID("test"),
},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"foo": "bar"},
},
@ -464,7 +464,7 @@ func newStatefulSetWithVolumes(replicas int, name string, petMounts []v1.VolumeM
Template: template,
VolumeClaimTemplates: claims,
ServiceName: "governingsvc",
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
RevisionHistoryLimit: func() *int32 {
limit := int32(2)
return &limit
@ -473,7 +473,7 @@ func newStatefulSetWithVolumes(replicas int, name string, petMounts []v1.VolumeM
}
}
func newStatefulSet(replicas int) *appsv1alpha1.StatefulSet {
func newStatefulSet(replicas int) *appsv1beta1.StatefulSet {
petMounts := []v1.VolumeMount{
{Name: "datadir", MountPath: "/tmp/zookeeper"},
}

View File

@ -17,12 +17,12 @@ limitations under the License.
package statefulset
import (
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
"github.com/openkruise/kruise/pkg/util/updatesort"
v1 "k8s.io/api/core/v1"
)
func sortPodsToUpdate(rollingUpdateStrategy *appsv1alpha1.RollingUpdateStatefulSetStrategy, updateRevision string, replicas []*v1.Pod) []int {
func sortPodsToUpdate(rollingUpdateStrategy *appsv1beta1.RollingUpdateStatefulSetStrategy, updateRevision string, replicas []*v1.Pod) []int {
var updateMin int
if rollingUpdateStrategy != nil && rollingUpdateStrategy.Partition != nil {
updateMin = int(*rollingUpdateStrategy.Partition)

View File

@ -20,7 +20,8 @@ import (
"reflect"
"testing"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appspub "github.com/openkruise/kruise/apis/apps/pub"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -28,7 +29,7 @@ import (
func TestSortPodsToUpdate(t *testing.T) {
cases := []struct {
strategy *appsv1alpha1.RollingUpdateStatefulSetStrategy
strategy *appsv1beta1.RollingUpdateStatefulSetStrategy
updateRevision string
replicas []*v1.Pod
expected []int
@ -44,9 +45,9 @@ func TestSortPodsToUpdate(t *testing.T) {
expected: []int{2, 1, 0},
},
{
strategy: &appsv1alpha1.RollingUpdateStatefulSetStrategy{
UnorderedUpdate: &appsv1alpha1.UnorderedUpdateStrategy{PriorityStrategy: &appsv1alpha1.UpdatePriorityStrategy{
WeightPriority: []appsv1alpha1.UpdatePriorityWeightTerm{
strategy: &appsv1beta1.RollingUpdateStatefulSetStrategy{
UnorderedUpdate: &appsv1beta1.UnorderedUpdateStrategy{PriorityStrategy: &appspub.UpdatePriorityStrategy{
WeightPriority: []appspub.UpdatePriorityWeightTerm{
{Weight: 20, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"k": "v1"}}},
{Weight: 10, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"k": "v2"}}},
},

View File

@ -22,10 +22,10 @@ import (
"fmt"
"time"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
"github.com/openkruise/kruise/pkg/client"
kruiseclientset "github.com/openkruise/kruise/pkg/client/clientset/versioned"
kruiseappslisters "github.com/openkruise/kruise/pkg/client/listers/apps/v1alpha1"
kruiseappslisters "github.com/openkruise/kruise/pkg/client/listers/apps/v1beta1"
"github.com/openkruise/kruise/pkg/util/expectations"
"github.com/openkruise/kruise/pkg/util/gate"
"github.com/openkruise/kruise/pkg/util/inplaceupdate"
@ -61,7 +61,7 @@ func init() {
var (
// controllerKind contains the schema.GroupVersionKind for this controller type.
controllerKind = appsv1alpha1.SchemeGroupVersion.WithKind("StatefulSet")
controllerKind = appsv1beta1.SchemeGroupVersion.WithKind("StatefulSet")
concurrentReconciles = 3
updateExpectations = expectations.NewUpdateExpectations(func(o metav1.Object) string {
@ -75,7 +75,7 @@ var (
// Add creates a new StatefulSet Controller and adds it to the Manager with default RBAC. The Manager will set fields on the Controller
// and Start it when the Manager is Started.
func Add(mgr manager.Manager) error {
if !gate.ResourceEnabled(&appsv1alpha1.StatefulSet{}) {
if !gate.ResourceEnabled(&appsv1beta1.StatefulSet{}) {
return nil
}
r, err := newReconciler(mgr)
@ -162,10 +162,10 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
}
// Watch for changes to StatefulSet
err = c.Watch(&source.Kind{Type: &appsv1alpha1.StatefulSet{}}, &handler.EnqueueRequestForObject{}, predicate.Funcs{
err = c.Watch(&source.Kind{Type: &appsv1beta1.StatefulSet{}}, &handler.EnqueueRequestForObject{}, predicate.Funcs{
UpdateFunc: func(e event.UpdateEvent) bool {
oldSS := e.ObjectOld.(*appsv1alpha1.StatefulSet)
newSS := e.ObjectNew.(*appsv1alpha1.StatefulSet)
oldSS := e.ObjectOld.(*appsv1beta1.StatefulSet)
newSS := e.ObjectNew.(*appsv1beta1.StatefulSet)
if oldSS.Status.Replicas != newSS.Status.Replicas {
klog.V(4).Infof("Observed updated replica count for StatefulSet: %v, %d->%d", newSS.Name, oldSS.Status.Replicas, newSS.Status.Replicas)
}
@ -179,7 +179,7 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
// Watch for changes to Pod created by StatefulSet
err = c.Watch(&source.Kind{Type: &v1.Pod{}}, &handler.EnqueueRequestForOwner{
IsController: true,
OwnerType: &appsv1alpha1.StatefulSet{},
OwnerType: &appsv1beta1.StatefulSet{},
})
if err != nil {
return err
@ -251,7 +251,7 @@ func (ssc *ReconcileStatefulSet) Reconcile(request reconcile.Request) (res recon
}
// adoptOrphanRevisions adopts any orphaned ControllerRevisions matched by set's Selector.
func (ssc *ReconcileStatefulSet) adoptOrphanRevisions(set *appsv1alpha1.StatefulSet) error {
func (ssc *ReconcileStatefulSet) adoptOrphanRevisions(set *appsv1beta1.StatefulSet) error {
revisions, err := ssc.control.ListRevisions(set)
if err != nil {
return err
@ -263,7 +263,7 @@ func (ssc *ReconcileStatefulSet) adoptOrphanRevisions(set *appsv1alpha1.Stateful
}
}
if len(orphanRevisions) > 0 {
fresh, err := ssc.kruiseClient.AppsV1alpha1().StatefulSets(set.Namespace).Get(set.Name, metav1.GetOptions{})
fresh, err := ssc.kruiseClient.AppsV1beta1().StatefulSets(set.Namespace).Get(set.Name, metav1.GetOptions{})
if err != nil {
return err
}
@ -280,7 +280,7 @@ func (ssc *ReconcileStatefulSet) adoptOrphanRevisions(set *appsv1alpha1.Stateful
//
// NOTE: Returned Pods are pointers to objects from the cache.
// If you need to modify one, you need to copy it first.
func (ssc *ReconcileStatefulSet) getPodsForStatefulSet(set *appsv1alpha1.StatefulSet, selector labels.Selector) ([]*v1.Pod, error) {
func (ssc *ReconcileStatefulSet) getPodsForStatefulSet(set *appsv1beta1.StatefulSet, selector labels.Selector) ([]*v1.Pod, error) {
// List all pods to include the pods that don't match the selector anymore but
// has a ControllerRef pointing to this StatefulSet.
pods, err := ssc.podLister.Pods(set.Namespace).List(labels.Everything())
@ -296,7 +296,7 @@ func (ssc *ReconcileStatefulSet) getPodsForStatefulSet(set *appsv1alpha1.Statefu
// If any adoptions are attempted, we should first recheck for deletion with
// an uncached quorum read sometime after listing Pods (see #42639).
canAdoptFunc := kubecontroller.RecheckDeletionTimestamp(func() (metav1.Object, error) {
fresh, err := ssc.kruiseClient.AppsV1alpha1().StatefulSets(set.Namespace).Get(set.Name, metav1.GetOptions{})
fresh, err := ssc.kruiseClient.AppsV1beta1().StatefulSets(set.Namespace).Get(set.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
@ -311,7 +311,7 @@ func (ssc *ReconcileStatefulSet) getPodsForStatefulSet(set *appsv1alpha1.Statefu
}
// syncStatefulSet syncs a tuple of (statefulset, []*v1.Pod).
func (ssc *ReconcileStatefulSet) syncStatefulSet(set *appsv1alpha1.StatefulSet, pods []*v1.Pod) error {
func (ssc *ReconcileStatefulSet) syncStatefulSet(set *appsv1beta1.StatefulSet, pods []*v1.Pod) error {
klog.V(4).Infof("Syncing StatefulSet %v/%v with %d pods", set.Namespace, set.Name, len(pods))
// TODO: investigate where we mutate the set during the update as it is not obvious.
if err := ssc.control.UpdateStatefulSet(set.DeepCopy(), pods); err != nil {

View File

@ -24,12 +24,12 @@ import (
"testing"
"time"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
kruiseclientset "github.com/openkruise/kruise/pkg/client/clientset/versioned"
kruisefake "github.com/openkruise/kruise/pkg/client/clientset/versioned/fake"
kruiseinformers "github.com/openkruise/kruise/pkg/client/informers/externalversions"
kruiseappsinformers "github.com/openkruise/kruise/pkg/client/informers/externalversions/apps/v1alpha1"
kruiseappslisters "github.com/openkruise/kruise/pkg/client/listers/apps/v1alpha1"
kruiseappsinformers "github.com/openkruise/kruise/pkg/client/informers/externalversions/apps/v1beta1"
kruiseappslisters "github.com/openkruise/kruise/pkg/client/listers/apps/v1beta1"
"github.com/openkruise/kruise/pkg/util/inplaceupdate"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
@ -72,7 +72,7 @@ func TestStatefulSetControllerCreates(t *testing.T) {
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
t.Error(err)
} else {
set = obj.(*appsv1alpha1.StatefulSet)
set = obj.(*appsv1beta1.StatefulSet)
}
if set.Status.Replicas != 3 {
t.Errorf("set.Status.Replicas = %v; want 3", set.Status.Replicas)
@ -88,7 +88,7 @@ func TestStatefulSetControllerDeletes(t *testing.T) {
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
t.Error(err)
} else {
set = obj.(*appsv1alpha1.StatefulSet)
set = obj.(*appsv1beta1.StatefulSet)
}
if set.Status.Replicas != 3 {
t.Errorf("set.Status.Replicas = %v; want 3", set.Status.Replicas)
@ -100,7 +100,7 @@ func TestStatefulSetControllerDeletes(t *testing.T) {
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
t.Error(err)
} else {
set = obj.(*appsv1alpha1.StatefulSet)
set = obj.(*appsv1beta1.StatefulSet)
}
if set.Status.Replicas != 0 {
t.Errorf("set.Status.Replicas = %v; want 0", set.Status.Replicas)
@ -116,7 +116,7 @@ func TestStatefulSetControllerRespectsTermination(t *testing.T) {
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
t.Error(err)
} else {
set = obj.(*appsv1alpha1.StatefulSet)
set = obj.(*appsv1beta1.StatefulSet)
}
if set.Status.Replicas != 3 {
t.Errorf("set.Status.Replicas = %v; want 3", set.Status.Replicas)
@ -151,7 +151,7 @@ func TestStatefulSetControllerRespectsTermination(t *testing.T) {
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
t.Error(err)
} else {
set = obj.(*appsv1alpha1.StatefulSet)
set = obj.(*appsv1beta1.StatefulSet)
}
if set.Status.Replicas != 0 {
t.Errorf("set.Status.Replicas = %v; want 0", set.Status.Replicas)
@ -167,7 +167,7 @@ func TestStatefulSetControllerBlocksScaling(t *testing.T) {
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
t.Error(err)
} else {
set = obj.(*appsv1alpha1.StatefulSet)
set = obj.(*appsv1beta1.StatefulSet)
}
if set.Status.Replicas != 3 {
t.Errorf("set.Status.Replicas = %v; want 3", set.Status.Replicas)
@ -604,7 +604,7 @@ func splitObjects(initialObjects []runtime.Object) ([]runtime.Object, []runtime.
var kubeObjects []runtime.Object
var kruiseObjects []runtime.Object
for _, o := range initialObjects {
if _, ok := o.(*appsv1alpha1.StatefulSet); ok {
if _, ok := o.(*appsv1beta1.StatefulSet); ok {
kruiseObjects = append(kruiseObjects, o)
} else {
kubeObjects = append(kubeObjects, o)
@ -619,11 +619,11 @@ func newFakeStatefulSetController(initialObjects ...runtime.Object) (*StatefulSe
kruiseClient := kruisefake.NewSimpleClientset(kruiseObjects...)
informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
kruiseInformerFactory := kruiseinformers.NewSharedInformerFactory(kruiseClient, controller.NoResyncPeriodFunc())
fpc := newFakeStatefulPodControl(informerFactory.Core().V1().Pods(), kruiseInformerFactory.Apps().V1alpha1().StatefulSets())
ssu := newFakeStatefulSetStatusUpdater(kruiseInformerFactory.Apps().V1alpha1().StatefulSets())
fpc := newFakeStatefulPodControl(informerFactory.Core().V1().Pods(), kruiseInformerFactory.Apps().V1beta1().StatefulSets())
ssu := newFakeStatefulSetStatusUpdater(kruiseInformerFactory.Apps().V1beta1().StatefulSets())
ssc := NewStatefulSetController(
informerFactory.Core().V1().Pods(),
kruiseInformerFactory.Apps().V1alpha1().StatefulSets(),
kruiseInformerFactory.Apps().V1beta1().StatefulSets(),
informerFactory.Core().V1().PersistentVolumeClaims(),
informerFactory.Apps().V1().ControllerRevisions(),
client,
@ -654,7 +654,7 @@ func getPodAtOrdinal(pods []*v1.Pod, ordinal int) *v1.Pod {
return pods[ordinal]
}
func scaleUpStatefulSetController(set *appsv1alpha1.StatefulSet, ssc *StatefulSetController, spc *fakeStatefulPodControl) error {
func scaleUpStatefulSetController(set *appsv1beta1.StatefulSet, ssc *StatefulSetController, spc *fakeStatefulPodControl) error {
spc.setsIndexer.Add(set)
ssc.enqueueStatefulSet(set)
fakeWorker(ssc)
@ -697,12 +697,12 @@ func scaleUpStatefulSetController(set *appsv1alpha1.StatefulSet, ssc *StatefulSe
if err != nil {
return err
}
set = obj.(*appsv1alpha1.StatefulSet)
set = obj.(*appsv1beta1.StatefulSet)
}
return assertMonotonicInvariants(set, spc)
}
func scaleDownStatefulSetController(set *appsv1alpha1.StatefulSet, ssc *StatefulSetController, spc *fakeStatefulPodControl) error {
func scaleDownStatefulSetController(set *appsv1beta1.StatefulSet, ssc *StatefulSetController, spc *fakeStatefulPodControl) error {
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
if err != nil {
return err
@ -749,7 +749,7 @@ func scaleDownStatefulSetController(set *appsv1alpha1.StatefulSet, ssc *Stateful
if err != nil {
return err
}
set = obj.(*appsv1alpha1.StatefulSet)
set = obj.(*appsv1beta1.StatefulSet)
}
return assertMonotonicInvariants(set, spc)
}
@ -821,8 +821,8 @@ func NewStatefulSetController(
cache.ResourceEventHandlerFuncs{
AddFunc: ssc.enqueueStatefulSet,
UpdateFunc: func(old, cur interface{}) {
oldPS := old.(*appsv1alpha1.StatefulSet)
curPS := cur.(*appsv1alpha1.StatefulSet)
oldPS := old.(*appsv1beta1.StatefulSet)
curPS := cur.(*appsv1beta1.StatefulSet)
if oldPS.Status.Replicas != curPS.Status.Replicas {
klog.V(4).Infof("Observed updated replica count for StatefulSet: %v, %d->%d", curPS.Name, oldPS.Status.Replicas, curPS.Status.Replicas)
}
@ -1018,7 +1018,7 @@ func (ssc *StatefulSetController) deletePod(obj interface{}) {
// resolveControllerRef returns the controller referenced by a ControllerRef,
// or nil if the ControllerRef could not be resolved to a matching controller
// of the correct Kind.
func (ssc *StatefulSetController) resolveControllerRef(namespace string, controllerRef *metav1.OwnerReference) *appsv1alpha1.StatefulSet {
func (ssc *StatefulSetController) resolveControllerRef(namespace string, controllerRef *metav1.OwnerReference) *appsv1beta1.StatefulSet {
// We can't look up by UID, so look up by Name and then verify UID.
// Don't even try to look up by Name if it's the wrong Kind.
if controllerRef.Kind != controllerKind.Kind {
@ -1038,7 +1038,7 @@ func (ssc *StatefulSetController) resolveControllerRef(namespace string, control
// getStatefulSetsForPod returns a list of StatefulSets that potentially match
// a given pod.
func (ssc *StatefulSetController) getStatefulSetsForPod(pod *v1.Pod) []*appsv1alpha1.StatefulSet {
func (ssc *StatefulSetController) getStatefulSetsForPod(pod *v1.Pod) []*appsv1beta1.StatefulSet {
sets, err := getPodStatefulSets(ssc.setLister, pod)
if err != nil {
return nil
@ -1055,9 +1055,9 @@ func (ssc *StatefulSetController) getStatefulSetsForPod(pod *v1.Pod) []*appsv1al
return sets
}
func getPodStatefulSets(s kruiseappslisters.StatefulSetLister, pod *v1.Pod) ([]*appsv1alpha1.StatefulSet, error) {
func getPodStatefulSets(s kruiseappslisters.StatefulSetLister, pod *v1.Pod) ([]*appsv1beta1.StatefulSet, error) {
var selector labels.Selector
var ps *appsv1alpha1.StatefulSet
var ps *appsv1beta1.StatefulSet
if len(pod.Labels) == 0 {
return nil, fmt.Errorf("no StatefulSets found for pod %v because it has no labels", pod.Name)
@ -1068,7 +1068,7 @@ func getPodStatefulSets(s kruiseappslisters.StatefulSetLister, pod *v1.Pod) ([]*
return nil, err
}
var psList []*appsv1alpha1.StatefulSet
var psList []*appsv1beta1.StatefulSet
for i := range list {
ps = list[i]
if ps.Namespace != pod.Namespace {

View File

@ -25,7 +25,7 @@ import (
"time"
"github.com/appscode/jsonpatch"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appspub "github.com/openkruise/kruise/apis/apps/pub"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -118,7 +118,7 @@ func (c *realControl) Refresh(pod *v1.Pod, opts *UpdateOptions) RefreshResult {
var delayDuration time.Duration
var err error
if pod.Annotations[appsv1alpha1.InPlaceUpdateGraceKey] != "" {
if pod.Annotations[appspub.InPlaceUpdateGraceKey] != "" {
if delayDuration, err = c.finishGracePeriod(pod, opts); err != nil {
return RefreshResult{RefreshErr: err}
}
@ -149,7 +149,7 @@ func (c *realControl) refreshCondition(pod *v1.Pod, opts *UpdateOptions) error {
}
newCondition := v1.PodCondition{
Type: appsv1alpha1.InPlaceUpdateReady,
Type: appspub.InPlaceUpdateReady,
Status: v1.ConditionTrue,
LastTransitionTime: c.now(),
}
@ -178,7 +178,7 @@ func (c *realControl) finishGracePeriod(pod *v1.Pod, opts *UpdateOptions) (time.
}
spec := UpdateSpec{}
updateSpecJSON, ok := clone.Annotations[appsv1alpha1.InPlaceUpdateGraceKey]
updateSpecJSON, ok := clone.Annotations[appspub.InPlaceUpdateGraceKey]
if !ok {
return nil
}
@ -187,10 +187,10 @@ func (c *realControl) finishGracePeriod(pod *v1.Pod, opts *UpdateOptions) (time.
}
graceDuration := time.Second * time.Duration(spec.GraceSeconds)
updateState := appsv1alpha1.InPlaceUpdateState{}
updateStateJSON, ok := clone.Annotations[appsv1alpha1.InPlaceUpdateStateKey]
updateState := appspub.InPlaceUpdateState{}
updateStateJSON, ok := clone.Annotations[appspub.InPlaceUpdateStateKey]
if !ok {
return fmt.Errorf("pod has %s but %s not found", appsv1alpha1.InPlaceUpdateGraceKey, appsv1alpha1.InPlaceUpdateStateKey)
return fmt.Errorf("pod has %s but %s not found", appspub.InPlaceUpdateGraceKey, appspub.InPlaceUpdateStateKey)
}
if err := json.Unmarshal([]byte(updateStateJSON), &updateState); err != nil {
return nil
@ -198,7 +198,7 @@ func (c *realControl) finishGracePeriod(pod *v1.Pod, opts *UpdateOptions) (time.
if clone.Labels[c.revisionKey] != spec.Revision {
// If revision-hash has changed, just drop this GracePeriodSpec and go through the normal update process again.
delete(clone.Annotations, appsv1alpha1.InPlaceUpdateGraceKey)
delete(clone.Annotations, appspub.InPlaceUpdateGraceKey)
} else {
if span := time.Since(updateState.UpdateTimestamp.Time); span < graceDuration {
delayDuration = roundupSeconds(graceDuration - span)
@ -208,7 +208,7 @@ func (c *realControl) finishGracePeriod(pod *v1.Pod, opts *UpdateOptions) (time.
if clone, err = patchUpdateSpecToPod(clone, &spec, opts); err != nil {
return err
}
delete(clone.Annotations, appsv1alpha1.InPlaceUpdateGraceKey)
delete(clone.Annotations, appspub.InPlaceUpdateGraceKey)
}
return c.adp.updatePod(clone)
@ -236,7 +236,7 @@ func (c *realControl) Update(pod *v1.Pod, oldRevision, newRevision *apps.Control
// 2. update condition for pod with readiness-gate
if containsReadinessGate(pod) {
newCondition := v1.PodCondition{
Type: appsv1alpha1.InPlaceUpdateReady,
Type: appspub.InPlaceUpdateReady,
LastTransitionTime: c.now(),
Status: v1.ConditionFalse,
Reason: "StartInPlaceUpdate",
@ -279,29 +279,29 @@ func (c *realControl) updatePodInPlace(pod *v1.Pod, spec *UpdateSpec, opts *Upda
}
// record old containerStatuses
inPlaceUpdateState := appsv1alpha1.InPlaceUpdateState{
inPlaceUpdateState := appspub.InPlaceUpdateState{
Revision: spec.Revision,
UpdateTimestamp: c.now(),
LastContainerStatuses: make(map[string]appsv1alpha1.InPlaceUpdateContainerStatus, len(spec.ContainerImages)),
LastContainerStatuses: make(map[string]appspub.InPlaceUpdateContainerStatus, len(spec.ContainerImages)),
}
for _, c := range clone.Status.ContainerStatuses {
if _, ok := spec.ContainerImages[c.Name]; ok {
inPlaceUpdateState.LastContainerStatuses[c.Name] = appsv1alpha1.InPlaceUpdateContainerStatus{
inPlaceUpdateState.LastContainerStatuses[c.Name] = appspub.InPlaceUpdateContainerStatus{
ImageID: c.ImageID,
}
}
}
inPlaceUpdateStateJSON, _ := json.Marshal(inPlaceUpdateState)
clone.Annotations[appsv1alpha1.InPlaceUpdateStateKey] = string(inPlaceUpdateStateJSON)
clone.Annotations[appspub.InPlaceUpdateStateKey] = string(inPlaceUpdateStateJSON)
if spec.GraceSeconds <= 0 {
if clone, err = patchUpdateSpecToPod(clone, spec, opts); err != nil {
return err
}
delete(clone.Annotations, appsv1alpha1.InPlaceUpdateGraceKey)
delete(clone.Annotations, appspub.InPlaceUpdateGraceKey)
} else {
inPlaceUpdateSpecJSON, _ := json.Marshal(spec)
clone.Annotations[appsv1alpha1.InPlaceUpdateGraceKey] = string(inPlaceUpdateSpecJSON)
clone.Annotations[appspub.InPlaceUpdateGraceKey] = string(inPlaceUpdateSpecJSON)
}
return c.adp.updatePod(clone)
@ -416,8 +416,8 @@ func GetTemplateFromRevision(revision *apps.ControllerRevision) (*v1.PodTemplate
// If the imageID in containerStatuses has not been changed, we assume that kubelet has not updated
// containers in Pod.
func CheckInPlaceUpdateCompleted(pod *v1.Pod) error {
inPlaceUpdateState := appsv1alpha1.InPlaceUpdateState{}
if stateStr, ok := pod.Annotations[appsv1alpha1.InPlaceUpdateStateKey]; !ok {
inPlaceUpdateState := appspub.InPlaceUpdateState{}
if stateStr, ok := pod.Annotations[appspub.InPlaceUpdateStateKey]; !ok {
return nil
} else if err := json.Unmarshal([]byte(stateStr), &inPlaceUpdateState); err != nil {
return err
@ -438,7 +438,7 @@ func CheckInPlaceUpdateCompleted(pod *v1.Pod) error {
}
}
_, isInGraceState := pod.Annotations[appsv1alpha1.InPlaceUpdateGraceKey]
_, isInGraceState := pod.Annotations[appspub.InPlaceUpdateGraceKey]
for _, cs := range pod.Status.ContainerStatuses {
if oldStatus, ok := inPlaceUpdateState.LastContainerStatuses[cs.Name]; ok {
// TODO: we assume that users should not update workload template with new image which actually has the same imageID as the old image
@ -461,16 +461,16 @@ func CheckInPlaceUpdateCompleted(pod *v1.Pod) error {
// InjectReadinessGate injects InPlaceUpdateReady into pod.spec.readinessGates
func InjectReadinessGate(pod *v1.Pod) {
for _, r := range pod.Spec.ReadinessGates {
if r.ConditionType == appsv1alpha1.InPlaceUpdateReady {
if r.ConditionType == appspub.InPlaceUpdateReady {
return
}
}
pod.Spec.ReadinessGates = append(pod.Spec.ReadinessGates, v1.PodReadinessGate{ConditionType: appsv1alpha1.InPlaceUpdateReady})
pod.Spec.ReadinessGates = append(pod.Spec.ReadinessGates, v1.PodReadinessGate{ConditionType: appspub.InPlaceUpdateReady})
}
func containsReadinessGate(pod *v1.Pod) bool {
for _, r := range pod.Spec.ReadinessGates {
if r.ConditionType == appsv1alpha1.InPlaceUpdateReady {
if r.ConditionType == appspub.InPlaceUpdateReady {
return true
}
}
@ -479,7 +479,7 @@ func containsReadinessGate(pod *v1.Pod) bool {
// GetCondition returns the InPlaceUpdateReady condition in Pod.
func GetCondition(pod *v1.Pod) *v1.PodCondition {
return getCondition(pod, appsv1alpha1.InPlaceUpdateReady)
return getCondition(pod, appspub.InPlaceUpdateReady)
}
func getCondition(pod *v1.Pod, cType v1.PodConditionType) *v1.PodCondition {

View File

@ -23,7 +23,7 @@ import (
"testing"
"time"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appspub "github.com/openkruise/kruise/apis/apps/pub"
"github.com/openkruise/kruise/pkg/util"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
@ -143,7 +143,7 @@ func TestCheckInPlaceUpdateCompleted(t *testing.T) {
apps.StatefulSetRevisionLabel: "new-revision",
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: `{"revision":"new-revision","lastContainerStatuses":{"c1":{"imageID":"img01"}}}`,
appspub.InPlaceUpdateStateKey: `{"revision":"new-revision","lastContainerStatuses":{"c1":{"imageID":"img01"}}}`,
},
},
Status: v1.PodStatus{
@ -164,7 +164,7 @@ func TestCheckInPlaceUpdateCompleted(t *testing.T) {
apps.StatefulSetRevisionLabel: "new-revision",
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: `{"revision":"old-revision","lastContainerStatuses":{"c1":{"imageID":"img01"}}}`,
appspub.InPlaceUpdateStateKey: `{"revision":"old-revision","lastContainerStatuses":{"c1":{"imageID":"img01"}}}`,
},
},
Status: v1.PodStatus{
@ -183,7 +183,7 @@ func TestCheckInPlaceUpdateCompleted(t *testing.T) {
apps.StatefulSetRevisionLabel: "new-revision",
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: `{"revision":"new-revision","lastContainerStatuses":{"c1":{"imageID":"img01"}}}`,
appspub.InPlaceUpdateStateKey: `{"revision":"new-revision","lastContainerStatuses":{"c1":{"imageID":"img01"}}}`,
},
},
Status: v1.PodStatus{
@ -203,7 +203,7 @@ func TestCheckInPlaceUpdateCompleted(t *testing.T) {
apps.StatefulSetRevisionLabel: "new-revision",
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: `{"revision":"new-revision","lastContainerStatuses":{"c1":{"imageID":"img01"}}}`,
appspub.InPlaceUpdateStateKey: `{"revision":"new-revision","lastContainerStatuses":{"c1":{"imageID":"img01"}}}`,
},
},
Status: v1.PodStatus{},
@ -244,11 +244,11 @@ func TestRefresh(t *testing.T) {
apps.StatefulSetRevisionLabel: "new-revision",
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: `{"revision":"new-revision","lastContainerStatuses":{"c1":{"imageID":"img01"}}}`,
appspub.InPlaceUpdateStateKey: `{"revision":"new-revision","lastContainerStatuses":{"c1":{"imageID":"img01"}}}`,
},
},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
},
},
expectedPod: &v1.Pod{
@ -257,11 +257,11 @@ func TestRefresh(t *testing.T) {
apps.StatefulSetRevisionLabel: "new-revision",
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: `{"revision":"new-revision","lastContainerStatuses":{"c1":{"imageID":"img01"}}}`,
appspub.InPlaceUpdateStateKey: `{"revision":"new-revision","lastContainerStatuses":{"c1":{"imageID":"img01"}}}`,
},
},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
},
},
},
@ -269,16 +269,16 @@ func TestRefresh(t *testing.T) {
name: "no existing condition",
pod: &v1.Pod{
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
},
},
expectedPod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{ResourceVersion: "1"},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
},
Status: v1.PodStatus{
Conditions: []v1.PodCondition{{Type: appsv1alpha1.InPlaceUpdateReady, Status: v1.ConditionTrue, LastTransitionTime: aHourAgo}},
Conditions: []v1.PodCondition{{Type: appspub.InPlaceUpdateReady, Status: v1.ConditionTrue, LastTransitionTime: aHourAgo}},
},
},
},
@ -286,7 +286,7 @@ func TestRefresh(t *testing.T) {
name: "existing condition status is False",
pod: &v1.Pod{
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
},
Status: v1.PodStatus{
Conditions: []v1.PodCondition{
@ -295,7 +295,7 @@ func TestRefresh(t *testing.T) {
Status: v1.ConditionTrue,
},
{
Type: appsv1alpha1.InPlaceUpdateReady,
Type: appspub.InPlaceUpdateReady,
Status: v1.ConditionFalse,
},
},
@ -304,7 +304,7 @@ func TestRefresh(t *testing.T) {
expectedPod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{ResourceVersion: "1"},
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
},
Status: v1.PodStatus{
Conditions: []v1.PodCondition{
@ -313,7 +313,7 @@ func TestRefresh(t *testing.T) {
Status: v1.ConditionTrue,
},
{
Type: appsv1alpha1.InPlaceUpdateReady,
Type: appspub.InPlaceUpdateReady,
Status: v1.ConditionTrue,
LastTransitionTime: aHourAgo,
},
@ -325,7 +325,7 @@ func TestRefresh(t *testing.T) {
name: "existing condition status is True",
pod: &v1.Pod{
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
},
Status: v1.PodStatus{
Conditions: []v1.PodCondition{
@ -334,7 +334,7 @@ func TestRefresh(t *testing.T) {
Status: v1.ConditionFalse,
},
{
Type: appsv1alpha1.InPlaceUpdateReady,
Type: appspub.InPlaceUpdateReady,
Status: v1.ConditionTrue,
},
},
@ -342,7 +342,7 @@ func TestRefresh(t *testing.T) {
},
expectedPod: &v1.Pod{
Spec: v1.PodSpec{
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
},
Status: v1.PodStatus{
Conditions: []v1.PodCondition{
@ -351,7 +351,7 @@ func TestRefresh(t *testing.T) {
Status: v1.ConditionFalse,
},
{
Type: appsv1alpha1.InPlaceUpdateReady,
Type: appspub.InPlaceUpdateReady,
Status: v1.ConditionTrue,
},
},
@ -366,13 +366,13 @@ func TestRefresh(t *testing.T) {
apps.StatefulSetRevisionLabel: "new-revision",
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: util.DumpJSON(appsv1alpha1.InPlaceUpdateState{Revision: "new-revision", UpdateTimestamp: tenSecondsAgo, LastContainerStatuses: map[string]appsv1alpha1.InPlaceUpdateContainerStatus{"c1": {ImageID: "img01"}}}),
appsv1alpha1.InPlaceUpdateGraceKey: `{"revision":"new-revision","containerImages":{"main":"img-name02"},"graceSeconds":30}`,
appspub.InPlaceUpdateStateKey: util.DumpJSON(appspub.InPlaceUpdateState{Revision: "new-revision", UpdateTimestamp: tenSecondsAgo, LastContainerStatuses: map[string]appspub.InPlaceUpdateContainerStatus{"c1": {ImageID: "img01"}}}),
appspub.InPlaceUpdateGraceKey: `{"revision":"new-revision","containerImages":{"main":"img-name02"},"graceSeconds":30}`,
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{{Name: "main", Image: "img-name01"}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
},
},
expectedPod: &v1.Pod{
@ -381,13 +381,13 @@ func TestRefresh(t *testing.T) {
apps.StatefulSetRevisionLabel: "new-revision",
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: util.DumpJSON(appsv1alpha1.InPlaceUpdateState{Revision: "new-revision", UpdateTimestamp: tenSecondsAgo, LastContainerStatuses: map[string]appsv1alpha1.InPlaceUpdateContainerStatus{"c1": {ImageID: "img01"}}}),
appsv1alpha1.InPlaceUpdateGraceKey: `{"revision":"new-revision","containerImages":{"main":"img-name02"},"graceSeconds":30}`,
appspub.InPlaceUpdateStateKey: util.DumpJSON(appspub.InPlaceUpdateState{Revision: "new-revision", UpdateTimestamp: tenSecondsAgo, LastContainerStatuses: map[string]appspub.InPlaceUpdateContainerStatus{"c1": {ImageID: "img01"}}}),
appspub.InPlaceUpdateGraceKey: `{"revision":"new-revision","containerImages":{"main":"img-name02"},"graceSeconds":30}`,
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{{Name: "main", Image: "img-name01"}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
},
},
},
@ -399,13 +399,13 @@ func TestRefresh(t *testing.T) {
apps.StatefulSetRevisionLabel: "new-revision",
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: util.DumpJSON(appsv1alpha1.InPlaceUpdateState{Revision: "new-revision", UpdateTimestamp: tenSecondsAgo, LastContainerStatuses: map[string]appsv1alpha1.InPlaceUpdateContainerStatus{"c1": {ImageID: "img01"}}}),
appsv1alpha1.InPlaceUpdateGraceKey: `{"revision":"new-revision","containerImages":{"main":"img-name02"},"graceSeconds":5}`,
appspub.InPlaceUpdateStateKey: util.DumpJSON(appspub.InPlaceUpdateState{Revision: "new-revision", UpdateTimestamp: tenSecondsAgo, LastContainerStatuses: map[string]appspub.InPlaceUpdateContainerStatus{"c1": {ImageID: "img01"}}}),
appspub.InPlaceUpdateGraceKey: `{"revision":"new-revision","containerImages":{"main":"img-name02"},"graceSeconds":5}`,
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{{Name: "main", Image: "img-name01"}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
},
},
expectedPod: &v1.Pod{
@ -414,13 +414,13 @@ func TestRefresh(t *testing.T) {
apps.StatefulSetRevisionLabel: "new-revision",
},
Annotations: map[string]string{
appsv1alpha1.InPlaceUpdateStateKey: util.DumpJSON(appsv1alpha1.InPlaceUpdateState{Revision: "new-revision", UpdateTimestamp: tenSecondsAgo, LastContainerStatuses: map[string]appsv1alpha1.InPlaceUpdateContainerStatus{"c1": {ImageID: "img01"}}}),
appspub.InPlaceUpdateStateKey: util.DumpJSON(appspub.InPlaceUpdateState{Revision: "new-revision", UpdateTimestamp: tenSecondsAgo, LastContainerStatuses: map[string]appspub.InPlaceUpdateContainerStatus{"c1": {ImageID: "img01"}}}),
},
ResourceVersion: "1",
},
Spec: v1.PodSpec{
Containers: []v1.Container{{Name: "main", Image: "img-name02"}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appsv1alpha1.InPlaceUpdateReady}},
ReadinessGates: []v1.PodReadinessGate{{ConditionType: appspub.InPlaceUpdateReady}},
},
},
},

View File

@ -20,18 +20,18 @@ import (
"fmt"
"time"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appspub "github.com/openkruise/kruise/apis/apps/pub"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)
func GetPodLifecycleState(pod *v1.Pod) appsv1alpha1.LifecycleStateType {
return appsv1alpha1.LifecycleStateType(pod.Labels[appsv1alpha1.LifecycleStateKey])
func GetPodLifecycleState(pod *v1.Pod) appspub.LifecycleStateType {
return appspub.LifecycleStateType(pod.Labels[appspub.LifecycleStateKey])
}
func SetPodLifecycle(state appsv1alpha1.LifecycleStateType) func(*v1.Pod) {
func SetPodLifecycle(state appspub.LifecycleStateType) func(*v1.Pod) {
return func(pod *v1.Pod) {
if pod.Labels == nil {
pod.Labels = make(map[string]string)
@ -39,27 +39,27 @@ func SetPodLifecycle(state appsv1alpha1.LifecycleStateType) func(*v1.Pod) {
if pod.Annotations == nil {
pod.Annotations = make(map[string]string)
}
pod.Labels[appsv1alpha1.LifecycleStateKey] = string(state)
pod.Annotations[appsv1alpha1.LifecycleTimestampKey] = time.Now().Format(time.RFC3339)
pod.Labels[appspub.LifecycleStateKey] = string(state)
pod.Annotations[appspub.LifecycleTimestampKey] = time.Now().Format(time.RFC3339)
}
}
func PatchPodLifecycle(c client.Client, pod *v1.Pod, state appsv1alpha1.LifecycleStateType) (bool, error) {
func PatchPodLifecycle(c client.Client, pod *v1.Pod, state appspub.LifecycleStateType) (bool, error) {
if GetPodLifecycleState(pod) == state {
return false, nil
}
body := fmt.Sprintf(
`{"metadata":{"labels":{"%s":"%s"},"annotations":{"%s":"%s"}}}`,
appsv1alpha1.LifecycleStateKey,
appspub.LifecycleStateKey,
string(state),
appsv1alpha1.LifecycleTimestampKey,
appspub.LifecycleTimestampKey,
time.Now().Format(time.RFC3339),
)
return true, c.Patch(nil, pod, client.RawPatch(types.StrategicMergePatchType, []byte(body)))
}
func IsPodHooked(hook *appsv1alpha1.LifecycleHook, pod *v1.Pod) bool {
func IsPodHooked(hook *appspub.LifecycleHook, pod *v1.Pod) bool {
if hook == nil || pod == nil {
return false
}

View File

@ -20,17 +20,17 @@ import (
"sort"
"strconv"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appspub "github.com/openkruise/kruise/apis/apps/pub"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
)
type prioritySort struct {
strategy *appsv1alpha1.UpdatePriorityStrategy
strategy *appspub.UpdatePriorityStrategy
}
func NewPrioritySorter(s *appsv1alpha1.UpdatePriorityStrategy) Sorter {
func NewPrioritySorter(s *appspub.UpdatePriorityStrategy) Sorter {
return &prioritySort{strategy: s}
}

View File

@ -19,20 +19,20 @@ package updatesort
import (
"testing"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appspub "github.com/openkruise/kruise/apis/apps/pub"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestCompare(t *testing.T) {
cases := []struct {
strategy *appsv1alpha1.UpdatePriorityStrategy
strategy *appspub.UpdatePriorityStrategy
podI map[string]string
podJ map[string]string
expected bool
}{
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
WeightPriority: []appsv1alpha1.UpdatePriorityWeightTerm{
strategy: &appspub.UpdatePriorityStrategy{
WeightPriority: []appspub.UpdatePriorityWeightTerm{
{Weight: 20, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key": "foo"}}},
{Weight: 10, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key": "bar"}}},
},
@ -42,8 +42,8 @@ func TestCompare(t *testing.T) {
expected: true,
},
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
WeightPriority: []appsv1alpha1.UpdatePriorityWeightTerm{
strategy: &appspub.UpdatePriorityStrategy{
WeightPriority: []appspub.UpdatePriorityWeightTerm{
{Weight: 20, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key": "foo"}}},
{Weight: 10, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key": "bar"}}},
},
@ -53,8 +53,8 @@ func TestCompare(t *testing.T) {
expected: true,
},
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
WeightPriority: []appsv1alpha1.UpdatePriorityWeightTerm{
strategy: &appspub.UpdatePriorityStrategy{
WeightPriority: []appspub.UpdatePriorityWeightTerm{
{Weight: 20, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key": "foo"}}},
{Weight: 10, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key": "bar"}}},
},
@ -64,8 +64,8 @@ func TestCompare(t *testing.T) {
expected: false,
},
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
WeightPriority: []appsv1alpha1.UpdatePriorityWeightTerm{
strategy: &appspub.UpdatePriorityStrategy{
WeightPriority: []appspub.UpdatePriorityWeightTerm{
{Weight: 20, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key": "foo"}}},
{Weight: 10, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key": "bar"}}},
},
@ -75,8 +75,8 @@ func TestCompare(t *testing.T) {
expected: false,
},
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
WeightPriority: []appsv1alpha1.UpdatePriorityWeightTerm{
strategy: &appspub.UpdatePriorityStrategy{
WeightPriority: []appspub.UpdatePriorityWeightTerm{
{Weight: 20, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key": "foo"}}},
{Weight: 10, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key": "bar"}}},
},
@ -86,8 +86,8 @@ func TestCompare(t *testing.T) {
expected: false,
},
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
WeightPriority: []appsv1alpha1.UpdatePriorityWeightTerm{
strategy: &appspub.UpdatePriorityStrategy{
WeightPriority: []appspub.UpdatePriorityWeightTerm{
{Weight: 20, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key1": "foo"}}},
{Weight: 10, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key2": "bar"}}},
{Weight: 15, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key3": "baz"}}},
@ -98,8 +98,8 @@ func TestCompare(t *testing.T) {
expected: false,
},
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
WeightPriority: []appsv1alpha1.UpdatePriorityWeightTerm{
strategy: &appspub.UpdatePriorityStrategy{
WeightPriority: []appspub.UpdatePriorityWeightTerm{
{Weight: 20, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key1": "foo"}}},
{Weight: 10, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key2": "bar"}}},
{Weight: 5, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key3": "baz"}}},
@ -110,8 +110,8 @@ func TestCompare(t *testing.T) {
expected: false,
},
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
OrderPriority: []appsv1alpha1.UpdatePriorityOrderTerm{
strategy: &appspub.UpdatePriorityStrategy{
OrderPriority: []appspub.UpdatePriorityOrderTerm{
{OrderedKey: "key1"},
{OrderedKey: "key2"},
},
@ -121,8 +121,8 @@ func TestCompare(t *testing.T) {
expected: true,
},
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
OrderPriority: []appsv1alpha1.UpdatePriorityOrderTerm{
strategy: &appspub.UpdatePriorityStrategy{
OrderPriority: []appspub.UpdatePriorityOrderTerm{
{OrderedKey: "key1"},
{OrderedKey: "key2"},
},
@ -132,8 +132,8 @@ func TestCompare(t *testing.T) {
expected: true,
},
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
OrderPriority: []appsv1alpha1.UpdatePriorityOrderTerm{
strategy: &appspub.UpdatePriorityStrategy{
OrderPriority: []appspub.UpdatePriorityOrderTerm{
{OrderedKey: "key1"},
{OrderedKey: "key2"},
},
@ -143,8 +143,8 @@ func TestCompare(t *testing.T) {
expected: true,
},
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
OrderPriority: []appsv1alpha1.UpdatePriorityOrderTerm{
strategy: &appspub.UpdatePriorityStrategy{
OrderPriority: []appspub.UpdatePriorityOrderTerm{
{OrderedKey: "key1"},
{OrderedKey: "key2"},
},
@ -154,8 +154,8 @@ func TestCompare(t *testing.T) {
expected: false,
},
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
OrderPriority: []appsv1alpha1.UpdatePriorityOrderTerm{
strategy: &appspub.UpdatePriorityStrategy{
OrderPriority: []appspub.UpdatePriorityOrderTerm{
{OrderedKey: "key1"},
{OrderedKey: "key2"},
},
@ -165,8 +165,8 @@ func TestCompare(t *testing.T) {
expected: false,
},
{
strategy: &appsv1alpha1.UpdatePriorityStrategy{
OrderPriority: []appsv1alpha1.UpdatePriorityOrderTerm{
strategy: &appspub.UpdatePriorityStrategy{
OrderPriority: []appspub.UpdatePriorityOrderTerm{
{OrderedKey: "key1"},
{OrderedKey: "key2"},
},

View File

@ -5,12 +5,12 @@ import (
"strconv"
"testing"
"k8s.io/apimachinery/pkg/util/uuid"
appspub "github.com/openkruise/kruise/apis/apps/pub"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/uuid"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)
@ -151,8 +151,8 @@ func TestValidate(t *testing.T) {
Type: appsv1alpha1.InPlaceIfPossibleCloneSetUpdateStrategyType,
Partition: &val2,
MaxUnavailable: &maxUnavailable120Percent,
PriorityStrategy: &appsv1alpha1.UpdatePriorityStrategy{
WeightPriority: []appsv1alpha1.UpdatePriorityWeightTerm{
PriorityStrategy: &appspub.UpdatePriorityStrategy{
WeightPriority: []appspub.UpdatePriorityWeightTerm{
{Weight: 20, MatchSelector: metav1.LabelSelector{MatchLabels: map[string]string{"key": "foo"}}},
},
},

View File

@ -28,6 +28,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
"sigs.k8s.io/controller-runtime/pkg/webhook/conversion"
)
var (
@ -66,6 +67,9 @@ func SetupWithManager(mgr manager.Manager) error {
klog.V(3).Infof("Registered webhook handler %s", path)
}
// register conversion webhook
server.Register("/convert", &conversion.Webhook{})
// register health handler
server.Register("/healthz", &health.Handler{})
@ -75,6 +79,7 @@ func SetupWithManager(mgr manager.Manager) error {
// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=mutatingwebhookconfigurations,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=validatingwebhookconfigurations,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch;update;patch
func Initialize(mgr manager.Manager, stopCh <-chan struct{}) error {
cli := &client.DelegatingClient{
@ -83,7 +88,7 @@ func Initialize(mgr manager.Manager, stopCh <-chan struct{}) error {
StatusClient: mgr.GetClient(),
}
c, err := webhookcontroller.New(cli, HandlerMap)
c, err := webhookcontroller.New(mgr.GetConfig(), cli, HandlerMap)
if err != nil {
return err
}
@ -91,7 +96,7 @@ func Initialize(mgr manager.Manager, stopCh <-chan struct{}) error {
c.Start(stopCh)
}()
timer := time.NewTimer(time.Second * 5)
timer := time.NewTimer(time.Second * 20)
defer timer.Stop()
select {
case <-webhookcontroller.Inited():

View File

@ -19,9 +19,11 @@ package mutating
import (
"context"
"encoding/json"
"fmt"
"net/http"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
"github.com/openkruise/kruise/pkg/util"
"k8s.io/klog"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
@ -43,20 +45,44 @@ var _ admission.Handler = &StatefulSetCreateUpdateHandler{}
// Handle handles admission requests.
func (h *StatefulSetCreateUpdateHandler) Handle(ctx context.Context, req admission.Request) admission.Response {
obj := &appsv1alpha1.StatefulSet{}
obj := &appsv1beta1.StatefulSet{}
var objv1alpha1 *appsv1alpha1.StatefulSet
err := h.Decoder.Decode(req, obj)
if err != nil {
return admission.Errored(http.StatusBadRequest, err)
switch req.AdmissionRequest.Resource.Version {
case appsv1beta1.GroupVersion.Version:
if err := h.Decoder.Decode(req, obj); err != nil {
return admission.Errored(http.StatusBadRequest, err)
}
case appsv1alpha1.GroupVersion.Version:
objv1alpha1 = &appsv1alpha1.StatefulSet{}
if err := h.Decoder.Decode(req, objv1alpha1); err != nil {
return admission.Errored(http.StatusBadRequest, err)
}
if err := objv1alpha1.ConvertTo(obj); err != nil {
return admission.Errored(http.StatusBadRequest, fmt.Errorf("failed to convert v1alpha1->v1beta1: %v", err))
}
}
appsv1alpha1.SetDefaultsStatefulSet(obj)
obj.Status = appsv1alpha1.StatefulSetStatus{}
appsv1beta1.SetDefaultsStatefulSet(obj)
obj.Status = appsv1beta1.StatefulSetStatus{}
marshalled, err := json.Marshal(obj)
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)
var err error
var marshalled []byte
if objv1alpha1 != nil {
if err := objv1alpha1.ConvertFrom(obj); err != nil {
return admission.Errored(http.StatusBadRequest, fmt.Errorf("failed to convert v1beta1->v1alpha1: %v", err))
}
marshalled, err = json.Marshal(objv1alpha1)
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)
}
} else {
marshalled, err = json.Marshal(obj)
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)
}
}
resp := admission.PatchResponseFromRaw(req.AdmissionRequest.Object.Raw, marshalled)
if len(resp.Patches) > 0 {
klog.V(5).Infof("Admit StatefulSet %s/%s patches: %v", obj.Namespace, obj.Name, util.DumpJSON(resp.Patches))

View File

@ -20,11 +20,11 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)
// +kubebuilder:webhook:path=/mutate-apps-kruise-io-v1alpha1-statefulset,mutating=true,failurePolicy=fail,groups=apps.kruise.io,resources=statefulsets,verbs=create;update,versions=v1alpha1,name=mstatefulset.kb.io
// +kubebuilder:webhook:path=/mutate-apps-kruise-io-statefulset,mutating=true,failurePolicy=fail,groups=apps.kruise.io,resources=statefulsets,verbs=create;update,versions=v1alpha1;v1beta1,name=mstatefulset.kb.io
var (
// HandlerMap contains admission webhook handlers
HandlerMap = map[string]admission.Handler{
"mutate-apps-kruise-io-v1alpha1-statefulset": &StatefulSetCreateUpdateHandler{},
"mutate-apps-kruise-io-statefulset": &StatefulSetCreateUpdateHandler{},
}
)

View File

@ -22,6 +22,8 @@ import (
"net/http"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
admissionv1beta1 "k8s.io/api/admission/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)
@ -42,11 +44,21 @@ var _ admission.Handler = &StatefulSetCreateUpdateHandler{}
// Handle handles admission requests.
func (h *StatefulSetCreateUpdateHandler) Handle(ctx context.Context, req admission.Request) admission.Response {
obj := &appsv1alpha1.StatefulSet{}
obj := &appsv1beta1.StatefulSet{}
err := h.Decoder.Decode(req, obj)
if err != nil {
return admission.Errored(http.StatusBadRequest, err)
switch req.AdmissionRequest.Resource.Version {
case appsv1beta1.GroupVersion.Version:
if err := h.Decoder.Decode(req, obj); err != nil {
return admission.Errored(http.StatusBadRequest, err)
}
case appsv1alpha1.GroupVersion.Version:
objv1alpha1 := &appsv1alpha1.StatefulSet{}
if err := h.Decoder.Decode(req, objv1alpha1); err != nil {
return admission.Errored(http.StatusBadRequest, err)
}
if err := objv1alpha1.ConvertTo(obj); err != nil {
return admission.Errored(http.StatusBadRequest, fmt.Errorf("failed to convert v1alpha1->v1beta1: %v", err))
}
}
switch req.AdmissionRequest.Operation {
@ -55,9 +67,21 @@ func (h *StatefulSetCreateUpdateHandler) Handle(ctx context.Context, req admissi
return admission.Errored(http.StatusUnprocessableEntity, allErrs.ToAggregate())
}
case admissionv1beta1.Update:
oldObj := &appsv1alpha1.StatefulSet{}
if err := h.Decoder.DecodeRaw(req.AdmissionRequest.OldObject, oldObj); err != nil {
return admission.Errored(http.StatusBadRequest, err)
oldObj := &appsv1beta1.StatefulSet{}
switch req.AdmissionRequest.Resource.Version {
case appsv1beta1.GroupVersion.Version:
if err := h.Decoder.DecodeRaw(req.AdmissionRequest.OldObject, oldObj); err != nil {
return admission.Errored(http.StatusBadRequest, err)
}
case appsv1alpha1.GroupVersion.Version:
objv1alpha1 := &appsv1alpha1.StatefulSet{}
if err := h.Decoder.DecodeRaw(req.AdmissionRequest.OldObject, objv1alpha1); err != nil {
return admission.Errored(http.StatusBadRequest, err)
}
if err := objv1alpha1.ConvertTo(oldObj); err != nil {
return admission.Errored(http.StatusBadRequest, fmt.Errorf("failed to convert v1alpha1->v1beta1: %v", err))
}
}
validationErrorList := validateStatefulSet(obj)
@ -67,7 +91,7 @@ func (h *StatefulSetCreateUpdateHandler) Handle(ctx context.Context, req admissi
}
if obj.Spec.UpdateStrategy.RollingUpdate != nil &&
obj.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy == appsv1alpha1.InPlaceOnlyPodUpdateStrategyType {
obj.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy == appsv1beta1.InPlaceOnlyPodUpdateStrategyType {
if err := validateTemplateInPlaceOnly(&oldObj.Spec.Template, &obj.Spec.Template); err != nil {
return admission.Errored(http.StatusUnprocessableEntity,
fmt.Errorf("invalid template modified with InPlaceOnly strategy: %v, currently only image update is allowed for InPlaceOnly", err))

View File

@ -6,6 +6,8 @@ import (
"regexp"
"github.com/appscode/jsonpatch"
appspub "github.com/openkruise/kruise/apis/apps/pub"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
@ -18,15 +20,13 @@ import (
"k8s.io/kubernetes/pkg/apis/core"
corev1 "k8s.io/kubernetes/pkg/apis/core/v1"
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
)
var inPlaceUpdateTemplateSpecPatchRexp = regexp.MustCompile("/containers/([0-9]+)/image")
// TODO (rz): break this giant function down further and use unit testing
// ValidateStatefulSetSpec tests if required fields in the StatefulSet spec are set.
func validateStatefulSetSpec(spec *appsv1alpha1.StatefulSetSpec, fldPath *field.Path) field.ErrorList {
func validateStatefulSetSpec(spec *appsv1beta1.StatefulSetSpec, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
switch spec.PodManagementPolicy {
@ -60,7 +60,7 @@ func validateStatefulSetSpec(spec *appsv1alpha1.StatefulSetSpec, fldPath *field.
apivalidation.ValidateNonnegativeField(
int64(*spec.UpdateStrategy.RollingUpdate.MinReadySeconds),
fldPath.Child("updateStrategy").Child("rollingUpdate").Child("minReadySeconds"))...)
if *spec.UpdateStrategy.RollingUpdate.MinReadySeconds > appsv1alpha1.MaxMinReadySeconds {
if *spec.UpdateStrategy.RollingUpdate.MinReadySeconds > appsv1beta1.MaxMinReadySeconds {
allErrs = append(allErrs,
field.Invalid(fldPath.Child("updateStrategy").Child("rollingUpdate").Child("minReadySeconds"),
*spec.UpdateStrategy.RollingUpdate.MinReadySeconds,
@ -126,16 +126,16 @@ func validateStatefulSetSpec(spec *appsv1alpha1.StatefulSetSpec, fldPath *field.
return allErrs
}
func validatePodUpdatePolicy(spec *appsv1alpha1.StatefulSetSpec, fldPath *field.Path) field.ErrorList {
func validatePodUpdatePolicy(spec *appsv1beta1.StatefulSetSpec, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
switch spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy {
case "":
allErrs = append(allErrs, field.Required(fldPath.Child("updateStrategy").Child("rollingUpdate").Child("podUpdatePolicy"), ""))
case appsv1alpha1.RecreatePodUpdateStrategyType:
case appsv1alpha1.InPlaceIfPossiblePodUpdateStrategyType, appsv1alpha1.InPlaceOnlyPodUpdateStrategyType:
case appsv1beta1.RecreatePodUpdateStrategyType:
case appsv1beta1.InPlaceIfPossiblePodUpdateStrategyType, appsv1beta1.InPlaceOnlyPodUpdateStrategyType:
var containsReadinessGate bool
for _, r := range spec.Template.Spec.ReadinessGates {
if r.ConditionType == appsv1alpha1.InPlaceUpdateReady {
if r.ConditionType == appspub.InPlaceUpdateReady {
containsReadinessGate = true
break
}
@ -145,7 +145,7 @@ func validatePodUpdatePolicy(spec *appsv1alpha1.StatefulSetSpec, fldPath *field.
field.Invalid(fldPath.Child("template").Child("spec").Child("readinessGates"),
spec.Template.Spec.ReadinessGates,
fmt.Sprintf("must contains %v when podUpdatePolicy is %v",
appsv1alpha1.InPlaceUpdateReady,
appspub.InPlaceUpdateReady,
spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy)))
}
default:
@ -153,14 +153,14 @@ func validatePodUpdatePolicy(spec *appsv1alpha1.StatefulSetSpec, fldPath *field.
field.Invalid(fldPath.Child("updateStrategy").Child("rollingUpdate").Child("podUpdatePolicy"),
spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy,
fmt.Sprintf("must be '%s', %s or '%s'",
appsv1alpha1.RecreatePodUpdateStrategyType,
appsv1alpha1.InPlaceIfPossiblePodUpdateStrategyType,
appsv1alpha1.InPlaceOnlyPodUpdateStrategyType)))
appsv1beta1.RecreatePodUpdateStrategyType,
appsv1beta1.InPlaceIfPossiblePodUpdateStrategyType,
appsv1beta1.InPlaceOnlyPodUpdateStrategyType)))
}
return allErrs
}
func validateMaxUnavailableField(spec *appsv1alpha1.StatefulSetSpec, fldPath *field.Path) field.ErrorList {
func validateMaxUnavailableField(spec *appsv1beta1.StatefulSetSpec, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
if spec.UpdateStrategy.RollingUpdate.MaxUnavailable == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("updateStrategy").
@ -201,14 +201,14 @@ func validateMaxUnavailableField(spec *appsv1alpha1.StatefulSetSpec, fldPath *fi
}
// ValidateStatefulSet validates a StatefulSet.
func validateStatefulSet(statefulSet *appsv1alpha1.StatefulSet) field.ErrorList {
func validateStatefulSet(statefulSet *appsv1beta1.StatefulSet) field.ErrorList {
allErrs := apivalidation.ValidateObjectMeta(&statefulSet.ObjectMeta, true, appsvalidation.ValidateStatefulSetName, field.NewPath("metadata"))
allErrs = append(allErrs, validateStatefulSetSpec(&statefulSet.Spec, field.NewPath("spec"))...)
return allErrs
}
// ValidateStatefulSetUpdate tests if required fields in the StatefulSet are set.
func ValidateStatefulSetUpdate(statefulSet, oldStatefulSet *appsv1alpha1.StatefulSet) field.ErrorList {
func ValidateStatefulSetUpdate(statefulSet, oldStatefulSet *appsv1beta1.StatefulSet) field.ErrorList {
allErrs := apivalidation.ValidateObjectMetaUpdate(&statefulSet.ObjectMeta, &oldStatefulSet.ObjectMeta, field.NewPath("metadata"))
restoreReplicas := statefulSet.Spec.Replicas

View File

@ -21,13 +21,12 @@ import (
"strings"
"testing"
appsv1beta1 "github.com/openkruise/kruise/apis/apps/v1beta1"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
utilpointer "k8s.io/utils/pointer"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
)
func TestValidateStatefulSet(t *testing.T) {
@ -78,56 +77,56 @@ func TestValidateStatefulSet(t *testing.T) {
var minus1 int32 = -1
maxUnavailable1 := intstr.FromInt(1)
maxUnavailable120Percent := intstr.FromString("120%")
successCases := []appsv1alpha1.StatefulSet{
successCases := []appsv1beta1.StatefulSet{
{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.ParallelPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.OnDeleteStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.OnDeleteStatefulSetStrategyType},
},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{
Type: apps.RollingUpdateStatefulSetStrategyType,
RollingUpdate: func() *appsv1alpha1.RollingUpdateStatefulSetStrategy {
return &appsv1alpha1.RollingUpdateStatefulSetStrategy{
RollingUpdate: func() *appsv1beta1.RollingUpdateStatefulSetStrategy {
return &appsv1beta1.RollingUpdateStatefulSetStrategy{
Partition: &val2,
PodUpdatePolicy: appsv1alpha1.RecreatePodUpdateStrategyType,
PodUpdatePolicy: appsv1beta1.RecreatePodUpdateStrategyType,
MaxUnavailable: &maxUnavailable1,
MinReadySeconds: utilpointer.Int32Ptr(10),
}
@ -146,57 +145,57 @@ func TestValidateStatefulSet(t *testing.T) {
}
// TODO: break the failed cases out with expected error instead of just pass with any error
errorCases := map[string]appsv1alpha1.StatefulSet{
errorCases := map[string]appsv1beta1.StatefulSet{
"zero-length ID": {
ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"missing-namespace": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123"},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"empty selector": {
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Template: validPodTemplate.Template,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"selector_doesnt_match": {
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
Template: validPodTemplate.Template,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"invalid manifest": {
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"negative_replicas": {
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Replicas: &minus1,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"invalid_label": {
@ -207,11 +206,11 @@ func TestValidateStatefulSet(t *testing.T) {
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
},
},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"invalid_label 2": {
@ -222,10 +221,10 @@ func TestValidateStatefulSet(t *testing.T) {
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
},
},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Template: invalidPodTemplate.Template,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"invalid_annotation": {
@ -236,11 +235,11 @@ func TestValidateStatefulSet(t *testing.T) {
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
},
},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"invalid restart policy 1": {
@ -248,7 +247,7 @@ func TestValidateStatefulSet(t *testing.T) {
Name: "abc-123",
Namespace: metav1.NamespaceDefault,
},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: v1.PodTemplateSpec{
@ -261,7 +260,7 @@ func TestValidateStatefulSet(t *testing.T) {
Labels: validLabels,
},
},
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"invalid restart policy 2": {
@ -269,7 +268,7 @@ func TestValidateStatefulSet(t *testing.T) {
Name: "abc-123",
Namespace: metav1.NamespaceDefault,
},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: v1.PodTemplateSpec{
@ -282,93 +281,93 @@ func TestValidateStatefulSet(t *testing.T) {
Labels: validLabels,
},
},
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"invalid update strategy": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: "foo"},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: "foo"},
},
},
"empty update strategy": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: ""},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: ""},
},
},
"invalid rolling update": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.OnDeleteStatefulSetStrategyType,
RollingUpdate: func() *appsv1alpha1.RollingUpdateStatefulSetStrategy {
return &appsv1alpha1.RollingUpdateStatefulSetStrategy{Partition: &val1}
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.OnDeleteStatefulSetStrategyType,
RollingUpdate: func() *appsv1beta1.RollingUpdateStatefulSetStrategy {
return &appsv1beta1.RollingUpdateStatefulSetStrategy{Partition: &val1}
}()},
},
},
"invalid rolling update 1": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.OnDeleteStatefulSetStrategyType,
RollingUpdate: func() *appsv1alpha1.RollingUpdateStatefulSetStrategy {
return &appsv1alpha1.RollingUpdateStatefulSetStrategy{MaxUnavailable: &maxUnavailable120Percent}
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.OnDeleteStatefulSetStrategyType,
RollingUpdate: func() *appsv1beta1.RollingUpdateStatefulSetStrategy {
return &appsv1beta1.RollingUpdateStatefulSetStrategy{MaxUnavailable: &maxUnavailable120Percent}
}()},
},
},
"invalid rolling update 2": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.OnDeleteStatefulSetStrategyType,
RollingUpdate: func() *appsv1alpha1.RollingUpdateStatefulSetStrategy {
return &appsv1alpha1.RollingUpdateStatefulSetStrategy{PodUpdatePolicy: "Unknown"}
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.OnDeleteStatefulSetStrategyType,
RollingUpdate: func() *appsv1beta1.RollingUpdateStatefulSetStrategy {
return &appsv1beta1.RollingUpdateStatefulSetStrategy{PodUpdatePolicy: "Unknown"}
}()},
},
},
"invalid rolling update 3": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.OnDeleteStatefulSetStrategyType,
RollingUpdate: func() *appsv1alpha1.RollingUpdateStatefulSetStrategy {
return &appsv1alpha1.RollingUpdateStatefulSetStrategy{PodUpdatePolicy: appsv1alpha1.InPlaceIfPossiblePodUpdateStrategyType}
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.OnDeleteStatefulSetStrategyType,
RollingUpdate: func() *appsv1beta1.RollingUpdateStatefulSetStrategy {
return &appsv1beta1.RollingUpdateStatefulSetStrategy{PodUpdatePolicy: appsv1beta1.InPlaceIfPossiblePodUpdateStrategyType}
}()},
},
},
"negative partition": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType,
RollingUpdate: func() *appsv1alpha1.RollingUpdateStatefulSetStrategy {
return &appsv1alpha1.RollingUpdateStatefulSetStrategy{
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType,
RollingUpdate: func() *appsv1beta1.RollingUpdateStatefulSetStrategy {
return &appsv1beta1.RollingUpdateStatefulSetStrategy{
Partition: &minus1,
PodUpdatePolicy: appsv1alpha1.RecreatePodUpdateStrategyType,
PodUpdatePolicy: appsv1beta1.RecreatePodUpdateStrategyType,
MaxUnavailable: &maxUnavailable1,
MinReadySeconds: utilpointer.Int32Ptr(1),
}
@ -377,15 +376,15 @@ func TestValidateStatefulSet(t *testing.T) {
},
"negative minReadySeconds": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType,
RollingUpdate: &appsv1alpha1.RollingUpdateStatefulSetStrategy{
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType,
RollingUpdate: &appsv1beta1.RollingUpdateStatefulSetStrategy{
Partition: &minus1,
PodUpdatePolicy: appsv1alpha1.RecreatePodUpdateStrategyType,
PodUpdatePolicy: appsv1beta1.RecreatePodUpdateStrategyType,
MaxUnavailable: &maxUnavailable1,
MinReadySeconds: utilpointer.Int32Ptr(-1),
},
@ -394,49 +393,49 @@ func TestValidateStatefulSet(t *testing.T) {
},
"too large minReadySeconds": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: apps.OrderedReadyPodManagement,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType,
RollingUpdate: &appsv1alpha1.RollingUpdateStatefulSetStrategy{
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType,
RollingUpdate: &appsv1beta1.RollingUpdateStatefulSetStrategy{
Partition: &minus1,
PodUpdatePolicy: appsv1alpha1.RecreatePodUpdateStrategyType,
PodUpdatePolicy: appsv1beta1.RecreatePodUpdateStrategyType,
MaxUnavailable: &maxUnavailable1,
MinReadySeconds: utilpointer.Int32Ptr(appsv1alpha1.MaxMinReadySeconds + 1),
MinReadySeconds: utilpointer.Int32Ptr(appsv1beta1.MaxMinReadySeconds + 1),
},
},
},
},
"empty pod management policy": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: "",
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"invalid pod management policy": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: "foo",
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
"set active deadline seconds": {
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
Spec: appsv1alpha1.StatefulSetSpec{
Spec: appsv1beta1.StatefulSetSpec{
PodManagementPolicy: "foo",
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: invalidPodTemplate2.Template,
Replicas: &val3,
UpdateStrategy: appsv1alpha1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
UpdateStrategy: appsv1beta1.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
},
},
}
@ -478,7 +477,7 @@ func TestValidateStatefulSet(t *testing.T) {
}
}
func setTestDefault(obj *appsv1alpha1.StatefulSet) {
func setTestDefault(obj *appsv1beta1.StatefulSet) {
if obj.Spec.Replicas == nil {
obj.Spec.Replicas = new(int32)
*obj.Spec.Replicas = 0

View File

@ -20,11 +20,11 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)
// +kubebuilder:webhook:path=/validate-apps-kruise-io-v1alpha1-statefulset,mutating=false,failurePolicy=fail,groups=apps.kruise.io,resources=statefulsets,verbs=create;update,versions=v1alpha1,name=vstatefulset.kb.io
// +kubebuilder:webhook:path=/validate-apps-kruise-io-statefulset,mutating=false,failurePolicy=fail,groups=apps.kruise.io,resources=statefulsets,verbs=create;update,versions=v1alpha1;v1beta1,name=vstatefulset.kb.io
var (
// HandlerMap contains admission webhook handlers
HandlerMap = map[string]admission.Handler{
"validate-apps-kruise-io-v1alpha1-statefulset": &StatefulSetCreateUpdateHandler{},
"validate-apps-kruise-io-statefulset": &StatefulSetCreateUpdateHandler{},
}
)

View File

@ -24,10 +24,15 @@ import (
extclient "github.com/openkruise/kruise/pkg/client"
webhookutil "github.com/openkruise/kruise/pkg/webhook/util"
"github.com/openkruise/kruise/pkg/webhook/util/configuration"
"github.com/openkruise/kruise/pkg/webhook/util/crd"
"github.com/openkruise/kruise/pkg/webhook/util/generator"
"github.com/openkruise/kruise/pkg/webhook/util/writer"
"k8s.io/api/admissionregistration/v1beta1"
v1 "k8s.io/api/core/v1"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
apiextensionsinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1"
apiextensionslisters "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1"
"k8s.io/apimachinery/pkg/types"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
@ -35,8 +40,7 @@ import (
admissionregistrationinformers "k8s.io/client-go/informers/admissionregistration/v1beta1"
coreinformers "k8s.io/client-go/informers/core/v1"
clientset "k8s.io/client-go/kubernetes"
admissionregistrationlisters "k8s.io/client-go/listers/admissionregistration/v1beta1"
corelisters "k8s.io/client-go/listers/core/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
"k8s.io/klog"
@ -64,16 +68,19 @@ type Controller struct {
runtimeClient client.Client
handlers map[string]admission.Handler
informerFactory informers.SharedInformerFactory
secretLister corelisters.SecretNamespaceLister
mutatingWCLister admissionregistrationlisters.MutatingWebhookConfigurationLister
validatingWCLister admissionregistrationlisters.ValidatingWebhookConfigurationLister
synced []cache.InformerSynced
informerFactory informers.SharedInformerFactory
//secretLister corelisters.SecretNamespaceLister
//mutatingWCLister admissionregistrationlisters.MutatingWebhookConfigurationLister
//validatingWCLister admissionregistrationlisters.ValidatingWebhookConfigurationLister
crdClient apiextensionsclientset.Interface
crdInformer cache.SharedIndexInformer
crdLister apiextensionslisters.CustomResourceDefinitionLister
synced []cache.InformerSynced
queue workqueue.RateLimitingInterface
}
func New(cli client.Client, handlers map[string]admission.Handler) (*Controller, error) {
func New(cfg *rest.Config, cli client.Client, handlers map[string]admission.Handler) (*Controller, error) {
c := &Controller{
kubeClient: extclient.GetGenericClient().KubeClient,
runtimeClient: cli,
@ -85,17 +92,10 @@ func New(cli client.Client, handlers map[string]admission.Handler) (*Controller,
c.informerFactory = informers.NewSharedInformerFactory(c.kubeClient, 0)
secretInformer := coreinformers.New(c.informerFactory, namespace, nil).Secrets()
c.secretLister = secretInformer.Lister().Secrets(namespace)
admissionRegistrationInformer := admissionregistrationinformers.New(c.informerFactory, v1.NamespaceAll, nil)
c.mutatingWCLister = admissionRegistrationInformer.MutatingWebhookConfigurations().Lister()
c.validatingWCLister = admissionRegistrationInformer.ValidatingWebhookConfigurations().Lister()
c.synced = []cache.InformerSynced{
secretInformer.Informer().HasSynced,
admissionRegistrationInformer.MutatingWebhookConfigurations().Informer().HasSynced,
admissionRegistrationInformer.ValidatingWebhookConfigurations().Informer().HasSynced,
}
//c.secretLister = secretInformer.Lister().Secrets(namespace)
//c.mutatingWCLister = admissionRegistrationInformer.MutatingWebhookConfigurations().Lister()
//c.validatingWCLister = admissionRegistrationInformer.ValidatingWebhookConfigurations().Lister()
secretInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
@ -148,6 +148,33 @@ func New(cli client.Client, handlers map[string]admission.Handler) (*Controller,
},
})
c.crdClient = apiextensionsclientset.NewForConfigOrDie(cfg)
c.crdInformer = apiextensionsinformers.NewCustomResourceDefinitionInformer(c.crdClient, 0, cache.Indexers{})
c.crdInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
crd := obj.(*apiextensionsv1beta1.CustomResourceDefinition)
if crd.Spec.Group == "apps.kruise.io" {
klog.Infof("CustomResourceDefinition %s added", crd.Name)
c.queue.Add("")
}
},
UpdateFunc: func(old, cur interface{}) {
crd := cur.(*apiextensionsv1beta1.CustomResourceDefinition)
if crd.Spec.Group == "apps.kruise.io" {
klog.Infof("CustomResourceDefinition %s updated", crd.Name)
c.queue.Add("")
}
},
})
c.crdLister = apiextensionslisters.NewCustomResourceDefinitionLister(c.crdInformer.GetIndexer())
c.synced = []cache.InformerSynced{
secretInformer.Informer().HasSynced,
admissionRegistrationInformer.MutatingWebhookConfigurations().Informer().HasSynced,
admissionRegistrationInformer.ValidatingWebhookConfigurations().Informer().HasSynced,
c.crdInformer.HasSynced,
}
return c, nil
}
@ -159,6 +186,9 @@ func (c *Controller) Start(stopCh <-chan struct{}) {
defer klog.Infof("Shutting down webhook-controller")
c.informerFactory.Start(stopCh)
go func() {
c.crdInformer.Run(stopCh)
}()
if !cache.WaitForNamedCacheSync("webhook-controller", stopCh, c.synced...) {
return
}
@ -228,6 +258,10 @@ func (c *Controller) sync() error {
return fmt.Errorf("failed to ensure configuration: %v", err)
}
if err := crd.Ensure(c.crdClient, c.crdLister, certs.CACert); err != nil {
return fmt.Errorf("failed to ensure crd: %v", err)
}
onceInit.Do(func() {
close(uninit)
})

View File

@ -0,0 +1,70 @@
/*
Copyright 2020 The Kruise 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 crd
import (
"fmt"
"reflect"
webhookutil "github.com/openkruise/kruise/pkg/webhook/util"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
apiextensionslisters "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1"
"k8s.io/apimachinery/pkg/labels"
)
func Ensure(client apiextensionsclientset.Interface, lister apiextensionslisters.CustomResourceDefinitionLister, caBundle []byte) error {
crdList, err := lister.List(labels.Everything())
if err != nil {
return fmt.Errorf("failed to list crds: %v", err)
}
webhookConfig := apiextensionsv1beta1.WebhookClientConfig{
CABundle: caBundle,
}
path := "/convert"
if host := webhookutil.GetHost(); len(host) > 0 {
url := fmt.Sprintf("https://%s:%d%s", host, webhookutil.GetPort(), path)
webhookConfig.URL = &url
} else {
var port int32 = 443
webhookConfig.Service = &apiextensionsv1beta1.ServiceReference{
Namespace: webhookutil.GetNamespace(),
Name: webhookutil.GetServiceName(),
Port: &port,
Path: &path,
}
}
for _, crd := range crdList {
if crd.Spec.Group != "apps.kruise.io" {
continue
}
if crd.Spec.Conversion == nil || crd.Spec.Conversion.Strategy != apiextensionsv1beta1.WebhookConverter {
continue
}
if !reflect.DeepEqual(crd.Spec.Conversion.WebhookClientConfig, webhookConfig) {
newCRD := crd.DeepCopy()
newCRD.Spec.Conversion.WebhookClientConfig = webhookConfig.DeepCopy()
if _, err := client.ApiextensionsV1beta1().CustomResourceDefinitions().Update(newCRD); err != nil {
return fmt.Errorf("failed to update CRD %s: %v", newCRD.Name, err)
}
}
}
return nil
}

View File

@ -132,7 +132,7 @@ func (s *secretCertWriter) read() (*generator.Artifacts, error) {
return nil, notFoundError{err}
}
certs := secretToCerts(secret)
if certs != nil {
if certs != nil && certs.CACert != nil && certs.CAKey != nil {
// Store the CA for next usage.
s.CertGenerator.SetCA(certs.CAKey, certs.CACert)
}

View File

@ -15,7 +15,7 @@ cp -r ./{apis,hack,vendor} "${TMP_DIR}"/src/github.com/openkruise/kruise/
(cd "${TMP_DIR}"/src/github.com/openkruise/kruise; \
GOPATH=${TMP_DIR} GO111MODULE=off /bin/bash vendor/k8s.io/code-generator/generate-groups.sh all \
github.com/openkruise/kruise/pkg/client github.com/openkruise/kruise/apis apps:v1alpha1 -h ./hack/boilerplate.go.txt)
github.com/openkruise/kruise/pkg/client github.com/openkruise/kruise/apis "apps:v1alpha1 apps:v1beta1" -h ./hack/boilerplate.go.txt)
rm -rf ./pkg/client/{clientset,informers,listers}
mv "${TMP_DIR}"/src/github.com/openkruise/kruise/pkg/client/* ./pkg/client

View File

@ -25,6 +25,7 @@ import (
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
appspub "github.com/openkruise/kruise/apis/apps/pub"
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
kruiseclientset "github.com/openkruise/kruise/pkg/client/clientset/versioned"
"github.com/openkruise/kruise/test/e2e/framework"
@ -586,7 +587,7 @@ var _ = SIGDescribe("StatefulSet", func() {
PodUpdatePolicy: appsv1alpha1.InPlaceIfPossiblePodUpdateStrategyType,
},
}
ss.Spec.Template.Spec.ReadinessGates = append(ss.Spec.Template.Spec.ReadinessGates, v1.PodReadinessGate{ConditionType: appsv1alpha1.InPlaceUpdateReady})
ss.Spec.Template.Spec.ReadinessGates = append(ss.Spec.Template.Spec.ReadinessGates, v1.PodReadinessGate{ConditionType: appspub.InPlaceUpdateReady})
ss, err := kc.AppsV1alpha1().StatefulSets(ns).Create(ss)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
sst.WaitForRunningAndReady(*ss.Spec.Replicas, ss)

Some files were not shown because too many files have changed in this diff Show More