mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 18:28:13 +00:00 
			
		
		
		
	Promotes the StatefulSet, ControllerRevision, Deployment, and ReplicaSet kinds to the apps/v1 group version.
This commit is contained in:
		| @@ -203,7 +203,7 @@ var apiVersionPriorities = map[schema.GroupVersion]priority{ | ||||
| 	{Group: "extensions", Version: "v1beta1"}: {group: 17900, version: 1}, | ||||
| 	// to my knowledge, nothing below here collides | ||||
| 	{Group: "apps", Version: "v1beta1"}:                          {group: 17800, version: 1}, | ||||
| 	{Group: "apps", Version: "v1beta2"}:                          {group: 17800, version: 1}, | ||||
| 	{Group: "apps", Version: "v1beta2"}:                          {group: 17800, version: 9}, | ||||
| 	{Group: "apps", Version: "v1"}:                               {group: 17800, version: 15}, | ||||
| 	{Group: "authentication.k8s.io", Version: "v1"}:              {group: 17700, version: 15}, | ||||
| 	{Group: "authentication.k8s.io", Version: "v1beta1"}:         {group: 17700, version: 9}, | ||||
|   | ||||
| @@ -74,6 +74,8 @@ func TestDefaulting(t *testing.T) { | ||||
| 		{Group: "apps", Version: "v1beta1", Kind: "StatefulSetList"}:                              {}, | ||||
| 		{Group: "apps", Version: "v1beta2", Kind: "StatefulSet"}:                                  {}, | ||||
| 		{Group: "apps", Version: "v1beta2", Kind: "StatefulSetList"}:                              {}, | ||||
| 		{Group: "apps", Version: "v1", Kind: "StatefulSet"}:                                       {}, | ||||
| 		{Group: "apps", Version: "v1", Kind: "StatefulSetList"}:                                   {}, | ||||
| 		{Group: "autoscaling", Version: "v1", Kind: "HorizontalPodAutoscaler"}:                    {}, | ||||
| 		{Group: "autoscaling", Version: "v1", Kind: "HorizontalPodAutoscalerList"}:                {}, | ||||
| 		{Group: "autoscaling", Version: "v2beta1", Kind: "HorizontalPodAutoscaler"}:               {}, | ||||
| @@ -107,10 +109,14 @@ func TestDefaulting(t *testing.T) { | ||||
| 		{Group: "apps", Version: "v1beta1", Kind: "DeploymentList"}:                                                  {}, | ||||
| 		{Group: "apps", Version: "v1beta2", Kind: "Deployment"}:                                                      {}, | ||||
| 		{Group: "apps", Version: "v1beta2", Kind: "DeploymentList"}:                                                  {}, | ||||
| 		{Group: "apps", Version: "v1", Kind: "Deployment"}:                                                           {}, | ||||
| 		{Group: "apps", Version: "v1", Kind: "DeploymentList"}:                                                       {}, | ||||
| 		{Group: "extensions", Version: "v1beta1", Kind: "PodSecurityPolicy"}:                                         {}, | ||||
| 		{Group: "extensions", Version: "v1beta1", Kind: "PodSecurityPolicyList"}:                                     {}, | ||||
| 		{Group: "apps", Version: "v1beta2", Kind: "ReplicaSet"}:                                                      {}, | ||||
| 		{Group: "apps", Version: "v1beta2", Kind: "ReplicaSetList"}:                                                  {}, | ||||
| 		{Group: "apps", Version: "v1", Kind: "ReplicaSet"}:                                                           {}, | ||||
| 		{Group: "apps", Version: "v1", Kind: "ReplicaSetList"}:                                                       {}, | ||||
| 		{Group: "extensions", Version: "v1beta1", Kind: "ReplicaSet"}:                                                {}, | ||||
| 		{Group: "extensions", Version: "v1beta1", Kind: "ReplicaSetList"}:                                            {}, | ||||
| 		{Group: "extensions", Version: "v1beta1", Kind: "NetworkPolicy"}:                                             {}, | ||||
|   | ||||
| @@ -17,13 +17,18 @@ limitations under the License. | ||||
| package v1 | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
|  | ||||
| 	appsv1 "k8s.io/api/apps/v1" | ||||
| 	"k8s.io/api/core/v1" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/conversion" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/util/intstr" | ||||
| 	"k8s.io/kubernetes/pkg/api" | ||||
| 	k8s_api_v1 "k8s.io/kubernetes/pkg/api/v1" | ||||
| 	"k8s.io/kubernetes/pkg/apis/apps" | ||||
| 	"k8s.io/kubernetes/pkg/apis/extensions" | ||||
| ) | ||||
|  | ||||
| @@ -33,14 +38,33 @@ func addConversionFuncs(scheme *runtime.Scheme) error { | ||||
| 	// it, but a plain int32 is more convenient in the internal type. These | ||||
| 	// functions are the same as the autogenerated ones in every other way. | ||||
| 	err := scheme.AddConversionFuncs( | ||||
| 		Convert_v1_StatefulSetSpec_To_apps_StatefulSetSpec, | ||||
| 		Convert_apps_StatefulSetSpec_To_v1_StatefulSetSpec, | ||||
| 		Convert_v1_StatefulSetUpdateStrategy_To_apps_StatefulSetUpdateStrategy, | ||||
| 		Convert_apps_StatefulSetUpdateStrategy_To_v1_StatefulSetUpdateStrategy, | ||||
| 		Convert_extensions_RollingUpdateDaemonSet_To_v1_RollingUpdateDaemonSet, | ||||
| 		Convert_v1_RollingUpdateDaemonSet_To_extensions_RollingUpdateDaemonSet, | ||||
| 		Convert_v1_StatefulSetStatus_To_apps_StatefulSetStatus, | ||||
| 		Convert_apps_StatefulSetStatus_To_v1_StatefulSetStatus, | ||||
| 		Convert_v1_Deployment_To_extensions_Deployment, | ||||
| 		Convert_extensions_Deployment_To_v1_Deployment, | ||||
| 		Convert_extensions_DaemonSet_To_v1_DaemonSet, | ||||
| 		Convert_v1_DaemonSet_To_extensions_DaemonSet, | ||||
| 		Convert_extensions_DaemonSetSpec_To_v1_DaemonSetSpec, | ||||
| 		Convert_v1_DaemonSetSpec_To_extensions_DaemonSetSpec, | ||||
| 		Convert_extensions_DaemonSetUpdateStrategy_To_v1_DaemonSetUpdateStrategy, | ||||
| 		Convert_v1_DaemonSetUpdateStrategy_To_extensions_DaemonSetUpdateStrategy, | ||||
| 		// extensions | ||||
| 		// TODO: below conversions should be dropped in favor of auto-generated | ||||
| 		// ones, see https://github.com/kubernetes/kubernetes/issues/39865 | ||||
| 		Convert_v1_DeploymentSpec_To_extensions_DeploymentSpec, | ||||
| 		Convert_extensions_DeploymentSpec_To_v1_DeploymentSpec, | ||||
| 		Convert_v1_DeploymentStrategy_To_extensions_DeploymentStrategy, | ||||
| 		Convert_extensions_DeploymentStrategy_To_v1_DeploymentStrategy, | ||||
| 		Convert_v1_RollingUpdateDeployment_To_extensions_RollingUpdateDeployment, | ||||
| 		Convert_extensions_RollingUpdateDeployment_To_v1_RollingUpdateDeployment, | ||||
| 		Convert_extensions_ReplicaSetSpec_To_v1_ReplicaSetSpec, | ||||
| 		Convert_v1_ReplicaSetSpec_To_extensions_ReplicaSetSpec, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| @@ -48,6 +72,150 @@ func addConversionFuncs(scheme *runtime.Scheme) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_v1_DeploymentSpec_To_extensions_DeploymentSpec(in *appsv1.DeploymentSpec, out *extensions.DeploymentSpec, s conversion.Scope) error { | ||||
| 	if in.Replicas != nil { | ||||
| 		out.Replicas = *in.Replicas | ||||
| 	} | ||||
| 	out.Selector = in.Selector | ||||
| 	if err := k8s_api_v1.Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(&in.Template, &out.Template, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := Convert_v1_DeploymentStrategy_To_extensions_DeploymentStrategy(&in.Strategy, &out.Strategy, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	out.RevisionHistoryLimit = in.RevisionHistoryLimit | ||||
| 	out.MinReadySeconds = in.MinReadySeconds | ||||
| 	out.Paused = in.Paused | ||||
| 	if in.ProgressDeadlineSeconds != nil { | ||||
| 		out.ProgressDeadlineSeconds = new(int32) | ||||
| 		*out.ProgressDeadlineSeconds = *in.ProgressDeadlineSeconds | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_extensions_DeploymentSpec_To_v1_DeploymentSpec(in *extensions.DeploymentSpec, out *appsv1.DeploymentSpec, s conversion.Scope) error { | ||||
| 	out.Replicas = &in.Replicas | ||||
| 	out.Selector = in.Selector | ||||
| 	if err := k8s_api_v1.Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec(&in.Template, &out.Template, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := Convert_extensions_DeploymentStrategy_To_v1_DeploymentStrategy(&in.Strategy, &out.Strategy, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if in.RevisionHistoryLimit != nil { | ||||
| 		out.RevisionHistoryLimit = new(int32) | ||||
| 		*out.RevisionHistoryLimit = int32(*in.RevisionHistoryLimit) | ||||
| 	} | ||||
| 	out.MinReadySeconds = int32(in.MinReadySeconds) | ||||
| 	out.Paused = in.Paused | ||||
| 	if in.ProgressDeadlineSeconds != nil { | ||||
| 		out.ProgressDeadlineSeconds = new(int32) | ||||
| 		*out.ProgressDeadlineSeconds = *in.ProgressDeadlineSeconds | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_extensions_DeploymentStrategy_To_v1_DeploymentStrategy(in *extensions.DeploymentStrategy, out *appsv1.DeploymentStrategy, s conversion.Scope) error { | ||||
| 	out.Type = appsv1.DeploymentStrategyType(in.Type) | ||||
| 	if in.RollingUpdate != nil { | ||||
| 		out.RollingUpdate = new(appsv1.RollingUpdateDeployment) | ||||
| 		if err := Convert_extensions_RollingUpdateDeployment_To_v1_RollingUpdateDeployment(in.RollingUpdate, out.RollingUpdate, s); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} else { | ||||
| 		out.RollingUpdate = nil | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_v1_DeploymentStrategy_To_extensions_DeploymentStrategy(in *appsv1.DeploymentStrategy, out *extensions.DeploymentStrategy, s conversion.Scope) error { | ||||
| 	out.Type = extensions.DeploymentStrategyType(in.Type) | ||||
| 	if in.RollingUpdate != nil { | ||||
| 		out.RollingUpdate = new(extensions.RollingUpdateDeployment) | ||||
| 		if err := Convert_v1_RollingUpdateDeployment_To_extensions_RollingUpdateDeployment(in.RollingUpdate, out.RollingUpdate, s); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} else { | ||||
| 		out.RollingUpdate = nil | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_v1_RollingUpdateDeployment_To_extensions_RollingUpdateDeployment(in *appsv1.RollingUpdateDeployment, out *extensions.RollingUpdateDeployment, s conversion.Scope) error { | ||||
| 	if err := s.Convert(in.MaxUnavailable, &out.MaxUnavailable, 0); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := s.Convert(in.MaxSurge, &out.MaxSurge, 0); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_extensions_RollingUpdateDeployment_To_v1_RollingUpdateDeployment(in *extensions.RollingUpdateDeployment, out *appsv1.RollingUpdateDeployment, s conversion.Scope) error { | ||||
| 	if out.MaxUnavailable == nil { | ||||
| 		out.MaxUnavailable = &intstr.IntOrString{} | ||||
| 	} | ||||
| 	if err := s.Convert(&in.MaxUnavailable, out.MaxUnavailable, 0); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if out.MaxSurge == nil { | ||||
| 		out.MaxSurge = &intstr.IntOrString{} | ||||
| 	} | ||||
| 	if err := s.Convert(&in.MaxSurge, out.MaxSurge, 0); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_v1_Deployment_To_extensions_Deployment(in *appsv1.Deployment, out *extensions.Deployment, s conversion.Scope) error { | ||||
| 	out.ObjectMeta = in.ObjectMeta | ||||
| 	if err := Convert_v1_DeploymentSpec_To_extensions_DeploymentSpec(&in.Spec, &out.Spec, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Copy annotation to deprecated rollbackTo field for roundtrip | ||||
| 	// TODO: remove this conversion after we delete extensions/v1beta1 and apps/v1beta1 Deployment | ||||
| 	if revision, _ := in.Annotations[appsv1.DeprecatedRollbackTo]; revision != "" { | ||||
| 		if revision64, err := strconv.ParseInt(revision, 10, 64); err != nil { | ||||
| 			return fmt.Errorf("failed to parse annotation[%s]=%s as int64: %v", appsv1.DeprecatedRollbackTo, revision, err) | ||||
| 		} else { | ||||
| 			out.Spec.RollbackTo = new(extensions.RollbackConfig) | ||||
| 			out.Spec.RollbackTo.Revision = revision64 | ||||
| 		} | ||||
| 		delete(out.Annotations, appsv1.DeprecatedRollbackTo) | ||||
| 	} else { | ||||
| 		out.Spec.RollbackTo = nil | ||||
| 	} | ||||
|  | ||||
| 	if err := Convert_v1_DeploymentStatus_To_extensions_DeploymentStatus(&in.Status, &out.Status, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_extensions_Deployment_To_v1_Deployment(in *extensions.Deployment, out *appsv1.Deployment, s conversion.Scope) error { | ||||
| 	out.ObjectMeta = in.ObjectMeta | ||||
| 	if err := Convert_extensions_DeploymentSpec_To_v1_DeploymentSpec(&in.Spec, &out.Spec, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Copy deprecated rollbackTo field to annotation for roundtrip | ||||
| 	// TODO: remove this conversion after we delete extensions/v1beta1 and apps/v1beta1 Deployment | ||||
| 	if in.Spec.RollbackTo != nil { | ||||
| 		if out.Annotations == nil { | ||||
| 			out.Annotations = make(map[string]string) | ||||
| 		} | ||||
| 		out.Annotations[appsv1.DeprecatedRollbackTo] = strconv.FormatInt(in.Spec.RollbackTo.Revision, 10) | ||||
| 	} else { | ||||
| 		delete(out.Annotations, appsv1.DeprecatedRollbackTo) | ||||
| 	} | ||||
|  | ||||
| 	if err := Convert_extensions_DeploymentStatus_To_v1_DeploymentStatus(&in.Status, &out.Status, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_extensions_RollingUpdateDaemonSet_To_v1_RollingUpdateDaemonSet(in *extensions.RollingUpdateDaemonSet, out *appsv1.RollingUpdateDaemonSet, s conversion.Scope) error { | ||||
| 	if out.MaxUnavailable == nil { | ||||
| 		out.MaxUnavailable = &intstr.IntOrString{} | ||||
| @@ -156,3 +324,163 @@ func Convert_v1_DaemonSetUpdateStrategy_To_extensions_DaemonSetUpdateStrategy(in | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_extensions_ReplicaSetSpec_To_v1_ReplicaSetSpec(in *extensions.ReplicaSetSpec, out *appsv1.ReplicaSetSpec, s conversion.Scope) error { | ||||
| 	out.Replicas = new(int32) | ||||
| 	*out.Replicas = int32(in.Replicas) | ||||
| 	out.MinReadySeconds = in.MinReadySeconds | ||||
| 	out.Selector = in.Selector | ||||
| 	if err := k8s_api_v1.Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec(&in.Template, &out.Template, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_v1_ReplicaSetSpec_To_extensions_ReplicaSetSpec(in *appsv1.ReplicaSetSpec, out *extensions.ReplicaSetSpec, s conversion.Scope) error { | ||||
| 	if in.Replicas != nil { | ||||
| 		out.Replicas = *in.Replicas | ||||
| 	} | ||||
| 	out.MinReadySeconds = in.MinReadySeconds | ||||
| 	out.Selector = in.Selector | ||||
| 	if err := k8s_api_v1.Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(&in.Template, &out.Template, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_v1_StatefulSetSpec_To_apps_StatefulSetSpec(in *appsv1.StatefulSetSpec, out *apps.StatefulSetSpec, s conversion.Scope) error { | ||||
| 	if in.Replicas != nil { | ||||
| 		out.Replicas = *in.Replicas | ||||
| 	} | ||||
| 	if in.Selector != nil { | ||||
| 		in, out := &in.Selector, &out.Selector | ||||
| 		*out = new(metav1.LabelSelector) | ||||
| 		if err := s.Convert(*in, *out, 0); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} else { | ||||
| 		out.Selector = nil | ||||
| 	} | ||||
| 	if err := k8s_api_v1.Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(&in.Template, &out.Template, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if in.VolumeClaimTemplates != nil { | ||||
| 		in, out := &in.VolumeClaimTemplates, &out.VolumeClaimTemplates | ||||
| 		*out = make([]api.PersistentVolumeClaim, len(*in)) | ||||
| 		for i := range *in { | ||||
| 			if err := s.Convert(&(*in)[i], &(*out)[i], 0); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} else { | ||||
| 		out.VolumeClaimTemplates = nil | ||||
| 	} | ||||
| 	if err := Convert_v1_StatefulSetUpdateStrategy_To_apps_StatefulSetUpdateStrategy(&in.UpdateStrategy, &out.UpdateStrategy, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if in.RevisionHistoryLimit != nil { | ||||
| 		out.RevisionHistoryLimit = new(int32) | ||||
| 		*out.RevisionHistoryLimit = *in.RevisionHistoryLimit | ||||
| 	} else { | ||||
| 		out.RevisionHistoryLimit = nil | ||||
| 	} | ||||
| 	out.ServiceName = in.ServiceName | ||||
| 	out.PodManagementPolicy = apps.PodManagementPolicyType(in.PodManagementPolicy) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_apps_StatefulSetSpec_To_v1_StatefulSetSpec(in *apps.StatefulSetSpec, out *appsv1.StatefulSetSpec, s conversion.Scope) error { | ||||
| 	out.Replicas = new(int32) | ||||
| 	*out.Replicas = in.Replicas | ||||
| 	if in.Selector != nil { | ||||
| 		in, out := &in.Selector, &out.Selector | ||||
| 		*out = new(metav1.LabelSelector) | ||||
| 		if err := s.Convert(*in, *out, 0); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} else { | ||||
| 		out.Selector = nil | ||||
| 	} | ||||
| 	if err := k8s_api_v1.Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec(&in.Template, &out.Template, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if in.VolumeClaimTemplates != nil { | ||||
| 		in, out := &in.VolumeClaimTemplates, &out.VolumeClaimTemplates | ||||
| 		*out = make([]v1.PersistentVolumeClaim, len(*in)) | ||||
| 		for i := range *in { | ||||
| 			if err := s.Convert(&(*in)[i], &(*out)[i], 0); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} else { | ||||
| 		out.VolumeClaimTemplates = nil | ||||
| 	} | ||||
| 	if in.RevisionHistoryLimit != nil { | ||||
| 		out.RevisionHistoryLimit = new(int32) | ||||
| 		*out.RevisionHistoryLimit = *in.RevisionHistoryLimit | ||||
| 	} else { | ||||
| 		out.RevisionHistoryLimit = nil | ||||
| 	} | ||||
| 	out.ServiceName = in.ServiceName | ||||
| 	out.PodManagementPolicy = appsv1.PodManagementPolicyType(in.PodManagementPolicy) | ||||
| 	if err := Convert_apps_StatefulSetUpdateStrategy_To_v1_StatefulSetUpdateStrategy(&in.UpdateStrategy, &out.UpdateStrategy, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_v1_StatefulSetUpdateStrategy_To_apps_StatefulSetUpdateStrategy(in *appsv1.StatefulSetUpdateStrategy, out *apps.StatefulSetUpdateStrategy, s conversion.Scope) error { | ||||
| 	out.Type = apps.StatefulSetUpdateStrategyType(in.Type) | ||||
| 	if in.RollingUpdate != nil { | ||||
| 		out.RollingUpdate = new(apps.RollingUpdateStatefulSetStrategy) | ||||
| 		out.RollingUpdate.Partition = *in.RollingUpdate.Partition | ||||
| 	} else { | ||||
| 		out.RollingUpdate = nil | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_apps_StatefulSetUpdateStrategy_To_v1_StatefulSetUpdateStrategy(in *apps.StatefulSetUpdateStrategy, out *appsv1.StatefulSetUpdateStrategy, s conversion.Scope) error { | ||||
| 	out.Type = appsv1.StatefulSetUpdateStrategyType(in.Type) | ||||
| 	if in.RollingUpdate != nil { | ||||
| 		out.RollingUpdate = new(appsv1.RollingUpdateStatefulSetStrategy) | ||||
| 		out.RollingUpdate.Partition = new(int32) | ||||
| 		*out.RollingUpdate.Partition = in.RollingUpdate.Partition | ||||
| 	} else { | ||||
| 		out.RollingUpdate = nil | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_v1_StatefulSetStatus_To_apps_StatefulSetStatus(in *appsv1.StatefulSetStatus, out *apps.StatefulSetStatus, s conversion.Scope) error { | ||||
| 	out.ObservedGeneration = new(int64) | ||||
| 	*out.ObservedGeneration = in.ObservedGeneration | ||||
| 	out.Replicas = in.Replicas | ||||
| 	out.ReadyReplicas = in.ReadyReplicas | ||||
| 	out.CurrentReplicas = in.CurrentReplicas | ||||
| 	out.UpdatedReplicas = in.UpdatedReplicas | ||||
| 	out.CurrentRevision = in.CurrentRevision | ||||
| 	out.UpdateRevision = in.UpdateRevision | ||||
| 	if in.CollisionCount != nil { | ||||
| 		out.CollisionCount = new(int32) | ||||
| 		*out.CollisionCount = *in.CollisionCount | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func Convert_apps_StatefulSetStatus_To_v1_StatefulSetStatus(in *apps.StatefulSetStatus, out *appsv1.StatefulSetStatus, s conversion.Scope) error { | ||||
| 	if in.ObservedGeneration != nil { | ||||
| 		out.ObservedGeneration = *in.ObservedGeneration | ||||
| 	} | ||||
| 	out.Replicas = in.Replicas | ||||
| 	out.ReadyReplicas = in.ReadyReplicas | ||||
| 	out.CurrentReplicas = in.CurrentReplicas | ||||
| 	out.UpdatedReplicas = in.UpdatedReplicas | ||||
| 	out.CurrentRevision = in.CurrentRevision | ||||
| 	out.UpdateRevision = in.UpdateRevision | ||||
| 	if in.CollisionCount != nil { | ||||
| 		out.CollisionCount = new(int32) | ||||
| 		*out.CollisionCount = *in.CollisionCount | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -20,13 +20,211 @@ import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	appsv1 "k8s.io/api/apps/v1" | ||||
| 	"k8s.io/api/core/v1" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/util/intstr" | ||||
| 	"k8s.io/kubernetes/pkg/api" | ||||
| 	"k8s.io/kubernetes/pkg/api/legacyscheme" | ||||
| 	"k8s.io/kubernetes/pkg/apis/apps" | ||||
| 	"k8s.io/kubernetes/pkg/apis/extensions" | ||||
|  | ||||
| 	apiequality "k8s.io/apimachinery/pkg/api/equality" | ||||
| ) | ||||
|  | ||||
| func TestV12StatefulSetSpecConversion(t *testing.T) { | ||||
| 	replicas := newInt32(2) | ||||
| 	selector := &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}} | ||||
| 	appsv1Template := v1.PodTemplateSpec{ | ||||
| 		ObjectMeta: metav1.ObjectMeta{Name: "foo"}, | ||||
| 		Spec: v1.PodSpec{ | ||||
| 			RestartPolicy:   v1.RestartPolicy("bar"), | ||||
| 			SecurityContext: new(v1.PodSecurityContext), | ||||
| 		}, | ||||
| 	} | ||||
| 	apiTemplate := api.PodTemplateSpec{ | ||||
| 		ObjectMeta: metav1.ObjectMeta{Name: "foo"}, | ||||
| 		Spec: api.PodSpec{ | ||||
| 			RestartPolicy:   api.RestartPolicy("bar"), | ||||
| 			SecurityContext: new(api.PodSecurityContext), | ||||
| 		}, | ||||
| 	} | ||||
| 	testcases := map[string]struct { | ||||
| 		stsSpec1 *apps.StatefulSetSpec | ||||
| 		stsSepc2 *appsv1.StatefulSetSpec | ||||
| 	}{ | ||||
| 		"StatefulSetSpec Conversion 1": { | ||||
| 			stsSpec1: &apps.StatefulSetSpec{ | ||||
| 				Replicas: *replicas, | ||||
| 				Template: apiTemplate, | ||||
| 			}, | ||||
| 			stsSepc2: &appsv1.StatefulSetSpec{ | ||||
| 				Replicas: replicas, | ||||
| 				Template: appsv1Template, | ||||
| 			}, | ||||
| 		}, | ||||
| 		"StatefulSetSpec Conversion 2": { | ||||
| 			stsSpec1: &apps.StatefulSetSpec{ | ||||
| 				Replicas:            *replicas, | ||||
| 				Selector:            selector, | ||||
| 				Template:            apiTemplate, | ||||
| 				ServiceName:         "foo", | ||||
| 				PodManagementPolicy: apps.PodManagementPolicyType("bar"), | ||||
| 			}, | ||||
| 			stsSepc2: &appsv1.StatefulSetSpec{ | ||||
| 				Replicas:            replicas, | ||||
| 				Selector:            selector, | ||||
| 				Template:            appsv1Template, | ||||
| 				ServiceName:         "foo", | ||||
| 				PodManagementPolicy: appsv1.PodManagementPolicyType("bar"), | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for k, tc := range testcases { | ||||
| 		// apps -> appsv1 | ||||
| 		internal1 := &appsv1.StatefulSetSpec{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.stsSpec1, internal1, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", k, "from extensions to appsv1", err) | ||||
| 		} | ||||
|  | ||||
| 		if !apiequality.Semantic.DeepEqual(internal1, tc.stsSepc2) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%#v, got \n\t%#v", k, "from extensions to appsv1", tc.stsSepc2, internal1) | ||||
| 		} | ||||
|  | ||||
| 		// appsv1 -> apps | ||||
| 		internal2 := &apps.StatefulSetSpec{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.stsSepc2, internal2, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", k, "from appsv1 to extensions", err) | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(internal2, tc.stsSpec1) { | ||||
| 			t.Errorf("%q- %q: expected\n\t%#v, got \n\t%#v", k, "from appsv1 to extensions", tc.stsSpec1, internal2) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestV1StatefulSetStatusConversion(t *testing.T) { | ||||
| 	observedGeneration := new(int64) | ||||
| 	*observedGeneration = 2 | ||||
| 	collisionCount := new(int32) | ||||
| 	*collisionCount = 1 | ||||
| 	testcases := map[string]struct { | ||||
| 		stsStatus1 *apps.StatefulSetStatus | ||||
| 		stsStatus2 *appsv1.StatefulSetStatus | ||||
| 	}{ | ||||
| 		"StatefulSetStatus Conversion 1": { | ||||
| 			stsStatus1: &apps.StatefulSetStatus{ | ||||
| 				Replicas:           int32(3), | ||||
| 				ReadyReplicas:      int32(1), | ||||
| 				CurrentReplicas:    int32(3), | ||||
| 				UpdatedReplicas:    int32(3), | ||||
| 				CurrentRevision:    "12345", | ||||
| 				UpdateRevision:     "23456", | ||||
| 				ObservedGeneration: observedGeneration, | ||||
| 			}, | ||||
| 			stsStatus2: &appsv1.StatefulSetStatus{ | ||||
| 				Replicas:           int32(3), | ||||
| 				ReadyReplicas:      int32(1), | ||||
| 				CurrentReplicas:    int32(3), | ||||
| 				UpdatedReplicas:    int32(3), | ||||
| 				CurrentRevision:    "12345", | ||||
| 				UpdateRevision:     "23456", | ||||
| 				ObservedGeneration: *observedGeneration, | ||||
| 			}, | ||||
| 		}, | ||||
| 		"StatefulSetStatus Conversion 2": { | ||||
| 			stsStatus1: &apps.StatefulSetStatus{ | ||||
| 				ObservedGeneration: observedGeneration, | ||||
| 				Replicas:           int32(3), | ||||
| 				ReadyReplicas:      int32(1), | ||||
| 				CurrentReplicas:    int32(3), | ||||
| 				UpdatedReplicas:    int32(3), | ||||
| 				CurrentRevision:    "12345", | ||||
| 				UpdateRevision:     "23456", | ||||
| 				CollisionCount:     collisionCount, | ||||
| 			}, | ||||
| 			stsStatus2: &appsv1.StatefulSetStatus{ | ||||
| 				ObservedGeneration: *observedGeneration, | ||||
| 				Replicas:           int32(3), | ||||
| 				ReadyReplicas:      int32(1), | ||||
| 				CurrentReplicas:    int32(3), | ||||
| 				UpdatedReplicas:    int32(3), | ||||
| 				CurrentRevision:    "12345", | ||||
| 				UpdateRevision:     "23456", | ||||
| 				CollisionCount:     collisionCount, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for k, tc := range testcases { | ||||
| 		// apps -> appsv1 | ||||
| 		internal1 := &appsv1.StatefulSetStatus{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.stsStatus1, internal1, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", k, "from apps to appsv1", err) | ||||
| 		} | ||||
|  | ||||
| 		if !apiequality.Semantic.DeepEqual(internal1, tc.stsStatus2) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%#v, got \n\t%#v", k, "from apps to appsv1", tc.stsStatus2, internal1) | ||||
| 		} | ||||
|  | ||||
| 		// appsv1 -> apps | ||||
| 		internal2 := &apps.StatefulSetStatus{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.stsStatus2, internal2, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", k, "from appsv1 to apps", err) | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(internal2, tc.stsStatus1) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%#v, got \n\t%#v", k, "from appsv1 to apps", tc.stsStatus1, internal2) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestV1StatefulSetUpdateStrategyConversion(t *testing.T) { | ||||
| 	partition := newInt32(2) | ||||
| 	appsv1rollingUpdate := new(appsv1.RollingUpdateStatefulSetStrategy) | ||||
| 	appsv1rollingUpdate.Partition = partition | ||||
| 	appsrollingUpdate := new(apps.RollingUpdateStatefulSetStrategy) | ||||
| 	appsrollingUpdate.Partition = *partition | ||||
| 	testcases := map[string]struct { | ||||
| 		stsUpdateStrategy1 *apps.StatefulSetUpdateStrategy | ||||
| 		stsUpdateStrategy2 *appsv1.StatefulSetUpdateStrategy | ||||
| 	}{ | ||||
| 		"StatefulSetUpdateStrategy Conversion 1": { | ||||
| 			stsUpdateStrategy1: &apps.StatefulSetUpdateStrategy{Type: apps.StatefulSetUpdateStrategyType("foo")}, | ||||
| 			stsUpdateStrategy2: &appsv1.StatefulSetUpdateStrategy{Type: appsv1.StatefulSetUpdateStrategyType("foo")}, | ||||
| 		}, | ||||
| 		"StatefulSetUpdateStrategy Conversion 2": { | ||||
| 			stsUpdateStrategy1: &apps.StatefulSetUpdateStrategy{ | ||||
| 				Type:          apps.StatefulSetUpdateStrategyType("foo"), | ||||
| 				RollingUpdate: appsrollingUpdate, | ||||
| 			}, | ||||
| 			stsUpdateStrategy2: &appsv1.StatefulSetUpdateStrategy{ | ||||
| 				Type:          appsv1.StatefulSetUpdateStrategyType("foo"), | ||||
| 				RollingUpdate: appsv1rollingUpdate, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for k, tc := range testcases { | ||||
| 		// apps -> appsv1 | ||||
| 		internal1 := &appsv1.StatefulSetUpdateStrategy{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.stsUpdateStrategy1, internal1, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", "apps -> appsv1", k, err) | ||||
| 		} | ||||
|  | ||||
| 		if !apiequality.Semantic.DeepEqual(internal1, tc.stsUpdateStrategy2) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%#v, got \n\t%#v", "apps -> appsv1", k, tc.stsUpdateStrategy2, internal1) | ||||
| 		} | ||||
|  | ||||
| 		// appsv1 -> apps | ||||
| 		internal2 := &apps.StatefulSetUpdateStrategy{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.stsUpdateStrategy2, internal2, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", "appsv1 -> apps", k, err) | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(internal2, tc.stsUpdateStrategy1) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%#v, got \n\t%#v", "appsv1 -> apps", k, tc.stsUpdateStrategy1, internal2) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestV1RollingUpdateDaemonSetConversion(t *testing.T) { | ||||
| 	intorstr := intstr.FromInt(1) | ||||
| 	testcases := map[string]struct { | ||||
| @@ -59,3 +257,344 @@ func TestV1RollingUpdateDaemonSetConversion(t *testing.T) { | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestV1DeploymentConversion(t *testing.T) { | ||||
| 	replica := newInt32(2) | ||||
| 	rollbackTo := new(extensions.RollbackConfig) | ||||
| 	rollbackTo.Revision = int64(2) | ||||
| 	testcases := map[string]struct { | ||||
| 		deployment1 *extensions.Deployment | ||||
| 		deployment2 *appsv1.Deployment | ||||
| 	}{ | ||||
| 		"Deployment Conversion 1": { | ||||
| 			deployment1: &extensions.Deployment{ | ||||
| 				Spec: extensions.DeploymentSpec{ | ||||
| 					Replicas:   *replica, | ||||
| 					RollbackTo: rollbackTo, | ||||
| 					Template: api.PodTemplateSpec{ | ||||
| 						Spec: api.PodSpec{ | ||||
| 							SecurityContext: new(api.PodSecurityContext), | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			deployment2: &appsv1.Deployment{ | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Annotations: map[string]string{appsv1.DeprecatedRollbackTo: "2"}, | ||||
| 				}, | ||||
| 				Spec: appsv1.DeploymentSpec{ | ||||
| 					Replicas: replica, | ||||
| 					Template: v1.PodTemplateSpec{ | ||||
| 						Spec: v1.PodSpec{ | ||||
| 							SecurityContext: new(v1.PodSecurityContext), | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		"Deployment Conversion 2": { | ||||
| 			deployment1: &extensions.Deployment{ | ||||
| 				Spec: extensions.DeploymentSpec{ | ||||
| 					Replicas: *replica, | ||||
| 					Template: api.PodTemplateSpec{ | ||||
| 						Spec: api.PodSpec{ | ||||
| 							SecurityContext: new(api.PodSecurityContext), | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			deployment2: &appsv1.Deployment{ | ||||
| 				Spec: appsv1.DeploymentSpec{ | ||||
| 					Replicas: replica, | ||||
| 					Template: v1.PodTemplateSpec{ | ||||
| 						Spec: v1.PodSpec{ | ||||
| 							SecurityContext: new(v1.PodSecurityContext), | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for k, tc := range testcases { | ||||
| 		// extensions -> v1beta2 | ||||
| 		internal1 := &appsv1.Deployment{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.deployment1, internal1, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", k, "from extensions to v1beta2", err) | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(internal1, tc.deployment2) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%#v, got \n\t%#v", k, "from extensions to v1beta2", tc.deployment2, internal1) | ||||
| 		} | ||||
|  | ||||
| 		// v1beta2 -> extensions | ||||
| 		internal2 := &extensions.Deployment{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.deployment2, internal2, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", k, "from v1beta2 to extensions", err) | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(internal2, tc.deployment1) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%#v, got \n\t%#v", k, "from v1beta2 to extensions", tc.deployment1, internal2) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestV1DeploymentSpecConversion(t *testing.T) { | ||||
| 	replica := newInt32(2) | ||||
| 	revisionHistoryLimit := newInt32(2) | ||||
| 	progressDeadlineSeconds := newInt32(2) | ||||
|  | ||||
| 	testcases := map[string]struct { | ||||
| 		deploymentSpec1 *extensions.DeploymentSpec | ||||
| 		deploymentSpec2 *appsv1.DeploymentSpec | ||||
| 	}{ | ||||
| 		"DeploymentSpec Conversion 1": { | ||||
| 			deploymentSpec1: &extensions.DeploymentSpec{ | ||||
| 				Replicas: *replica, | ||||
| 				Template: api.PodTemplateSpec{ | ||||
| 					Spec: api.PodSpec{ | ||||
| 						SecurityContext: new(api.PodSecurityContext), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			deploymentSpec2: &appsv1.DeploymentSpec{ | ||||
| 				Replicas: replica, | ||||
| 				Template: v1.PodTemplateSpec{ | ||||
| 					Spec: v1.PodSpec{ | ||||
| 						SecurityContext: new(v1.PodSecurityContext), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		"DeploymentSpec Conversion 2": { | ||||
| 			deploymentSpec1: &extensions.DeploymentSpec{ | ||||
| 				Replicas:             *replica, | ||||
| 				RevisionHistoryLimit: revisionHistoryLimit, | ||||
| 				MinReadySeconds:      2, | ||||
| 				Paused:               true, | ||||
| 				Template: api.PodTemplateSpec{ | ||||
| 					Spec: api.PodSpec{ | ||||
| 						SecurityContext: new(api.PodSecurityContext), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			deploymentSpec2: &appsv1.DeploymentSpec{ | ||||
| 				Replicas:             replica, | ||||
| 				RevisionHistoryLimit: revisionHistoryLimit, | ||||
| 				MinReadySeconds:      2, | ||||
| 				Paused:               true, | ||||
| 				Template: v1.PodTemplateSpec{ | ||||
| 					Spec: v1.PodSpec{ | ||||
| 						SecurityContext: new(v1.PodSecurityContext), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		"DeploymentSpec Conversion 3": { | ||||
| 			deploymentSpec1: &extensions.DeploymentSpec{ | ||||
| 				Replicas:                *replica, | ||||
| 				ProgressDeadlineSeconds: progressDeadlineSeconds, | ||||
| 				Template: api.PodTemplateSpec{ | ||||
| 					Spec: api.PodSpec{ | ||||
| 						SecurityContext: new(api.PodSecurityContext), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			deploymentSpec2: &appsv1.DeploymentSpec{ | ||||
| 				Replicas:                replica, | ||||
| 				ProgressDeadlineSeconds: progressDeadlineSeconds, | ||||
| 				Template: v1.PodTemplateSpec{ | ||||
| 					Spec: v1.PodSpec{ | ||||
| 						SecurityContext: new(v1.PodSecurityContext), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	// extensions -> appsv1 | ||||
| 	for k, tc := range testcases { | ||||
| 		internal := &appsv1.DeploymentSpec{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.deploymentSpec1, internal, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", "extensions -> appsv1", k, err) | ||||
| 		} | ||||
|  | ||||
| 		if !apiequality.Semantic.DeepEqual(internal, tc.deploymentSpec2) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%+v, got \n\t%+v", "extensions -> appsv1", k, tc.deploymentSpec2, internal) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// appsv1 -> extensions | ||||
| 	for k, tc := range testcases { | ||||
| 		internal := &extensions.DeploymentSpec{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.deploymentSpec2, internal, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", "appsv1 -> extensions", k, err) | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(internal, tc.deploymentSpec1) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%+v, got \n\t%+v", "appsv1 -> extensions", k, tc.deploymentSpec1, internal) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| func TestV1DeploymentStrategyConversion(t *testing.T) { | ||||
| 	maxUnavailable := intstr.FromInt(2) | ||||
| 	maxSurge := intstr.FromInt(2) | ||||
| 	extensionsRollingUpdate := extensions.RollingUpdateDeployment{MaxUnavailable: maxUnavailable, MaxSurge: maxSurge} | ||||
| 	appsv1RollingUpdate := appsv1.RollingUpdateDeployment{MaxUnavailable: &maxUnavailable, MaxSurge: &maxSurge} | ||||
| 	testcases := map[string]struct { | ||||
| 		deploymentStrategy1 *extensions.DeploymentStrategy | ||||
| 		deploymentStrategy2 *appsv1.DeploymentStrategy | ||||
| 	}{ | ||||
| 		"DeploymentStrategy Conversion 1": { | ||||
| 			deploymentStrategy1: &extensions.DeploymentStrategy{Type: extensions.DeploymentStrategyType("foo")}, | ||||
| 			deploymentStrategy2: &appsv1.DeploymentStrategy{Type: appsv1.DeploymentStrategyType("foo")}, | ||||
| 		}, | ||||
| 		"DeploymentStrategy Conversion 2": { | ||||
| 			deploymentStrategy1: &extensions.DeploymentStrategy{Type: extensions.DeploymentStrategyType("foo"), RollingUpdate: &extensionsRollingUpdate}, | ||||
| 			deploymentStrategy2: &appsv1.DeploymentStrategy{Type: appsv1.DeploymentStrategyType("foo"), RollingUpdate: &appsv1RollingUpdate}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for k, tc := range testcases { | ||||
| 		// extensions -> appsv1 | ||||
| 		internal1 := &appsv1.DeploymentStrategy{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.deploymentStrategy1, internal1, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", k, "extensions -> appsv1", err) | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(internal1, tc.deploymentStrategy2) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%#v, got \n\t%#v", k, "extensions -> appsv1", tc.deploymentStrategy2, internal1) | ||||
| 		} | ||||
|  | ||||
| 		// appsv1 -> extensions | ||||
| 		internal2 := &extensions.DeploymentStrategy{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.deploymentStrategy2, internal2, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", k, "appsv1 -> extensions", err) | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(internal2, tc.deploymentStrategy1) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%#v, got \n\t%#v", k, "appsv1 -> extensions", tc.deploymentStrategy1, internal2) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestV1RollingUpdateDeploymentConversion(t *testing.T) { | ||||
| 	nilIntStr := intstr.IntOrString{} | ||||
| 	maxUnavailable := intstr.FromInt(2) | ||||
| 	maxSurge := intstr.FromInt(2) | ||||
| 	testcases := map[string]struct { | ||||
| 		rollingUpdateDeployment1 *extensions.RollingUpdateDeployment | ||||
| 		rollingUpdateDeployment2 *appsv1.RollingUpdateDeployment | ||||
| 	}{ | ||||
| 		"RollingUpdateDeployment Conversion 1": { | ||||
| 			rollingUpdateDeployment1: &extensions.RollingUpdateDeployment{}, | ||||
| 			rollingUpdateDeployment2: &appsv1.RollingUpdateDeployment{MaxUnavailable: &nilIntStr, MaxSurge: &nilIntStr}, | ||||
| 		}, | ||||
| 		"RollingUpdateDeployment Conversion 2": { | ||||
| 			rollingUpdateDeployment1: &extensions.RollingUpdateDeployment{MaxUnavailable: maxUnavailable}, | ||||
| 			rollingUpdateDeployment2: &appsv1.RollingUpdateDeployment{MaxUnavailable: &maxUnavailable, MaxSurge: &nilIntStr}, | ||||
| 		}, | ||||
| 		"RollingUpdateDeployment Conversion 3": { | ||||
| 			rollingUpdateDeployment1: &extensions.RollingUpdateDeployment{MaxSurge: maxSurge}, | ||||
| 			rollingUpdateDeployment2: &appsv1.RollingUpdateDeployment{MaxSurge: &maxSurge, MaxUnavailable: &nilIntStr}, | ||||
| 		}, | ||||
| 		"RollingUpdateDeployment Conversion 4": { | ||||
| 			rollingUpdateDeployment1: &extensions.RollingUpdateDeployment{MaxUnavailable: maxUnavailable, MaxSurge: maxSurge}, | ||||
| 			rollingUpdateDeployment2: &appsv1.RollingUpdateDeployment{MaxUnavailable: &maxUnavailable, MaxSurge: &maxSurge}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for k, tc := range testcases { | ||||
| 		// extensions -> appsv1 | ||||
| 		internal1 := &appsv1.RollingUpdateDeployment{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.rollingUpdateDeployment1, internal1, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", k, "extensions -> appsv1", err) | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(internal1, tc.rollingUpdateDeployment2) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%#v, got \n\t%#v", k, "extensions -> appsv1", tc.rollingUpdateDeployment2, internal1) | ||||
| 		} | ||||
|  | ||||
| 		// appsv1 -> extensions | ||||
| 		internal2 := &extensions.RollingUpdateDeployment{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.rollingUpdateDeployment2, internal2, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", k, "appsv1 -> extensions", err) | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(internal2, tc.rollingUpdateDeployment1) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%#v, got \n\t%#v", k, "appsv1 -> extensions", tc.rollingUpdateDeployment1, internal2) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestV1ReplicaSetSpecConversion(t *testing.T) { | ||||
| 	replicas := new(int32) | ||||
| 	*replicas = 2 | ||||
| 	matchExpressions := []metav1.LabelSelectorRequirement{ | ||||
| 		{Key: "foo", Operator: metav1.LabelSelectorOpIn, Values: []string{"foo"}}, | ||||
| 	} | ||||
| 	matchLabels := map[string]string{"foo": "bar"} | ||||
| 	selector := &metav1.LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions} | ||||
|  | ||||
| 	testcases := map[string]struct { | ||||
| 		replicaset1 *extensions.ReplicaSetSpec | ||||
| 		replicaset2 *appsv1.ReplicaSetSpec | ||||
| 	}{ | ||||
| 		"ReplicaSetSpec Conversion 1": { | ||||
| 			replicaset1: &extensions.ReplicaSetSpec{ | ||||
| 				Replicas:        *replicas, | ||||
| 				MinReadySeconds: 2, | ||||
| 				Template: api.PodTemplateSpec{ | ||||
| 					Spec: api.PodSpec{ | ||||
| 						SecurityContext: new(api.PodSecurityContext), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			replicaset2: &appsv1.ReplicaSetSpec{ | ||||
| 				Replicas:        replicas, | ||||
| 				MinReadySeconds: 2, | ||||
| 				Template: v1.PodTemplateSpec{ | ||||
| 					Spec: v1.PodSpec{ | ||||
| 						SecurityContext: new(v1.PodSecurityContext), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		"ReplicaSetSpec Conversion 2": { | ||||
| 			replicaset1: &extensions.ReplicaSetSpec{ | ||||
| 				Replicas: *replicas, | ||||
| 				Selector: selector, | ||||
| 				Template: api.PodTemplateSpec{ | ||||
| 					Spec: api.PodSpec{ | ||||
| 						SecurityContext: new(api.PodSecurityContext), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			replicaset2: &appsv1.ReplicaSetSpec{ | ||||
| 				Replicas: replicas, | ||||
| 				Selector: selector, | ||||
| 				Template: v1.PodTemplateSpec{ | ||||
| 					Spec: v1.PodSpec{ | ||||
| 						SecurityContext: new(v1.PodSecurityContext), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for k, tc := range testcases { | ||||
| 		// extensions -> appsv1 | ||||
| 		internal1 := &appsv1.ReplicaSetSpec{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.replicaset1, internal1, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", k, "extensions -> appsv1", err) | ||||
| 		} | ||||
|  | ||||
| 		if !apiequality.Semantic.DeepEqual(internal1, tc.replicaset2) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%+v, got \n\t%+v", k, "extensions -> appsv1", tc.replicaset2, internal1) | ||||
| 		} | ||||
|  | ||||
| 		// appsv1 -> extensions | ||||
| 		internal2 := &extensions.ReplicaSetSpec{} | ||||
| 		if err := legacyscheme.Scheme.Convert(tc.replicaset2, internal2, nil); err != nil { | ||||
| 			t.Errorf("%q - %q: unexpected error: %v", k, "appsv1 -> extensions", err) | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(internal2, tc.replicaset1) { | ||||
| 			t.Errorf("%q - %q: expected\n\t%+v, got \n\t%+v", k, "appsv1 -> extensions", tc.replicaset1, internal2) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -26,6 +26,49 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { | ||||
| 	return RegisterDefaults(scheme) | ||||
| } | ||||
|  | ||||
| // SetDefaults_Deployment sets additional defaults compared to its counterpart | ||||
| // in extensions. These addons are: | ||||
| // - MaxUnavailable during rolling update set to 25% (1 in extensions) | ||||
| // - MaxSurge value during rolling update set to 25% (1 in extensions) | ||||
| // - RevisionHistoryLimit set to 10 (not set in extensions) | ||||
| // - ProgressDeadlineSeconds set to 600s (not set in extensions) | ||||
| func SetDefaults_Deployment(obj *appsv1.Deployment) { | ||||
| 	// Set DeploymentSpec.Replicas to 1 if it is not set. | ||||
| 	if obj.Spec.Replicas == nil { | ||||
| 		obj.Spec.Replicas = new(int32) | ||||
| 		*obj.Spec.Replicas = 1 | ||||
| 	} | ||||
| 	strategy := &obj.Spec.Strategy | ||||
| 	// Set default DeploymentStrategyType as RollingUpdate. | ||||
| 	if strategy.Type == "" { | ||||
| 		strategy.Type = appsv1.RollingUpdateDeploymentStrategyType | ||||
| 	} | ||||
| 	if strategy.Type == appsv1.RollingUpdateDeploymentStrategyType { | ||||
| 		if strategy.RollingUpdate == nil { | ||||
| 			rollingUpdate := appsv1.RollingUpdateDeployment{} | ||||
| 			strategy.RollingUpdate = &rollingUpdate | ||||
| 		} | ||||
| 		if strategy.RollingUpdate.MaxUnavailable == nil { | ||||
| 			// Set default MaxUnavailable as 25% by default. | ||||
| 			maxUnavailable := intstr.FromString("25%") | ||||
| 			strategy.RollingUpdate.MaxUnavailable = &maxUnavailable | ||||
| 		} | ||||
| 		if strategy.RollingUpdate.MaxSurge == nil { | ||||
| 			// Set default MaxSurge as 25% by default. | ||||
| 			maxSurge := intstr.FromString("25%") | ||||
| 			strategy.RollingUpdate.MaxSurge = &maxSurge | ||||
| 		} | ||||
| 	} | ||||
| 	if obj.Spec.RevisionHistoryLimit == nil { | ||||
| 		obj.Spec.RevisionHistoryLimit = new(int32) | ||||
| 		*obj.Spec.RevisionHistoryLimit = 10 | ||||
| 	} | ||||
| 	if obj.Spec.ProgressDeadlineSeconds == nil { | ||||
| 		obj.Spec.ProgressDeadlineSeconds = new(int32) | ||||
| 		*obj.Spec.ProgressDeadlineSeconds = 600 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func SetDefaults_DaemonSet(obj *appsv1.DaemonSet) { | ||||
| 	updateStrategy := &obj.Spec.UpdateStrategy | ||||
| 	if updateStrategy.Type == "" { | ||||
| @@ -47,3 +90,38 @@ func SetDefaults_DaemonSet(obj *appsv1.DaemonSet) { | ||||
| 		*obj.Spec.RevisionHistoryLimit = 10 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func SetDefaults_StatefulSet(obj *appsv1.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 = &appsv1.RollingUpdateStatefulSetStrategy{} | ||||
| 	} | ||||
|  | ||||
| 	if obj.Spec.UpdateStrategy.Type == appsv1.RollingUpdateStatefulSetStrategyType && | ||||
| 		obj.Spec.UpdateStrategy.RollingUpdate != nil && | ||||
| 		obj.Spec.UpdateStrategy.RollingUpdate.Partition == nil { | ||||
| 		obj.Spec.UpdateStrategy.RollingUpdate.Partition = new(int32) | ||||
| 		*obj.Spec.UpdateStrategy.RollingUpdate.Partition = 0 | ||||
| 	} | ||||
|  | ||||
| 	if obj.Spec.Replicas == nil { | ||||
| 		obj.Spec.Replicas = new(int32) | ||||
| 		*obj.Spec.Replicas = 1 | ||||
| 	} | ||||
| 	if obj.Spec.RevisionHistoryLimit == nil { | ||||
| 		obj.Spec.RevisionHistoryLimit = new(int32) | ||||
| 		*obj.Spec.RevisionHistoryLimit = 10 | ||||
| 	} | ||||
| } | ||||
| func SetDefaults_ReplicaSet(obj *appsv1.ReplicaSet) { | ||||
| 	if obj.Spec.Replicas == nil { | ||||
| 		obj.Spec.Replicas = new(int32) | ||||
| 		*obj.Spec.Replicas = 1 | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -23,6 +23,7 @@ import ( | ||||
| 	appsv1 "k8s.io/api/apps/v1" | ||||
| 	"k8s.io/api/core/v1" | ||||
| 	apiequality "k8s.io/apimachinery/pkg/api/equality" | ||||
| 	"k8s.io/apimachinery/pkg/api/resource" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/util/intstr" | ||||
| @@ -167,6 +168,382 @@ func TestSetDefaultDaemonSetSpec(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestSetDefaultStatefulSet(t *testing.T) { | ||||
| 	defaultLabels := map[string]string{"foo": "bar"} | ||||
| 	var defaultPartition int32 = 0 | ||||
| 	var defaultReplicas int32 = 1 | ||||
|  | ||||
| 	period := int64(v1.DefaultTerminationGracePeriodSeconds) | ||||
| 	defaultTemplate := v1.PodTemplateSpec{ | ||||
| 		Spec: v1.PodSpec{ | ||||
| 			DNSPolicy:                     v1.DNSClusterFirst, | ||||
| 			RestartPolicy:                 v1.RestartPolicyAlways, | ||||
| 			SecurityContext:               &v1.PodSecurityContext{}, | ||||
| 			TerminationGracePeriodSeconds: &period, | ||||
| 			SchedulerName:                 api.DefaultSchedulerName, | ||||
| 		}, | ||||
| 		ObjectMeta: metav1.ObjectMeta{ | ||||
| 			Labels: defaultLabels, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	tests := []struct { | ||||
| 		original *appsv1.StatefulSet | ||||
| 		expected *appsv1.StatefulSet | ||||
| 	}{ | ||||
| 		{ // labels and default update strategy | ||||
| 			original: &appsv1.StatefulSet{ | ||||
| 				Spec: appsv1.StatefulSetSpec{ | ||||
| 					Template: defaultTemplate, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: &appsv1.StatefulSet{ | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Labels: defaultLabels, | ||||
| 				}, | ||||
| 				Spec: appsv1.StatefulSetSpec{ | ||||
| 					Replicas:            &defaultReplicas, | ||||
| 					Template:            defaultTemplate, | ||||
| 					PodManagementPolicy: appsv1.OrderedReadyPodManagement, | ||||
| 					UpdateStrategy: appsv1.StatefulSetUpdateStrategy{ | ||||
| 						Type: appsv1.RollingUpdateStatefulSetStrategyType, | ||||
| 						RollingUpdate: &appsv1.RollingUpdateStatefulSetStrategy{ | ||||
| 							Partition: &defaultPartition, | ||||
| 						}, | ||||
| 					}, | ||||
| 					RevisionHistoryLimit: newInt32(10), | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ // Alternate update strategy | ||||
| 			original: &appsv1.StatefulSet{ | ||||
| 				Spec: appsv1.StatefulSetSpec{ | ||||
| 					Template: defaultTemplate, | ||||
| 					UpdateStrategy: appsv1.StatefulSetUpdateStrategy{ | ||||
| 						Type: appsv1.OnDeleteStatefulSetStrategyType, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: &appsv1.StatefulSet{ | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Labels: defaultLabels, | ||||
| 				}, | ||||
| 				Spec: appsv1.StatefulSetSpec{ | ||||
| 					Replicas:            &defaultReplicas, | ||||
| 					Template:            defaultTemplate, | ||||
| 					PodManagementPolicy: appsv1.OrderedReadyPodManagement, | ||||
| 					UpdateStrategy: appsv1.StatefulSetUpdateStrategy{ | ||||
| 						Type: appsv1.OnDeleteStatefulSetStrategyType, | ||||
| 					}, | ||||
| 					RevisionHistoryLimit: newInt32(10), | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ // Parallel pod management policy. | ||||
| 			original: &appsv1.StatefulSet{ | ||||
| 				Spec: appsv1.StatefulSetSpec{ | ||||
| 					Template:            defaultTemplate, | ||||
| 					PodManagementPolicy: appsv1.ParallelPodManagement, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: &appsv1.StatefulSet{ | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Labels: defaultLabels, | ||||
| 				}, | ||||
| 				Spec: appsv1.StatefulSetSpec{ | ||||
| 					Replicas:            &defaultReplicas, | ||||
| 					Template:            defaultTemplate, | ||||
| 					PodManagementPolicy: appsv1.ParallelPodManagement, | ||||
| 					UpdateStrategy: appsv1.StatefulSetUpdateStrategy{ | ||||
| 						Type: appsv1.RollingUpdateStatefulSetStrategyType, | ||||
| 						RollingUpdate: &appsv1.RollingUpdateStatefulSetStrategy{ | ||||
| 							Partition: &defaultPartition, | ||||
| 						}, | ||||
| 					}, | ||||
| 					RevisionHistoryLimit: newInt32(10), | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for i, test := range tests { | ||||
| 		original := test.original | ||||
| 		expected := test.expected | ||||
| 		obj2 := roundTrip(t, runtime.Object(original)) | ||||
| 		got, ok := obj2.(*appsv1.StatefulSet) | ||||
| 		if !ok { | ||||
| 			t.Errorf("(%d) unexpected object: %v", i, got) | ||||
| 			t.FailNow() | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(got.Spec, expected.Spec) { | ||||
| 			t.Errorf("(%d) got different than expected\ngot:\n\t%+v\nexpected:\n\t%+v", i, got.Spec, expected.Spec) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestSetDefaultDeployment(t *testing.T) { | ||||
| 	defaultIntOrString := intstr.FromString("25%") | ||||
| 	differentIntOrString := intstr.FromInt(5) | ||||
| 	period := int64(v1.DefaultTerminationGracePeriodSeconds) | ||||
| 	defaultTemplate := v1.PodTemplateSpec{ | ||||
| 		Spec: v1.PodSpec{ | ||||
| 			DNSPolicy:                     v1.DNSClusterFirst, | ||||
| 			RestartPolicy:                 v1.RestartPolicyAlways, | ||||
| 			SecurityContext:               &v1.PodSecurityContext{}, | ||||
| 			TerminationGracePeriodSeconds: &period, | ||||
| 			SchedulerName:                 api.DefaultSchedulerName, | ||||
| 		}, | ||||
| 	} | ||||
| 	tests := []struct { | ||||
| 		original *appsv1.Deployment | ||||
| 		expected *appsv1.Deployment | ||||
| 	}{ | ||||
| 		{ | ||||
| 			original: &appsv1.Deployment{}, | ||||
| 			expected: &appsv1.Deployment{ | ||||
| 				Spec: appsv1.DeploymentSpec{ | ||||
| 					Replicas: newInt32(1), | ||||
| 					Strategy: appsv1.DeploymentStrategy{ | ||||
| 						Type: appsv1.RollingUpdateDeploymentStrategyType, | ||||
| 						RollingUpdate: &appsv1.RollingUpdateDeployment{ | ||||
| 							MaxSurge:       &defaultIntOrString, | ||||
| 							MaxUnavailable: &defaultIntOrString, | ||||
| 						}, | ||||
| 					}, | ||||
| 					RevisionHistoryLimit:    newInt32(10), | ||||
| 					ProgressDeadlineSeconds: newInt32(600), | ||||
| 					Template:                defaultTemplate, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			original: &appsv1.Deployment{ | ||||
| 				Spec: appsv1.DeploymentSpec{ | ||||
| 					Replicas: newInt32(5), | ||||
| 					Strategy: appsv1.DeploymentStrategy{ | ||||
| 						RollingUpdate: &appsv1.RollingUpdateDeployment{ | ||||
| 							MaxSurge: &differentIntOrString, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: &appsv1.Deployment{ | ||||
| 				Spec: appsv1.DeploymentSpec{ | ||||
| 					Replicas: newInt32(5), | ||||
| 					Strategy: appsv1.DeploymentStrategy{ | ||||
| 						Type: appsv1.RollingUpdateDeploymentStrategyType, | ||||
| 						RollingUpdate: &appsv1.RollingUpdateDeployment{ | ||||
| 							MaxSurge:       &differentIntOrString, | ||||
| 							MaxUnavailable: &defaultIntOrString, | ||||
| 						}, | ||||
| 					}, | ||||
| 					RevisionHistoryLimit:    newInt32(10), | ||||
| 					ProgressDeadlineSeconds: newInt32(600), | ||||
| 					Template:                defaultTemplate, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			original: &appsv1.Deployment{ | ||||
| 				Spec: appsv1.DeploymentSpec{ | ||||
| 					Replicas: newInt32(3), | ||||
| 					Strategy: appsv1.DeploymentStrategy{ | ||||
| 						Type:          appsv1.RollingUpdateDeploymentStrategyType, | ||||
| 						RollingUpdate: nil, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: &appsv1.Deployment{ | ||||
| 				Spec: appsv1.DeploymentSpec{ | ||||
| 					Replicas: newInt32(3), | ||||
| 					Strategy: appsv1.DeploymentStrategy{ | ||||
| 						Type: appsv1.RollingUpdateDeploymentStrategyType, | ||||
| 						RollingUpdate: &appsv1.RollingUpdateDeployment{ | ||||
| 							MaxSurge:       &defaultIntOrString, | ||||
| 							MaxUnavailable: &defaultIntOrString, | ||||
| 						}, | ||||
| 					}, | ||||
| 					RevisionHistoryLimit:    newInt32(10), | ||||
| 					ProgressDeadlineSeconds: newInt32(600), | ||||
| 					Template:                defaultTemplate, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			original: &appsv1.Deployment{ | ||||
| 				Spec: appsv1.DeploymentSpec{ | ||||
| 					Replicas: newInt32(5), | ||||
| 					Strategy: appsv1.DeploymentStrategy{ | ||||
| 						Type: appsv1.RecreateDeploymentStrategyType, | ||||
| 					}, | ||||
| 					RevisionHistoryLimit: newInt32(0), | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: &appsv1.Deployment{ | ||||
| 				Spec: appsv1.DeploymentSpec{ | ||||
| 					Replicas: newInt32(5), | ||||
| 					Strategy: appsv1.DeploymentStrategy{ | ||||
| 						Type: appsv1.RecreateDeploymentStrategyType, | ||||
| 					}, | ||||
| 					RevisionHistoryLimit:    newInt32(0), | ||||
| 					ProgressDeadlineSeconds: newInt32(600), | ||||
| 					Template:                defaultTemplate, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			original: &appsv1.Deployment{ | ||||
| 				Spec: appsv1.DeploymentSpec{ | ||||
| 					Replicas: newInt32(5), | ||||
| 					Strategy: appsv1.DeploymentStrategy{ | ||||
| 						Type: appsv1.RecreateDeploymentStrategyType, | ||||
| 					}, | ||||
| 					ProgressDeadlineSeconds: newInt32(30), | ||||
| 					RevisionHistoryLimit:    newInt32(2), | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: &appsv1.Deployment{ | ||||
| 				Spec: appsv1.DeploymentSpec{ | ||||
| 					Replicas: newInt32(5), | ||||
| 					Strategy: appsv1.DeploymentStrategy{ | ||||
| 						Type: appsv1.RecreateDeploymentStrategyType, | ||||
| 					}, | ||||
| 					ProgressDeadlineSeconds: newInt32(30), | ||||
| 					RevisionHistoryLimit:    newInt32(2), | ||||
| 					Template:                defaultTemplate, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
| 		original := test.original | ||||
| 		expected := test.expected | ||||
| 		obj2 := roundTrip(t, runtime.Object(original)) | ||||
| 		got, ok := obj2.(*appsv1.Deployment) | ||||
| 		if !ok { | ||||
| 			t.Errorf("unexpected object: %v", got) | ||||
| 			t.FailNow() | ||||
| 		} | ||||
| 		if !apiequality.Semantic.DeepEqual(got.Spec, expected.Spec) { | ||||
| 			t.Errorf("object mismatch!\nexpected:\n\t%+v\ngot:\n\t%+v", got.Spec, expected.Spec) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestDefaultDeploymentAvailability(t *testing.T) { | ||||
| 	d := roundTrip(t, runtime.Object(&appsv1.Deployment{})).(*appsv1.Deployment) | ||||
|  | ||||
| 	maxUnavailable, err := intstr.GetValueFromIntOrPercent(d.Spec.Strategy.RollingUpdate.MaxUnavailable, int(*(d.Spec.Replicas)), false) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("unexpected error: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	if *(d.Spec.Replicas)-int32(maxUnavailable) <= 0 { | ||||
| 		t.Fatalf("the default value of maxUnavailable can lead to no active replicas during rolling update") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestSetDefaultReplicaSetReplicas(t *testing.T) { | ||||
| 	tests := []struct { | ||||
| 		rs             appsv1.ReplicaSet | ||||
| 		expectReplicas int32 | ||||
| 	}{ | ||||
| 		{ | ||||
| 			rs: appsv1.ReplicaSet{ | ||||
| 				Spec: appsv1.ReplicaSetSpec{ | ||||
| 					Template: v1.PodTemplateSpec{ | ||||
| 						ObjectMeta: metav1.ObjectMeta{ | ||||
| 							Labels: map[string]string{ | ||||
| 								"foo": "bar", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectReplicas: 1, | ||||
| 		}, | ||||
| 		{ | ||||
| 			rs: appsv1.ReplicaSet{ | ||||
| 				Spec: appsv1.ReplicaSetSpec{ | ||||
| 					Replicas: newInt32(0), | ||||
| 					Template: v1.PodTemplateSpec{ | ||||
| 						ObjectMeta: metav1.ObjectMeta{ | ||||
| 							Labels: map[string]string{ | ||||
| 								"foo": "bar", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectReplicas: 0, | ||||
| 		}, | ||||
| 		{ | ||||
| 			rs: appsv1.ReplicaSet{ | ||||
| 				Spec: appsv1.ReplicaSetSpec{ | ||||
| 					Replicas: newInt32(3), | ||||
| 					Template: v1.PodTemplateSpec{ | ||||
| 						ObjectMeta: metav1.ObjectMeta{ | ||||
| 							Labels: map[string]string{ | ||||
| 								"foo": "bar", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectReplicas: 3, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
| 		rs := &test.rs | ||||
| 		obj2 := roundTrip(t, runtime.Object(rs)) | ||||
| 		rs2, ok := obj2.(*appsv1.ReplicaSet) | ||||
| 		if !ok { | ||||
| 			t.Errorf("unexpected object: %v", rs2) | ||||
| 			t.FailNow() | ||||
| 		} | ||||
| 		if rs2.Spec.Replicas == nil { | ||||
| 			t.Errorf("unexpected nil Replicas") | ||||
| 		} else if test.expectReplicas != *rs2.Spec.Replicas { | ||||
| 			t.Errorf("expected: %d replicas, got: %d", test.expectReplicas, *rs2.Spec.Replicas) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestDefaultRequestIsNotSetForReplicaSet(t *testing.T) { | ||||
| 	s := v1.PodSpec{} | ||||
| 	s.Containers = []v1.Container{ | ||||
| 		{ | ||||
| 			Resources: v1.ResourceRequirements{ | ||||
| 				Limits: v1.ResourceList{ | ||||
| 					v1.ResourceCPU: resource.MustParse("100m"), | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	rs := &appsv1.ReplicaSet{ | ||||
| 		Spec: appsv1.ReplicaSetSpec{ | ||||
| 			Replicas: newInt32(3), | ||||
| 			Template: v1.PodTemplateSpec{ | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Labels: map[string]string{ | ||||
| 						"foo": "bar", | ||||
| 					}, | ||||
| 				}, | ||||
| 				Spec: s, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	output := roundTrip(t, runtime.Object(rs)) | ||||
| 	rs2 := output.(*appsv1.ReplicaSet) | ||||
| 	defaultRequest := rs2.Spec.Template.Spec.Containers[0].Resources.Requests | ||||
| 	requestValue := defaultRequest[v1.ResourceCPU] | ||||
| 	if requestValue.String() != "0" { | ||||
| 		t.Errorf("Expected 0 request value, got: %s", requestValue.String()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func roundTrip(t *testing.T, obj runtime.Object) runtime.Object { | ||||
| 	data, err := runtime.Encode(legacyscheme.Codecs.LegacyCodec(SchemeGroupVersion), obj) | ||||
| 	if err != nil { | ||||
|   | ||||
| @@ -118,11 +118,30 @@ func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.API | ||||
| 	version := appsapiv1.SchemeGroupVersion | ||||
|  | ||||
| 	storage := map[string]rest.Storage{} | ||||
| 	if apiResourceConfigSource.ResourceEnabled(version.WithResource("deployments")) { | ||||
| 		deploymentStorage := deploymentstore.NewStorage(restOptionsGetter) | ||||
| 		storage["deployments"] = deploymentStorage.Deployment | ||||
| 		storage["deployments/status"] = deploymentStorage.Status | ||||
| 	} | ||||
| 	if apiResourceConfigSource.ResourceEnabled(version.WithResource("statefulsets")) { | ||||
| 		statefulSetStorage := statefulsetstore.NewStorage(restOptionsGetter) | ||||
| 		storage["statefulsets"] = statefulSetStorage.StatefulSet | ||||
| 		storage["statefulsets/status"] = statefulSetStorage.Status | ||||
| 	} | ||||
| 	if apiResourceConfigSource.ResourceEnabled(version.WithResource("daemonsets")) { | ||||
| 		daemonSetStorage, daemonSetStatusStorage := daemonsetstore.NewREST(restOptionsGetter) | ||||
| 		storage["daemonsets"] = daemonSetStorage | ||||
| 		storage["daemonsets/status"] = daemonSetStatusStorage | ||||
| 	} | ||||
| 	if apiResourceConfigSource.ResourceEnabled(version.WithResource("replicasets")) { | ||||
| 		replicaSetStorage := replicasetstore.NewStorage(restOptionsGetter) | ||||
| 		storage["replicasets"] = replicaSetStorage.ReplicaSet | ||||
| 		storage["replicasets/status"] = replicaSetStorage.Status | ||||
| 	} | ||||
| 	if apiResourceConfigSource.ResourceEnabled(version.WithResource("controllerrevisions")) { | ||||
| 		historyStorage := controllerrevisionsstore.NewREST(restOptionsGetter) | ||||
| 		storage["controllerrevisions"] = historyStorage | ||||
| 	} | ||||
| 	return storage | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -19,6 +19,7 @@ package deployment | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	appsv1 "k8s.io/api/apps/v1" | ||||
| 	appsv1beta1 "k8s.io/api/apps/v1beta1" | ||||
| 	appsv1beta2 "k8s.io/api/apps/v1beta2" | ||||
| 	extensionsv1beta1 "k8s.io/api/extensions/v1beta1" | ||||
| @@ -117,7 +118,7 @@ func (deploymentStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old | ||||
| 			// no-op for compatibility | ||||
| 		case extensionsv1beta1.SchemeGroupVersion: | ||||
| 			// no-op for compatibility | ||||
| 		case appsv1beta2.SchemeGroupVersion: | ||||
| 		case appsv1beta2.SchemeGroupVersion, appsv1.SchemeGroupVersion: | ||||
| 			// disallow mutation of selector | ||||
| 			allErrs = append(allErrs, apivalidation.ValidateImmutableField(newDeployment.Spec.Selector, oldDeployment.Spec.Selector, field.NewPath("spec").Child("selector"))...) | ||||
| 		default: | ||||
|   | ||||
| @@ -22,6 +22,7 @@ import ( | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
|  | ||||
| 	appsv1 "k8s.io/api/apps/v1" | ||||
| 	appsv1beta2 "k8s.io/api/apps/v1beta2" | ||||
| 	extensionsv1beta1 "k8s.io/api/extensions/v1beta1" | ||||
| 	apiequality "k8s.io/apimachinery/pkg/api/equality" | ||||
| @@ -127,7 +128,7 @@ func (rsStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime | ||||
| 		switch groupVersion { | ||||
| 		case extensionsv1beta1.SchemeGroupVersion: | ||||
| 			// no-op for compatibility | ||||
| 		case appsv1beta2.SchemeGroupVersion: | ||||
| 		case appsv1beta2.SchemeGroupVersion, appsv1.SchemeGroupVersion: | ||||
| 			// disallow mutation of selector | ||||
| 			allErrs = append(allErrs, apivalidation.ValidateImmutableField(newReplicaSet.Spec.Selector, oldReplicaSet.Spec.Selector, field.NewPath("spec").Child("selector"))...) | ||||
| 		default: | ||||
|   | ||||
| @@ -44,8 +44,16 @@ var ( | ||||
| // Adds the list of known types to the given scheme. | ||||
| func addKnownTypes(scheme *runtime.Scheme) error { | ||||
| 	scheme.AddKnownTypes(SchemeGroupVersion, | ||||
| 		&Deployment{}, | ||||
| 		&DeploymentList{}, | ||||
| 		&StatefulSet{}, | ||||
| 		&StatefulSetList{}, | ||||
| 		&DaemonSet{}, | ||||
| 		&DaemonSetList{}, | ||||
| 		&ReplicaSet{}, | ||||
| 		&ReplicaSetList{}, | ||||
| 		&ControllerRevision{}, | ||||
| 		&ControllerRevisionList{}, | ||||
| 	) | ||||
| 	metav1.AddToGroupVersion(scheme, SchemeGroupVersion) | ||||
| 	return nil | ||||
|   | ||||
| @@ -19,14 +19,415 @@ package v1 | ||||
| import ( | ||||
| 	"k8s.io/api/core/v1" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	runtime "k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/util/intstr" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	ControllerRevisionHashLabelKey = "controller-revision-hash" | ||||
| 	StatefulSetRevisionLabel       = ControllerRevisionHashLabelKey | ||||
| 	DeprecatedRollbackTo           = "deprecated.deployment.rollback.to" | ||||
| 	DeprecatedTemplateGeneration   = "deprecated.daemonset.template.generation" | ||||
| ) | ||||
|  | ||||
| // +genclient | ||||
| // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||||
|  | ||||
| // StatefulSet represents a set of pods with consistent identities. | ||||
| // Identities are defined as: | ||||
| //  - Network: A single stable DNS and hostname. | ||||
| //  - Storage: As many VolumeClaims as requested. | ||||
| // The StatefulSet guarantees that a given network identity will always | ||||
| // map to the same storage identity. | ||||
| type StatefulSet struct { | ||||
| 	metav1.TypeMeta `json:",inline"` | ||||
| 	// +optional | ||||
| 	metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` | ||||
|  | ||||
| 	// Spec defines the desired identities of pods in this set. | ||||
| 	// +optional | ||||
| 	Spec StatefulSetSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` | ||||
|  | ||||
| 	// Status is the current status of Pods in this StatefulSet. This data | ||||
| 	// may be out of date by some window of time. | ||||
| 	// +optional | ||||
| 	Status StatefulSetStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` | ||||
| } | ||||
|  | ||||
| // PodManagementPolicyType defines the policy for creating pods under a stateful set. | ||||
| type PodManagementPolicyType string | ||||
|  | ||||
| const ( | ||||
| 	// OrderedReadyPodManagement will create pods in strictly increasing order on | ||||
| 	// scale up and strictly decreasing order on scale down, progressing only when | ||||
| 	// the previous pod is ready or terminated. At most one pod will be changed | ||||
| 	// at any time. | ||||
| 	OrderedReadyPodManagement PodManagementPolicyType = "OrderedReady" | ||||
| 	// ParallelPodManagement will create and delete pods as soon as the stateful set | ||||
| 	// replica count is changed, and will not wait for pods to be ready or complete | ||||
| 	// termination. | ||||
| 	ParallelPodManagement = "Parallel" | ||||
| ) | ||||
|  | ||||
| // 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 StatefulSetUpdateStrategyType `json:"type,omitempty" protobuf:"bytes,1,opt,name=type,casttype=StatefulSetStrategyType"` | ||||
| 	// RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. | ||||
| 	// +optional | ||||
| 	RollingUpdate *RollingUpdateStatefulSetStrategy `json:"rollingUpdate,omitempty" protobuf:"bytes,2,opt,name=rollingUpdate"` | ||||
| } | ||||
|  | ||||
| // StatefulSetUpdateStrategyType is a string enumeration type that enumerates | ||||
| // all possible update strategies for the StatefulSet controller. | ||||
| type StatefulSetUpdateStrategyType string | ||||
|  | ||||
| const ( | ||||
| 	// RollingUpdateStatefulSetStrategyType indicates that update will be | ||||
| 	// applied to all Pods in the StatefulSet with respect to the StatefulSet | ||||
| 	// ordering constraints. When a scale operation is performed with this | ||||
| 	// strategy, new Pods will be created from the specification version indicated | ||||
| 	// by the StatefulSet's updateRevision. | ||||
| 	RollingUpdateStatefulSetStrategyType = "RollingUpdate" | ||||
| 	// OnDeleteStatefulSetStrategyType triggers the legacy behavior. Version | ||||
| 	// tracking and ordered rolling restarts are disabled. Pods are recreated | ||||
| 	// from the StatefulSetSpec when they are manually deleted. When a scale | ||||
| 	// operation is performed with this strategy,specification version indicated | ||||
| 	// by the StatefulSet's currentRevision. | ||||
| 	OnDeleteStatefulSetStrategyType = "OnDelete" | ||||
| ) | ||||
|  | ||||
| // RollingUpdateStatefulSetStrategy is used to communicate parameter for RollingUpdateStatefulSetStrategyType. | ||||
| type RollingUpdateStatefulSetStrategy struct { | ||||
| 	// Partition indicates the ordinal at which the StatefulSet should be | ||||
| 	// partitioned. | ||||
| 	// Default value is 0. | ||||
| 	// +optional | ||||
| 	Partition *int32 `json:"partition,omitempty" protobuf:"varint,1,opt,name=partition"` | ||||
| } | ||||
|  | ||||
| // A StatefulSetSpec is the specification of a 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" protobuf:"varint,1,opt,name=replicas"` | ||||
|  | ||||
| 	// selector is a label query over pods that should match the replica count. | ||||
| 	// If empty, defaulted to labels on the pod template. | ||||
| 	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors | ||||
| 	// +optional | ||||
| 	Selector *metav1.LabelSelector `json:"selector,omitempty" protobuf:"bytes,2,opt,name=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" protobuf:"bytes,3,opt,name=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" protobuf:"bytes,4,rep,name=volumeClaimTemplates"` | ||||
|  | ||||
| 	// 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" protobuf:"bytes,5,opt,name=serviceName"` | ||||
|  | ||||
| 	// 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 PodManagementPolicyType `json:"podManagementPolicy,omitempty" protobuf:"bytes,6,opt,name=podManagementPolicy,casttype=PodManagementPolicyType"` | ||||
|  | ||||
| 	// 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" protobuf:"bytes,7,opt,name=updateStrategy"` | ||||
|  | ||||
| 	// 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" protobuf:"varint,8,opt,name=revisionHistoryLimit"` | ||||
| } | ||||
|  | ||||
| // StatefulSetStatus represents the current state of a 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" protobuf:"varint,1,opt,name=observedGeneration"` | ||||
|  | ||||
| 	// replicas is the number of Pods created by the StatefulSet controller. | ||||
| 	Replicas int32 `json:"replicas" protobuf:"varint,2,opt,name=replicas"` | ||||
|  | ||||
| 	// readyReplicas is the number of Pods created by the StatefulSet controller that have a Ready Condition. | ||||
| 	ReadyReplicas int32 `json:"readyReplicas,omitempty" protobuf:"varint,3,opt,name=readyReplicas"` | ||||
|  | ||||
| 	// currentReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version | ||||
| 	// indicated by currentRevision. | ||||
| 	CurrentReplicas int32 `json:"currentReplicas,omitempty" protobuf:"varint,4,opt,name=currentReplicas"` | ||||
|  | ||||
| 	// updatedReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version | ||||
| 	// indicated by updateRevision. | ||||
| 	UpdatedReplicas int32 `json:"updatedReplicas,omitempty" protobuf:"varint,5,opt,name=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" protobuf:"bytes,6,opt,name=currentRevision"` | ||||
|  | ||||
| 	// 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" protobuf:"bytes,7,opt,name=updateRevision"` | ||||
|  | ||||
| 	// 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" protobuf:"varint,9,opt,name=collisionCount"` | ||||
| } | ||||
|  | ||||
| // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||||
|  | ||||
| // StatefulSetList is a collection of StatefulSets. | ||||
| type StatefulSetList struct { | ||||
| 	metav1.TypeMeta `json:",inline"` | ||||
| 	// +optional | ||||
| 	metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` | ||||
| 	Items           []StatefulSet `json:"items" protobuf:"bytes,2,rep,name=items"` | ||||
| } | ||||
|  | ||||
| // +genclient | ||||
| // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||||
|  | ||||
| // Deployment enables declarative updates for Pods and ReplicaSets. | ||||
| type Deployment struct { | ||||
| 	metav1.TypeMeta `json:",inline"` | ||||
| 	// Standard object metadata. | ||||
| 	// +optional | ||||
| 	metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` | ||||
|  | ||||
| 	// Specification of the desired behavior of the Deployment. | ||||
| 	// +optional | ||||
| 	Spec DeploymentSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` | ||||
|  | ||||
| 	// Most recently observed status of the Deployment. | ||||
| 	// +optional | ||||
| 	Status DeploymentStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` | ||||
| } | ||||
|  | ||||
| // DeploymentSpec is the specification of the desired behavior of the Deployment. | ||||
| type DeploymentSpec struct { | ||||
| 	// Number of desired pods. This is a pointer to distinguish between explicit | ||||
| 	// zero and not specified. Defaults to 1. | ||||
| 	// +optional | ||||
| 	Replicas *int32 `json:"replicas,omitempty" protobuf:"varint,1,opt,name=replicas"` | ||||
|  | ||||
| 	// Label selector for pods. Existing ReplicaSets whose pods are | ||||
| 	// selected by this will be the ones affected by this deployment. | ||||
| 	// +optional | ||||
| 	Selector *metav1.LabelSelector `json:"selector,omitempty" protobuf:"bytes,2,opt,name=selector"` | ||||
|  | ||||
| 	// Template describes the pods that will be created. | ||||
| 	Template v1.PodTemplateSpec `json:"template" protobuf:"bytes,3,opt,name=template"` | ||||
|  | ||||
| 	// The deployment strategy to use to replace existing pods with new ones. | ||||
| 	// +optional | ||||
| 	Strategy DeploymentStrategy `json:"strategy,omitempty" protobuf:"bytes,4,opt,name=strategy"` | ||||
|  | ||||
| 	// 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) | ||||
| 	// +optional | ||||
| 	MinReadySeconds int32 `json:"minReadySeconds,omitempty" protobuf:"varint,5,opt,name=minReadySeconds"` | ||||
|  | ||||
| 	// The number of old ReplicaSets to retain to allow rollback. | ||||
| 	// This is a pointer to distinguish between explicit zero and not specified. | ||||
| 	// Defaults to 10. | ||||
| 	// +optional | ||||
| 	RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty" protobuf:"varint,6,opt,name=revisionHistoryLimit"` | ||||
|  | ||||
| 	// Indicates that the deployment is paused. | ||||
| 	// +optional | ||||
| 	Paused bool `json:"paused,omitempty" protobuf:"varint,7,opt,name=paused"` | ||||
|  | ||||
| 	// The maximum time in seconds for a deployment to make progress before it | ||||
| 	// is considered to be failed. The deployment controller will continue to | ||||
| 	// process failed deployments and a condition with a ProgressDeadlineExceeded | ||||
| 	// reason will be surfaced in the deployment status. Note that progress will | ||||
| 	// not be estimated during the time a deployment is paused. Defaults to 600s. | ||||
| 	ProgressDeadlineSeconds *int32 `json:"progressDeadlineSeconds,omitempty" protobuf:"varint,9,opt,name=progressDeadlineSeconds"` | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	// DefaultDeploymentUniqueLabelKey is the default key of the selector that is added | ||||
| 	// to existing RCs (and label key that is added to its pods) to prevent the existing RCs | ||||
| 	// to select new pods (and old pods being select by new RC). | ||||
| 	DefaultDeploymentUniqueLabelKey string = "pod-template-hash" | ||||
| ) | ||||
|  | ||||
| // DeploymentStrategy describes how to replace existing pods with new ones. | ||||
| type DeploymentStrategy struct { | ||||
| 	// Type of deployment. Can be "Recreate" or "RollingUpdate". Default is RollingUpdate. | ||||
| 	// +optional | ||||
| 	Type DeploymentStrategyType `json:"type,omitempty" protobuf:"bytes,1,opt,name=type,casttype=DeploymentStrategyType"` | ||||
|  | ||||
| 	// Rolling update config params. Present only if DeploymentStrategyType = | ||||
| 	// RollingUpdate. | ||||
| 	//--- | ||||
| 	// TODO: Update this to follow our convention for oneOf, whatever we decide it | ||||
| 	// to be. | ||||
| 	// +optional | ||||
| 	RollingUpdate *RollingUpdateDeployment `json:"rollingUpdate,omitempty" protobuf:"bytes,2,opt,name=rollingUpdate"` | ||||
| } | ||||
|  | ||||
| type DeploymentStrategyType string | ||||
|  | ||||
| const ( | ||||
| 	// Kill all existing pods before creating new ones. | ||||
| 	RecreateDeploymentStrategyType DeploymentStrategyType = "Recreate" | ||||
|  | ||||
| 	// Replace the old RCs by new one using rolling update i.e gradually scale down the old RCs and scale up the new one. | ||||
| 	RollingUpdateDeploymentStrategyType DeploymentStrategyType = "RollingUpdate" | ||||
| ) | ||||
|  | ||||
| // Spec to control the desired behavior of rolling update. | ||||
| type RollingUpdateDeployment struct { | ||||
| 	// 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. | ||||
| 	// This can not be 0 if MaxSurge is 0. | ||||
| 	// Defaults to 25%. | ||||
| 	// Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods | ||||
| 	// immediately when the rolling update starts. Once new pods are ready, old RC | ||||
| 	// can be scaled down further, followed by scaling up the new RC, ensuring | ||||
| 	// that the total number of pods available at all times during the update is at | ||||
| 	// least 70% of desired pods. | ||||
| 	// +optional | ||||
| 	MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty" protobuf:"bytes,1,opt,name=maxUnavailable"` | ||||
|  | ||||
| 	// The maximum number of pods that can be scheduled above the desired number of | ||||
| 	// pods. | ||||
| 	// Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). | ||||
| 	// This can not be 0 if MaxUnavailable is 0. | ||||
| 	// Absolute number is calculated from percentage by rounding up. | ||||
| 	// Defaults to 25%. | ||||
| 	// Example: when this is set to 30%, the new RC can be scaled up immediately when | ||||
| 	// the rolling update starts, such that the total number of old and new pods do not exceed | ||||
| 	// 130% of desired pods. Once old pods have been killed, | ||||
| 	// new RC can be scaled up further, ensuring that total number of pods running | ||||
| 	// at any time during the update is atmost 130% of desired pods. | ||||
| 	// +optional | ||||
| 	MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"` | ||||
| } | ||||
|  | ||||
| // DeploymentStatus is the most recently observed status of the Deployment. | ||||
| type DeploymentStatus struct { | ||||
| 	// The generation observed by the deployment controller. | ||||
| 	// +optional | ||||
| 	ObservedGeneration int64 `json:"observedGeneration,omitempty" protobuf:"varint,1,opt,name=observedGeneration"` | ||||
|  | ||||
| 	// Total number of non-terminated pods targeted by this deployment (their labels match the selector). | ||||
| 	// +optional | ||||
| 	Replicas int32 `json:"replicas,omitempty" protobuf:"varint,2,opt,name=replicas"` | ||||
|  | ||||
| 	// Total number of non-terminated pods targeted by this deployment that have the desired template spec. | ||||
| 	// +optional | ||||
| 	UpdatedReplicas int32 `json:"updatedReplicas,omitempty" protobuf:"varint,3,opt,name=updatedReplicas"` | ||||
|  | ||||
| 	// Total number of ready pods targeted by this deployment. | ||||
| 	// +optional | ||||
| 	ReadyReplicas int32 `json:"readyReplicas,omitempty" protobuf:"varint,7,opt,name=readyReplicas"` | ||||
|  | ||||
| 	// Total number of available pods (ready for at least minReadySeconds) targeted by this deployment. | ||||
| 	// +optional | ||||
| 	AvailableReplicas int32 `json:"availableReplicas,omitempty" protobuf:"varint,4,opt,name=availableReplicas"` | ||||
|  | ||||
| 	// Total number of unavailable pods targeted by this deployment. This is the total number of | ||||
| 	// pods that are still required for the deployment to have 100% available capacity. They may | ||||
| 	// either be pods that are running but not yet available or pods that still have not been created. | ||||
| 	// +optional | ||||
| 	UnavailableReplicas int32 `json:"unavailableReplicas,omitempty" protobuf:"varint,5,opt,name=unavailableReplicas"` | ||||
|  | ||||
| 	// Represents the latest available observations of a deployment's current state. | ||||
| 	// +patchMergeKey=type | ||||
| 	// +patchStrategy=merge | ||||
| 	Conditions []DeploymentCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,6,rep,name=conditions"` | ||||
|  | ||||
| 	// Count of hash collisions for the Deployment. The Deployment controller uses this | ||||
| 	// field as a collision avoidance mechanism when it needs to create the name for the | ||||
| 	// newest ReplicaSet. | ||||
| 	// +optional | ||||
| 	CollisionCount *int32 `json:"collisionCount,omitempty" protobuf:"varint,8,opt,name=collisionCount"` | ||||
| } | ||||
|  | ||||
| type DeploymentConditionType string | ||||
|  | ||||
| // These are valid conditions of a deployment. | ||||
| const ( | ||||
| 	// Available means the deployment is available, ie. at least the minimum available | ||||
| 	// replicas required are up and running for at least minReadySeconds. | ||||
| 	DeploymentAvailable DeploymentConditionType = "Available" | ||||
| 	// Progressing means the deployment is progressing. Progress for a deployment is | ||||
| 	// considered when a new replica set is created or adopted, and when new pods scale | ||||
| 	// up or old pods scale down. Progress is not estimated for paused deployments or | ||||
| 	// when progressDeadlineSeconds is not specified. | ||||
| 	DeploymentProgressing DeploymentConditionType = "Progressing" | ||||
| 	// ReplicaFailure is added in a deployment when one of its pods fails to be created | ||||
| 	// or deleted. | ||||
| 	DeploymentReplicaFailure DeploymentConditionType = "ReplicaFailure" | ||||
| ) | ||||
|  | ||||
| // DeploymentCondition describes the state of a deployment at a certain point. | ||||
| type DeploymentCondition struct { | ||||
| 	// Type of deployment condition. | ||||
| 	Type DeploymentConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=DeploymentConditionType"` | ||||
| 	// Status of the condition, one of True, False, Unknown. | ||||
| 	Status v1.ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=k8s.io/api/core/v1.ConditionStatus"` | ||||
| 	// The last time this condition was updated. | ||||
| 	LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty" protobuf:"bytes,6,opt,name=lastUpdateTime"` | ||||
| 	// Last time the condition transitioned from one status to another. | ||||
| 	LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,7,opt,name=lastTransitionTime"` | ||||
| 	// The reason for the condition's last transition. | ||||
| 	Reason string `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason"` | ||||
| 	// A human readable message indicating details about the transition. | ||||
| 	Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"` | ||||
| } | ||||
|  | ||||
| // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||||
|  | ||||
| // DeploymentList is a list of Deployments. | ||||
| type DeploymentList struct { | ||||
| 	metav1.TypeMeta `json:",inline"` | ||||
| 	// Standard list metadata. | ||||
| 	// +optional | ||||
| 	metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` | ||||
|  | ||||
| 	// Items is the list of Deployments. | ||||
| 	Items []Deployment `json:"items" protobuf:"bytes,2,rep,name=items"` | ||||
| } | ||||
|  | ||||
| // DaemonSetUpdateStrategy is a struct used to control the update strategy for a DaemonSet. | ||||
| type DaemonSetUpdateStrategy struct { | ||||
| 	// Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is RollingUpdate. | ||||
| @@ -199,3 +600,170 @@ type DaemonSetList struct { | ||||
| 	// A list of daemon sets. | ||||
| 	Items []DaemonSet `json:"items" protobuf:"bytes,2,rep,name=items"` | ||||
| } | ||||
|  | ||||
| // +genclient | ||||
| // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||||
|  | ||||
| // ReplicaSet ensures that a specified number of pod replicas are running at any given time. | ||||
| type ReplicaSet struct { | ||||
| 	metav1.TypeMeta `json:",inline"` | ||||
|  | ||||
| 	// If the Labels of a ReplicaSet are empty, they are defaulted to | ||||
| 	// be the same as the Pod(s) that the ReplicaSet manages. | ||||
| 	// Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata | ||||
| 	// +optional | ||||
| 	metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` | ||||
|  | ||||
| 	// Spec defines the specification of the desired behavior of the ReplicaSet. | ||||
| 	// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status | ||||
| 	// +optional | ||||
| 	Spec ReplicaSetSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` | ||||
|  | ||||
| 	// Status is the most recently observed status of the ReplicaSet. | ||||
| 	// This data may be out of date by some window of time. | ||||
| 	// Populated by the system. | ||||
| 	// Read-only. | ||||
| 	// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status | ||||
| 	// +optional | ||||
| 	Status ReplicaSetStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` | ||||
| } | ||||
|  | ||||
| // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||||
|  | ||||
| // ReplicaSetList is a collection of ReplicaSets. | ||||
| type ReplicaSetList struct { | ||||
| 	metav1.TypeMeta `json:",inline"` | ||||
| 	// Standard list metadata. | ||||
| 	// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds | ||||
| 	// +optional | ||||
| 	metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` | ||||
|  | ||||
| 	// List of ReplicaSets. | ||||
| 	// More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller | ||||
| 	Items []ReplicaSet `json:"items" protobuf:"bytes,2,rep,name=items"` | ||||
| } | ||||
|  | ||||
| // ReplicaSetSpec is the specification of a ReplicaSet. | ||||
| type ReplicaSetSpec struct { | ||||
| 	// Replicas is the number of desired replicas. | ||||
| 	// This is a pointer to distinguish between explicit zero and unspecified. | ||||
| 	// Defaults to 1. | ||||
| 	// More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/#what-is-a-replicationcontroller | ||||
| 	// +optional | ||||
| 	Replicas *int32 `json:"replicas,omitempty" protobuf:"varint,1,opt,name=replicas"` | ||||
|  | ||||
| 	// 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) | ||||
| 	// +optional | ||||
| 	MinReadySeconds int32 `json:"minReadySeconds,omitempty" protobuf:"varint,4,opt,name=minReadySeconds"` | ||||
|  | ||||
| 	// Selector is a label query over pods that should match the replica count. | ||||
| 	// If the selector is empty, it is defaulted to the labels present on the pod template. | ||||
| 	// Label keys and values that must match in order to be controlled by this replica set. | ||||
| 	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors | ||||
| 	// +optional | ||||
| 	Selector *metav1.LabelSelector `json:"selector,omitempty" protobuf:"bytes,2,opt,name=selector"` | ||||
|  | ||||
| 	// Template is the object that describes the pod that will be created if | ||||
| 	// insufficient replicas are detected. | ||||
| 	// More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template | ||||
| 	// +optional | ||||
| 	Template v1.PodTemplateSpec `json:"template,omitempty" protobuf:"bytes,3,opt,name=template"` | ||||
| } | ||||
|  | ||||
| // ReplicaSetStatus represents the current status of a ReplicaSet. | ||||
| type ReplicaSetStatus struct { | ||||
| 	// Replicas is the most recently oberved number of replicas. | ||||
| 	// More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/#what-is-a-replicationcontroller | ||||
| 	Replicas int32 `json:"replicas" protobuf:"varint,1,opt,name=replicas"` | ||||
|  | ||||
| 	// The number of pods that have labels matching the labels of the pod template of the replicaset. | ||||
| 	// +optional | ||||
| 	FullyLabeledReplicas int32 `json:"fullyLabeledReplicas,omitempty" protobuf:"varint,2,opt,name=fullyLabeledReplicas"` | ||||
|  | ||||
| 	// The number of ready replicas for this replica set. | ||||
| 	// +optional | ||||
| 	ReadyReplicas int32 `json:"readyReplicas,omitempty" protobuf:"varint,4,opt,name=readyReplicas"` | ||||
|  | ||||
| 	// The number of available replicas (ready for at least minReadySeconds) for this replica set. | ||||
| 	// +optional | ||||
| 	AvailableReplicas int32 `json:"availableReplicas,omitempty" protobuf:"varint,5,opt,name=availableReplicas"` | ||||
|  | ||||
| 	// ObservedGeneration reflects the generation of the most recently observed ReplicaSet. | ||||
| 	// +optional | ||||
| 	ObservedGeneration int64 `json:"observedGeneration,omitempty" protobuf:"varint,3,opt,name=observedGeneration"` | ||||
|  | ||||
| 	// Represents the latest available observations of a replica set's current state. | ||||
| 	// +optional | ||||
| 	// +patchMergeKey=type | ||||
| 	// +patchStrategy=merge | ||||
| 	Conditions []ReplicaSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,6,rep,name=conditions"` | ||||
| } | ||||
|  | ||||
| type ReplicaSetConditionType string | ||||
|  | ||||
| // These are valid conditions of a replica set. | ||||
| const ( | ||||
| 	// ReplicaSetReplicaFailure is added in a replica set when one of its pods fails to be created | ||||
| 	// due to insufficient quota, limit ranges, pod security policy, node selectors, etc. or deleted | ||||
| 	// due to kubelet being down or finalizers are failing. | ||||
| 	ReplicaSetReplicaFailure ReplicaSetConditionType = "ReplicaFailure" | ||||
| ) | ||||
|  | ||||
| // ReplicaSetCondition describes the state of a replica set at a certain point. | ||||
| type ReplicaSetCondition struct { | ||||
| 	// Type of replica set condition. | ||||
| 	Type ReplicaSetConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=ReplicaSetConditionType"` | ||||
| 	// Status of the condition, one of True, False, Unknown. | ||||
| 	Status v1.ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=k8s.io/api/core/v1.ConditionStatus"` | ||||
| 	// The last time the condition transitioned from one status to another. | ||||
| 	// +optional | ||||
| 	LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,3,opt,name=lastTransitionTime"` | ||||
| 	// The reason for the condition's last transition. | ||||
| 	// +optional | ||||
| 	Reason string `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason"` | ||||
| 	// A human readable message indicating details about the transition. | ||||
| 	// +optional | ||||
| 	Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"` | ||||
| } | ||||
|  | ||||
| // +genclient | ||||
| // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||||
|  | ||||
| // ControllerRevision implements an immutable snapshot of state data. Clients | ||||
| // are responsible for serializing and deserializing the objects that contain | ||||
| // their internal state. | ||||
| // Once a ControllerRevision has been successfully created, it can not be updated. | ||||
| // The API Server will fail validation of all requests that attempt to mutate | ||||
| // the Data field. ControllerRevisions may, however, be deleted. Note that, due to its use by both | ||||
| // the DaemonSet and StatefulSet controllers for update and rollback, this object is beta. However, | ||||
| // it may be subject to name and representation changes in future releases, and clients should not | ||||
| // depend on its stability. It is primarily for internal use by controllers. | ||||
| type ControllerRevision struct { | ||||
| 	metav1.TypeMeta `json:",inline"` | ||||
| 	// Standard object's metadata. | ||||
| 	// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata | ||||
| 	// +optional | ||||
| 	metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` | ||||
|  | ||||
| 	// Data is the serialized representation of the state. | ||||
| 	Data runtime.RawExtension `json:"data,omitempty" protobuf:"bytes,2,opt,name=data"` | ||||
|  | ||||
| 	// Revision indicates the revision of the state represented by Data. | ||||
| 	Revision int64 `json:"revision" protobuf:"varint,3,opt,name=revision"` | ||||
| } | ||||
|  | ||||
| // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||||
|  | ||||
| // ControllerRevisionList is a resource containing a list of ControllerRevision objects. | ||||
| type ControllerRevisionList struct { | ||||
| 	metav1.TypeMeta `json:",inline"` | ||||
|  | ||||
| 	// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata | ||||
| 	// +optional | ||||
| 	metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` | ||||
|  | ||||
| 	// Items is the list of ControllerRevisions | ||||
| 	Items []ControllerRevision `json:"items" protobuf:"bytes,2,rep,name=items"` | ||||
| } | ||||
|   | ||||
| @@ -181,6 +181,26 @@ var etcdStorageData = map[schema.GroupVersionResource]struct { | ||||
| 		expectedEtcdPath: "/registry/daemonsets/etcdstoragepathtestnamespace/ds6", | ||||
| 		expectedGVK:      gvkP("extensions", "v1beta1", "DaemonSet"), | ||||
| 	}, | ||||
| 	gvr("apps", "v1", "deployments"): { | ||||
| 		stub:             `{"metadata": {"name": "deployment4"}, "spec": {"selector": {"matchLabels": {"f": "z"}}, "template": {"metadata": {"labels": {"f": "z"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container6"}]}}}}`, | ||||
| 		expectedEtcdPath: "/registry/deployments/etcdstoragepathtestnamespace/deployment4", | ||||
| 		expectedGVK:      gvkP("extensions", "v1beta1", "Deployment"), | ||||
| 	}, | ||||
| 	gvr("apps", "v1", "statefulsets"): { | ||||
| 		stub:             `{"metadata": {"name": "ss3"}, "spec": {"selector": {"matchLabels": {"a": "b"}}, "template": {"metadata": {"labels": {"a": "b"}}}}}`, | ||||
| 		expectedEtcdPath: "/registry/statefulsets/etcdstoragepathtestnamespace/ss3", | ||||
| 		expectedGVK:      gvkP("apps", "v1beta1", "StatefulSet"), | ||||
| 	}, | ||||
| 	gvr("apps", "v1", "replicasets"): { | ||||
| 		stub:             `{"metadata": {"name": "rs3"}, "spec": {"selector": {"matchLabels": {"g": "h"}}, "template": {"metadata": {"labels": {"g": "h"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container4"}]}}}}`, | ||||
| 		expectedEtcdPath: "/registry/replicasets/etcdstoragepathtestnamespace/rs3", | ||||
| 		expectedGVK:      gvkP("extensions", "v1beta1", "ReplicaSet"), | ||||
| 	}, | ||||
| 	gvr("apps", "v1", "controllerrevisions"): { | ||||
| 		stub:             `{"metadata":{"name":"crs3"},"data":{"name":"abc","namespace":"default","creationTimestamp":null,"Spec":{"Replicas":0,"Selector":{"matchLabels":{"foo":"bar"}},"Template":{"creationTimestamp":null,"labels":{"foo":"bar"},"Spec":{"Volumes":null,"InitContainers":null,"Containers":null,"RestartPolicy":"Always","TerminationGracePeriodSeconds":null,"ActiveDeadlineSeconds":null,"DNSPolicy":"ClusterFirst","NodeSelector":null,"ServiceAccountName":"","AutomountServiceAccountToken":null,"NodeName":"","SecurityContext":null,"ImagePullSecrets":null,"Hostname":"","Subdomain":"","Affinity":null,"SchedulerName":"","Tolerations":null,"HostAliases":null}},"VolumeClaimTemplates":null,"ServiceName":""},"Status":{"ObservedGeneration":null,"Replicas":0}},"revision":0}`, | ||||
| 		expectedEtcdPath: "/registry/controllerrevisions/etcdstoragepathtestnamespace/crs3", | ||||
| 		expectedGVK:      gvkP("apps", "v1beta1", "ControllerRevision"), | ||||
| 	}, | ||||
| 	// -- | ||||
|  | ||||
| 	// k8s.io/kubernetes/pkg/apis/autoscaling/v1 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Kenneth Owens
					Kenneth Owens