k8s.io/client-go@v0.22.2/applyconfigurations/doc.go (about) 1 /* 2 Copyright The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // Code generated by applyconfiguration-gen. DO NOT EDIT. 18 19 /* 20 Package applyconfigurations provides typesafe go representations of the apply 21 configurations that are used to constructs Server-side Apply requests. 22 23 Basics 24 25 The Apply functions in the typed client (see the k8s.io/client-go/kubernetes/typed packages) offer 26 a direct and typesafe way of calling Server-side Apply. Each Apply function takes an "apply 27 configuration" type as an argument, which is a structured representation of an Apply request. For 28 example: 29 30 import ( 31 ... 32 v1ac "k8s.io/client-go/applyconfigurations/autoscaling/v1" 33 ) 34 hpaApplyConfig := v1ac.HorizontalPodAutoscaler(autoscalerName, ns). 35 WithSpec(v1ac.HorizontalPodAutoscalerSpec(). 36 WithMinReplicas(0) 37 ) 38 return hpav1client.Apply(ctx, hpaApplyConfig, metav1.ApplyOptions{FieldManager: "mycontroller", Force: true}) 39 40 Note in this example that HorizontalPodAutoscaler is imported from an "applyconfigurations" 41 package. Each "apply configuration" type represents the same Kubernetes object kind as the 42 corresponding go struct, but where all fields are pointers to make them optional, allowing apply 43 requests to be accurately represented. For example, this when the apply configuration in the above 44 example is marshalled to YAML, it produces: 45 46 apiVersion: autoscaling/v1 47 kind: HorizontalPodAutoscaler 48 metadata: 49 name: myHPA 50 namespace: myNamespace 51 spec: 52 minReplicas: 0 53 54 To understand why this is needed, the above YAML cannot be produced by the 55 v1.HorizontalPodAutoscaler go struct. Take for example: 56 57 hpa := v1.HorizontalPodAutoscaler{ 58 TypeMeta: metav1.TypeMeta{ 59 APIVersion: "autoscaling/v1", 60 Kind: "HorizontalPodAutoscaler", 61 }, 62 ObjectMeta: ObjectMeta{ 63 Namespace: ns, 64 Name: autoscalerName, 65 }, 66 Spec: v1.HorizontalPodAutoscalerSpec{ 67 MinReplicas: pointer.Int32Ptr(0), 68 }, 69 } 70 71 The above code attempts to declare the same apply configuration as shown in the previous examples, 72 but when marshalled to YAML, produces: 73 74 kind: HorizontalPodAutoscaler 75 apiVersion: autoscaling/v1 76 metadata: 77 name: myHPA 78 namespace: myNamespace 79 creationTimestamp: null 80 spec: 81 scaleTargetRef: 82 kind: "" 83 name: "" 84 minReplicas: 0 85 maxReplicas: 0 86 87 Which, among other things, contains spec.maxReplicas set to 0. This is almost certainly not what 88 the caller intended (the intended apply configuration says nothing about the maxReplicas field), 89 and could have serious consequences on a production system: it directs the autoscaler to downscale 90 to zero pods. The problem here originates from the fact that the go structs contain required fields 91 that are zero valued if not set explicitly. The go structs work as intended for create and update 92 operations, but are fundamentally incompatible with apply, which is why we have introduced the 93 generated "apply configuration" types. 94 95 The "apply configurations" also have convenience With<FieldName> functions that make it easier to 96 build apply requests. This allows developers to set fields without having to deal with the fact that 97 all the fields in the "apply configuration" types are pointers, and are inconvenient to set using 98 go. For example "MinReplicas: &0" is not legal go code, so without the With functions, developers 99 would work around this problem by using a library, .e.g. "MinReplicas: pointer.Int32Ptr(0)", but 100 string enumerations like corev1.Protocol are still a problem since they cannot be supported by a 101 general purpose library. In addition to the convenience, the With functions also isolate 102 developers from the underlying representation, which makes it safer for the underlying 103 representation to be changed to support additional features in the future. 104 105 Controller Support 106 107 The new client-go support makes it much easier to use Server-side Apply in controllers, by either of 108 two mechanisms. 109 110 Mechanism 1: 111 112 When authoring new controllers to use Server-side Apply, a good approach is to have the controller 113 recreate the apply configuration for an object each time it reconciles that object. This ensures 114 that the controller fully reconciles all the fields that it is responsible for. Controllers 115 typically should unconditionally set all the fields they own by setting "Force: true" in the 116 ApplyOptions. Controllers must also provide a FieldManager name that is unique to the 117 reconciliation loop that apply is called from. 118 119 When upgrading existing controllers to use Server-side Apply the same approach often works 120 well--migrate the controllers to recreate the apply configuration each time it reconciles any 121 object. For cases where this does not work well, see Mechanism 2. 122 123 Mechanism 2: 124 125 When upgrading existing controllers to use Server-side Apply, the controller might have multiple 126 code paths that update different parts of an object depending on various conditions. Migrating a 127 controller like this to Server-side Apply can be risky because if the controller forgets to include 128 any fields in an apply configuration that is included in a previous apply request, a field can be 129 accidentally deleted. For such cases, an alternative to mechanism 1 is to replace any controller 130 reconciliation code that performs a "read/modify-in-place/update" (or patch) workflow with a 131 "extract/modify-in-place/apply" workflow. Here's an example of the new workflow: 132 133 fieldMgr := "my-field-manager" 134 deploymentClient := clientset.AppsV1().Deployments("default") 135 // read, could also be read from a shared informer 136 deployment, err := deploymentClient.Get(ctx, "example-deployment", metav1.GetOptions{}) 137 if err != nil { 138 // handle error 139 } 140 // extract 141 deploymentApplyConfig, err := appsv1ac.ExtractDeployment(deployment, fieldMgr) 142 if err != nil { 143 // handle error 144 } 145 // modify-in-place 146 deploymentApplyConfig.Spec.Template.Spec.WithContainers(corev1ac.Container(). 147 WithName("modify-slice"). 148 WithImage("nginx:1.14.2"), 149 ) 150 // apply 151 applied, err := deploymentClient.Apply(ctx, extractedDeployment, metav1.ApplyOptions{FieldManager: fieldMgr}) 152 */ 153 package applyconfigurations