mirror of
https://github.com/kubernetes/sample-controller.git
synced 2026-05-01 00:00:03 +08:00
Merge pull request #72947 from apelisse/wip-feature-serverside-apply-merge
Merge feature-serverside-apply back in master Kubernetes-commit: 2a5a41a08b08075aa2960170c8342d974ccc2cd3
This commit is contained in:
+24
@@ -27,6 +27,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"sigs.k8s.io/structured-merge-diff/merge"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -184,6 +185,29 @@ func NewConflict(qualifiedResource schema.GroupResource, name string, err error)
|
||||
}}
|
||||
}
|
||||
|
||||
// NewApplyConflict returns an error including details on the requests apply conflicts
|
||||
func NewApplyConflict(conflicts merge.Conflicts) *StatusError {
|
||||
causes := make([]metav1.StatusCause, 0, len(conflicts))
|
||||
for _, conflict := range conflicts {
|
||||
causes = append(causes, metav1.StatusCause{
|
||||
Type: metav1.CauseType("conflict"),
|
||||
Message: conflict.Error(),
|
||||
Field: conflict.Path.String(),
|
||||
})
|
||||
}
|
||||
|
||||
return &StatusError{ErrStatus: metav1.Status{
|
||||
Status: metav1.StatusFailure,
|
||||
Code: http.StatusConflict,
|
||||
Reason: metav1.StatusReasonConflict,
|
||||
Details: &metav1.StatusDetails{
|
||||
// TODO: Get obj details here?
|
||||
Causes: causes,
|
||||
},
|
||||
Message: fmt.Sprintf("Apply failed with %d conflicts: %s", len(conflicts), conflicts.Error()),
|
||||
}}
|
||||
}
|
||||
|
||||
// NewGone returns an error indicating the item no longer available at the server and no forwarding address is known.
|
||||
func NewGone(message string) *StatusError {
|
||||
return &StatusError{metav1.Status{
|
||||
|
||||
+2
-2
@@ -20,14 +20,13 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"k8s.io/klog"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// errNotList is returned when an object implements the Object style interfaces but not the List style
|
||||
@@ -138,6 +137,7 @@ func AsPartialObjectMetadata(m metav1.Object) *metav1beta1.PartialObjectMetadata
|
||||
Finalizers: m.GetFinalizers(),
|
||||
ClusterName: m.GetClusterName(),
|
||||
Initializers: m.GetInitializers(),
|
||||
ManagedFields: m.GetManagedFields(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -680,7 +680,7 @@ func NewScaledQuantity(value int64, scale Scale) *Quantity {
|
||||
}
|
||||
}
|
||||
|
||||
// Value returns the value of q; any fractional part will be lost.
|
||||
// Value returns the unscaled value of q rounded up to the nearest integer away from 0.
|
||||
func (q *Quantity) Value() int64 {
|
||||
return q.ScaledValue(0)
|
||||
}
|
||||
|
||||
+996
-201
File diff suppressed because it is too large
Load Diff
+74
@@ -202,6 +202,23 @@ message ExportOptions {
|
||||
optional bool exact = 2;
|
||||
}
|
||||
|
||||
// Fields stores a set of fields in a data structure like a Trie.
|
||||
// To understand how this is used, see: https://github.com/kubernetes-sigs/structured-merge-diff
|
||||
message Fields {
|
||||
// Map stores a set of fields in a data structure like a Trie.
|
||||
//
|
||||
// Each key is either a '.' representing the field itself, and will always map to an empty set,
|
||||
// or a string representing a sub-field or item. The string will follow one of these four formats:
|
||||
// 'f:<name>', where <name> is the name of a field in a struct, or key in a map
|
||||
// 'v:<value>', where <value> is the exact json formatted value of a list item
|
||||
// 'i:<index>', where <index> is position of a item in a list
|
||||
// 'k:<keys>', where <keys> is a map of a list item's key fields to their unique values
|
||||
// If a key maps to an empty Fields value, the field that key represents is part of the set.
|
||||
//
|
||||
// The exact format is defined in k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal
|
||||
map<string, Fields> map = 1;
|
||||
}
|
||||
|
||||
// GetOptions is the standard query options to the standard REST get call.
|
||||
message GetOptions {
|
||||
// When specified:
|
||||
@@ -436,6 +453,31 @@ message ListOptions {
|
||||
optional string continue = 8;
|
||||
}
|
||||
|
||||
// ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of the resource
|
||||
// that the fieldset applies to.
|
||||
message ManagedFieldsEntry {
|
||||
// Manager is an identifier of the workflow managing these fields.
|
||||
optional string manager = 1;
|
||||
|
||||
// Operation is the type of operation which lead to this ManagedFieldsEntry being created.
|
||||
// The only valid values for this field are 'Apply' and 'Update'.
|
||||
optional string operation = 2;
|
||||
|
||||
// APIVersion defines the version of this resource that this field set
|
||||
// applies to. The format is "group/version" just like the top-level
|
||||
// APIVersion field. It is necessary to track the version of a field
|
||||
// set because it cannot be automatically converted.
|
||||
optional string apiVersion = 3;
|
||||
|
||||
// Time is timestamp of when these fields were set. It should always be empty if Operation is 'Apply'
|
||||
// +optional
|
||||
optional Time time = 4;
|
||||
|
||||
// Fields identifies a set of fields.
|
||||
// +optional
|
||||
optional Fields fields = 5;
|
||||
}
|
||||
|
||||
// MicroTime is version of Time with microsecond level precision.
|
||||
//
|
||||
// +protobuf.options.marshal=false
|
||||
@@ -617,6 +659,19 @@ message ObjectMeta {
|
||||
// This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.
|
||||
// +optional
|
||||
optional string clusterName = 15;
|
||||
|
||||
// ManagedFields maps workflow-id and version to the set of fields
|
||||
// that are managed by that workflow. This is mostly for internal
|
||||
// housekeeping, and users typically shouldn't need to set or
|
||||
// understand this field. A workflow can be the user's name, a
|
||||
// controller's name, or the name of a specific apply path like
|
||||
// "ci-cd". The set of fields is always in the version that the
|
||||
// workflow used when modifying the object.
|
||||
//
|
||||
// This field is alpha and can be changed or removed without notice.
|
||||
//
|
||||
// +optional
|
||||
repeated ManagedFieldsEntry managedFields = 17;
|
||||
}
|
||||
|
||||
// OwnerReference contains enough information to let you identify an owning
|
||||
@@ -656,6 +711,24 @@ message OwnerReference {
|
||||
message Patch {
|
||||
}
|
||||
|
||||
// PatchOptions may be provided when patching an API object.
|
||||
// PatchOptions is meant to be a superset of UpdateOptions.
|
||||
message PatchOptions {
|
||||
// When present, indicates that modifications should not be
|
||||
// persisted. An invalid or unrecognized dryRun directive will
|
||||
// result in an error response and no further processing of the
|
||||
// request. Valid values are:
|
||||
// - All: all dry run stages will be processed
|
||||
// +optional
|
||||
repeated string dryRun = 1;
|
||||
|
||||
// Force is going to "force" Apply requests. It means user will
|
||||
// re-acquire conflicting fields owned by other people. Force
|
||||
// flag must be unset for non-apply patch requests.
|
||||
// +optional
|
||||
optional bool force = 2;
|
||||
}
|
||||
|
||||
// Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.
|
||||
message Preconditions {
|
||||
// Specifies the target UID.
|
||||
@@ -841,6 +914,7 @@ message TypeMeta {
|
||||
}
|
||||
|
||||
// UpdateOptions may be provided when updating an API object.
|
||||
// All fields in UpdateOptions should also be present in PatchOptions.
|
||||
message UpdateOptions {
|
||||
// When present, indicates that modifications should not be
|
||||
// persisted. An invalid or unrecognized dryRun directive will
|
||||
|
||||
+15
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
@@ -243,4 +244,18 @@ func ResetObjectMetaForStatus(meta, existingMeta Object) {
|
||||
meta.SetAnnotations(existingMeta.GetAnnotations())
|
||||
meta.SetFinalizers(existingMeta.GetFinalizers())
|
||||
meta.SetOwnerReferences(existingMeta.GetOwnerReferences())
|
||||
meta.SetManagedFields(existingMeta.GetManagedFields())
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler
|
||||
func (f Fields) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(&f.Map)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler
|
||||
func (f *Fields) UnmarshalJSON(b []byte) error {
|
||||
return json.Unmarshal(b, &f.Map)
|
||||
}
|
||||
|
||||
var _ json.Marshaler = Fields{}
|
||||
var _ json.Unmarshaler = &Fields{}
|
||||
|
||||
+8
-2
@@ -63,6 +63,8 @@ type Object interface {
|
||||
SetOwnerReferences([]OwnerReference)
|
||||
GetClusterName() string
|
||||
SetClusterName(clusterName string)
|
||||
GetManagedFields() []ManagedFieldsEntry
|
||||
SetManagedFields(managedFields []ManagedFieldsEntry)
|
||||
}
|
||||
|
||||
// ListMetaAccessor retrieves the list interface from an object
|
||||
@@ -166,5 +168,9 @@ func (meta *ObjectMeta) GetOwnerReferences() []OwnerReference { return m
|
||||
func (meta *ObjectMeta) SetOwnerReferences(references []OwnerReference) {
|
||||
meta.OwnerReferences = references
|
||||
}
|
||||
func (meta *ObjectMeta) GetClusterName() string { return meta.ClusterName }
|
||||
func (meta *ObjectMeta) SetClusterName(clusterName string) { meta.ClusterName = clusterName }
|
||||
func (meta *ObjectMeta) GetClusterName() string { return meta.ClusterName }
|
||||
func (meta *ObjectMeta) SetClusterName(clusterName string) { meta.ClusterName = clusterName }
|
||||
func (meta *ObjectMeta) GetManagedFields() []ManagedFieldsEntry { return meta.ManagedFields }
|
||||
func (meta *ObjectMeta) SetManagedFields(managedFields []ManagedFieldsEntry) {
|
||||
meta.ManagedFields = managedFields
|
||||
}
|
||||
|
||||
+2
@@ -55,6 +55,7 @@ func AddToGroupVersion(scheme *runtime.Scheme, groupVersion schema.GroupVersion)
|
||||
&DeleteOptions{},
|
||||
&CreateOptions{},
|
||||
&UpdateOptions{},
|
||||
&PatchOptions{},
|
||||
)
|
||||
utilruntime.Must(scheme.AddConversionFuncs(
|
||||
Convert_v1_WatchEvent_To_watch_Event,
|
||||
@@ -90,6 +91,7 @@ func init() {
|
||||
&DeleteOptions{},
|
||||
&CreateOptions{},
|
||||
&UpdateOptions{},
|
||||
&PatchOptions{},
|
||||
)
|
||||
|
||||
// register manually. This usually goes through the SchemeBuilder, which we cannot use here.
|
||||
|
||||
+82
@@ -252,6 +252,19 @@ type ObjectMeta struct {
|
||||
// This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.
|
||||
// +optional
|
||||
ClusterName string `json:"clusterName,omitempty" protobuf:"bytes,15,opt,name=clusterName"`
|
||||
|
||||
// ManagedFields maps workflow-id and version to the set of fields
|
||||
// that are managed by that workflow. This is mostly for internal
|
||||
// housekeeping, and users typically shouldn't need to set or
|
||||
// understand this field. A workflow can be the user's name, a
|
||||
// controller's name, or the name of a specific apply path like
|
||||
// "ci-cd". The set of fields is always in the version that the
|
||||
// workflow used when modifying the object.
|
||||
//
|
||||
// This field is alpha and can be changed or removed without notice.
|
||||
//
|
||||
// +optional
|
||||
ManagedFields []ManagedFieldsEntry `json:"managedFields,omitempty" protobuf:"bytes,17,rep,name=managedFields"`
|
||||
}
|
||||
|
||||
// Initializers tracks the progress of initialization.
|
||||
@@ -494,7 +507,30 @@ type CreateOptions struct {
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// PatchOptions may be provided when patching an API object.
|
||||
// PatchOptions is meant to be a superset of UpdateOptions.
|
||||
type PatchOptions struct {
|
||||
TypeMeta `json:",inline"`
|
||||
|
||||
// When present, indicates that modifications should not be
|
||||
// persisted. An invalid or unrecognized dryRun directive will
|
||||
// result in an error response and no further processing of the
|
||||
// request. Valid values are:
|
||||
// - All: all dry run stages will be processed
|
||||
// +optional
|
||||
DryRun []string `json:"dryRun,omitempty" protobuf:"bytes,1,rep,name=dryRun"`
|
||||
|
||||
// Force is going to "force" Apply requests. It means user will
|
||||
// re-acquire conflicting fields owned by other people. Force
|
||||
// flag must be unset for non-apply patch requests.
|
||||
// +optional
|
||||
Force *bool `json:"force,omitempty" protobuf:"varint,2,opt,name=force"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// UpdateOptions may be provided when updating an API object.
|
||||
// All fields in UpdateOptions should also be present in PatchOptions.
|
||||
type UpdateOptions struct {
|
||||
TypeMeta `json:",inline"`
|
||||
|
||||
@@ -1009,3 +1045,49 @@ const (
|
||||
LabelSelectorOpExists LabelSelectorOperator = "Exists"
|
||||
LabelSelectorOpDoesNotExist LabelSelectorOperator = "DoesNotExist"
|
||||
)
|
||||
|
||||
// ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of the resource
|
||||
// that the fieldset applies to.
|
||||
type ManagedFieldsEntry struct {
|
||||
// Manager is an identifier of the workflow managing these fields.
|
||||
Manager string `json:"manager,omitempty" protobuf:"bytes,1,opt,name=manager"`
|
||||
// Operation is the type of operation which lead to this ManagedFieldsEntry being created.
|
||||
// The only valid values for this field are 'Apply' and 'Update'.
|
||||
Operation ManagedFieldsOperationType `json:"operation,omitempty" protobuf:"bytes,2,opt,name=operation,casttype=ManagedFieldsOperationType"`
|
||||
// APIVersion defines the version of this resource that this field set
|
||||
// applies to. The format is "group/version" just like the top-level
|
||||
// APIVersion field. It is necessary to track the version of a field
|
||||
// set because it cannot be automatically converted.
|
||||
APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,3,opt,name=apiVersion"`
|
||||
// Time is timestamp of when these fields were set. It should always be empty if Operation is 'Apply'
|
||||
// +optional
|
||||
Time *Time `json:"time,omitempty" protobuf:"bytes,4,opt,name=time"`
|
||||
// Fields identifies a set of fields.
|
||||
// +optional
|
||||
Fields *Fields `json:"fields,omitempty" protobuf:"bytes,5,opt,name=fields,casttype=Fields"`
|
||||
}
|
||||
|
||||
// ManagedFieldsOperationType is the type of operation which lead to a ManagedFieldsEntry being created.
|
||||
type ManagedFieldsOperationType string
|
||||
|
||||
const (
|
||||
ManagedFieldsOperationApply ManagedFieldsOperationType = "Apply"
|
||||
ManagedFieldsOperationUpdate ManagedFieldsOperationType = "Update"
|
||||
)
|
||||
|
||||
// Fields stores a set of fields in a data structure like a Trie.
|
||||
// To understand how this is used, see: https://github.com/kubernetes-sigs/structured-merge-diff
|
||||
type Fields struct {
|
||||
// Map stores a set of fields in a data structure like a Trie.
|
||||
//
|
||||
// Each key is either a '.' representing the field itself, and will always map to an empty set,
|
||||
// or a string representing a sub-field or item. The string will follow one of these four formats:
|
||||
// 'f:<name>', where <name> is the name of a field in a struct, or key in a map
|
||||
// 'v:<value>', where <value> is the exact json formatted value of a list item
|
||||
// 'i:<index>', where <index> is position of a item in a list
|
||||
// 'k:<keys>', where <keys> is a map of a list item's key fields to their unique values
|
||||
// If a key maps to an empty Fields value, the field that key represents is part of the set.
|
||||
//
|
||||
// The exact format is defined in k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal
|
||||
Map map[string]Fields `json:",inline" protobuf:"bytes,1,rep,name=map"`
|
||||
}
|
||||
|
||||
+33
-1
@@ -118,6 +118,14 @@ func (ExportOptions) SwaggerDoc() map[string]string {
|
||||
return map_ExportOptions
|
||||
}
|
||||
|
||||
var map_Fields = map[string]string{
|
||||
"": "Fields stores a set of fields in a data structure like a Trie. To understand how this is used, see: https://github.com/kubernetes-sigs/structured-merge-diff",
|
||||
}
|
||||
|
||||
func (Fields) SwaggerDoc() map[string]string {
|
||||
return map_Fields
|
||||
}
|
||||
|
||||
var map_GetOptions = map[string]string{
|
||||
"": "GetOptions is the standard query options to the standard REST get call.",
|
||||
"resourceVersion": "When specified: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
@@ -213,6 +221,19 @@ func (ListOptions) SwaggerDoc() map[string]string {
|
||||
return map_ListOptions
|
||||
}
|
||||
|
||||
var map_ManagedFieldsEntry = map[string]string{
|
||||
"": "ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of the resource that the fieldset applies to.",
|
||||
"manager": "Manager is an identifier of the workflow managing these fields.",
|
||||
"operation": "Operation is the type of operation which lead to this ManagedFieldsEntry being created. The only valid values for this field are 'Apply' and 'Update'.",
|
||||
"apiVersion": "APIVersion defines the version of this resource that this field set applies to. The format is \"group/version\" just like the top-level APIVersion field. It is necessary to track the version of a field set because it cannot be automatically converted.",
|
||||
"time": "Time is timestamp of when these fields were set. It should always be empty if Operation is 'Apply'",
|
||||
"fields": "Fields identifies a set of fields.",
|
||||
}
|
||||
|
||||
func (ManagedFieldsEntry) SwaggerDoc() map[string]string {
|
||||
return map_ManagedFieldsEntry
|
||||
}
|
||||
|
||||
var map_ObjectMeta = map[string]string{
|
||||
"": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.",
|
||||
"name": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
|
||||
@@ -231,6 +252,7 @@ var map_ObjectMeta = map[string]string{
|
||||
"initializers": "An initializer is a controller which enforces some system invariant at object creation time. This field is a list of initializers that have not yet acted on this object. If nil or empty, this object has been completely initialized. Otherwise, the object is considered uninitialized and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to observe uninitialized objects.\n\nWhen an object is created, the system will populate this list with the current set of initializers. Only privileged users may set or modify this list. Once it is empty, it may not be modified further by any user.\n\nDEPRECATED - initializers are an alpha field and will be removed in v1.15.",
|
||||
"finalizers": "Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed.",
|
||||
"clusterName": "The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.",
|
||||
"managedFields": "ManagedFields maps workflow-id and version to the set of fields that are managed by that workflow. This is mostly for internal housekeeping, and users typically shouldn't need to set or understand this field. A workflow can be the user's name, a controller's name, or the name of a specific apply path like \"ci-cd\". The set of fields is always in the version that the workflow used when modifying the object.\n\nThis field is alpha and can be changed or removed without notice.",
|
||||
}
|
||||
|
||||
func (ObjectMeta) SwaggerDoc() map[string]string {
|
||||
@@ -259,6 +281,16 @@ func (Patch) SwaggerDoc() map[string]string {
|
||||
return map_Patch
|
||||
}
|
||||
|
||||
var map_PatchOptions = map[string]string{
|
||||
"": "PatchOptions may be provided when patching an API object. PatchOptions is meant to be a superset of UpdateOptions.",
|
||||
"dryRun": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed",
|
||||
"force": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.",
|
||||
}
|
||||
|
||||
func (PatchOptions) SwaggerDoc() map[string]string {
|
||||
return map_PatchOptions
|
||||
}
|
||||
|
||||
var map_Preconditions = map[string]string{
|
||||
"": "Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.",
|
||||
"uid": "Specifies the target UID.",
|
||||
@@ -337,7 +369,7 @@ func (TypeMeta) SwaggerDoc() map[string]string {
|
||||
}
|
||||
|
||||
var map_UpdateOptions = map[string]string{
|
||||
"": "UpdateOptions may be provided when updating an API object.",
|
||||
"": "UpdateOptions may be provided when updating an API object. All fields in UpdateOptions should also be present in PatchOptions.",
|
||||
"dryRun": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed",
|
||||
}
|
||||
|
||||
|
||||
+48
-2
@@ -143,13 +143,20 @@ func (u *Unstructured) setNestedField(value interface{}, fields ...string) {
|
||||
SetNestedField(u.Object, value, fields...)
|
||||
}
|
||||
|
||||
func (u *Unstructured) setNestedSlice(value []string, fields ...string) {
|
||||
func (u *Unstructured) setNestedStringSlice(value []string, fields ...string) {
|
||||
if u.Object == nil {
|
||||
u.Object = make(map[string]interface{})
|
||||
}
|
||||
SetNestedStringSlice(u.Object, value, fields...)
|
||||
}
|
||||
|
||||
func (u *Unstructured) setNestedSlice(value []interface{}, fields ...string) {
|
||||
if u.Object == nil {
|
||||
u.Object = make(map[string]interface{})
|
||||
}
|
||||
SetNestedSlice(u.Object, value, fields...)
|
||||
}
|
||||
|
||||
func (u *Unstructured) setNestedMap(value map[string]string, fields ...string) {
|
||||
if u.Object == nil {
|
||||
u.Object = make(map[string]interface{})
|
||||
@@ -436,7 +443,7 @@ func (u *Unstructured) SetFinalizers(finalizers []string) {
|
||||
RemoveNestedField(u.Object, "metadata", "finalizers")
|
||||
return
|
||||
}
|
||||
u.setNestedSlice(finalizers, "metadata", "finalizers")
|
||||
u.setNestedStringSlice(finalizers, "metadata", "finalizers")
|
||||
}
|
||||
|
||||
func (u *Unstructured) GetClusterName() string {
|
||||
@@ -450,3 +457,42 @@ func (u *Unstructured) SetClusterName(clusterName string) {
|
||||
}
|
||||
u.setNestedField(clusterName, "metadata", "clusterName")
|
||||
}
|
||||
|
||||
func (u *Unstructured) GetManagedFields() []metav1.ManagedFieldsEntry {
|
||||
items, found, err := NestedSlice(u.Object, "metadata", "managedFields")
|
||||
if !found || err != nil {
|
||||
return nil
|
||||
}
|
||||
managedFields := []metav1.ManagedFieldsEntry{}
|
||||
for _, item := range items {
|
||||
m, ok := item.(map[string]interface{})
|
||||
if !ok {
|
||||
utilruntime.HandleError(fmt.Errorf("unable to retrieve managedFields for object, item %v is not a map", item))
|
||||
return nil
|
||||
}
|
||||
out := metav1.ManagedFieldsEntry{}
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(m, &out); err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("unable to retrieve managedFields for object: %v", err))
|
||||
return nil
|
||||
}
|
||||
managedFields = append(managedFields, out)
|
||||
}
|
||||
return managedFields
|
||||
}
|
||||
|
||||
func (u *Unstructured) SetManagedFields(managedFields []metav1.ManagedFieldsEntry) {
|
||||
if managedFields == nil {
|
||||
RemoveNestedField(u.Object, "metadata", "managedFields")
|
||||
return
|
||||
}
|
||||
items := []interface{}{}
|
||||
for _, managedFieldsEntry := range managedFields {
|
||||
out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&managedFieldsEntry)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("unable to set managedFields for object: %v", err))
|
||||
return
|
||||
}
|
||||
items = append(items, out)
|
||||
}
|
||||
u.setNestedSlice(items, "metadata", "managedFields")
|
||||
}
|
||||
|
||||
+90
@@ -312,6 +312,29 @@ func (in *ExportOptions) DeepCopyObject() runtime.Object {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Fields) DeepCopyInto(out *Fields) {
|
||||
*out = *in
|
||||
if in.Map != nil {
|
||||
in, out := &in.Map, &out.Map
|
||||
*out = make(map[string]Fields, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Fields.
|
||||
func (in *Fields) DeepCopy() *Fields {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Fields)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *GetOptions) DeepCopyInto(out *GetOptions) {
|
||||
*out = *in
|
||||
@@ -624,6 +647,31 @@ func (in *ListOptions) DeepCopyObject() runtime.Object {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ManagedFieldsEntry) DeepCopyInto(out *ManagedFieldsEntry) {
|
||||
*out = *in
|
||||
if in.Time != nil {
|
||||
in, out := &in.Time, &out.Time
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.Fields != nil {
|
||||
in, out := &in.Fields, &out.Fields
|
||||
*out = new(Fields)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedFieldsEntry.
|
||||
func (in *ManagedFieldsEntry) DeepCopy() *ManagedFieldsEntry {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ManagedFieldsEntry)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MicroTime.
|
||||
func (in *MicroTime) DeepCopy() *MicroTime {
|
||||
if in == nil {
|
||||
@@ -678,6 +726,13 @@ func (in *ObjectMeta) DeepCopyInto(out *ObjectMeta) {
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.ManagedFields != nil {
|
||||
in, out := &in.ManagedFields, &out.ManagedFields
|
||||
*out = make([]ManagedFieldsEntry, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -733,6 +788,41 @@ func (in *Patch) DeepCopy() *Patch {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PatchOptions) DeepCopyInto(out *PatchOptions) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
if in.DryRun != nil {
|
||||
in, out := &in.DryRun, &out.DryRun
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Force != nil {
|
||||
in, out := &in.Force, &out.Force
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PatchOptions.
|
||||
func (in *PatchOptions) DeepCopy() *PatchOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PatchOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *PatchOptions) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Preconditions) DeepCopyInto(out *Preconditions) {
|
||||
*out = *in
|
||||
|
||||
+1
@@ -42,6 +42,7 @@ type TypeMeta struct {
|
||||
|
||||
const (
|
||||
ContentTypeJSON string = "application/json"
|
||||
ContentTypeYAML string = "application/yaml"
|
||||
)
|
||||
|
||||
// RawExtension is used to hold extensions in external versions.
|
||||
|
||||
+1
@@ -25,4 +25,5 @@ const (
|
||||
JSONPatchType PatchType = "application/json-patch+json"
|
||||
MergePatchType PatchType = "application/merge-patch+json"
|
||||
StrategicMergePatchType PatchType = "application/strategic-merge-patch+json"
|
||||
ApplyPatchType PatchType = "application/apply-patch+yaml"
|
||||
)
|
||||
|
||||
-2
@@ -217,11 +217,9 @@ func (d *YAMLOrJSONDecoder) Decode(into interface{}) error {
|
||||
if d.decoder == nil {
|
||||
buffer, origData, isJSON := GuessJSONStream(d.r, d.bufferSize)
|
||||
if isJSON {
|
||||
klog.V(4).Infof("decoding stream as JSON")
|
||||
d.decoder = json.NewDecoder(buffer)
|
||||
d.rawData = origData
|
||||
} else {
|
||||
klog.V(4).Infof("decoding stream as YAML")
|
||||
d.decoder = NewYAMLToJSONDecoder(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user