sigs.k8s.io/cluster-api@v1.7.1/cmd/clusterctl/client/rollout.go (about) 1 /* 2 Copyright 2020 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 package client 18 19 import ( 20 "context" 21 "fmt" 22 "strings" 23 24 corev1 "k8s.io/api/core/v1" 25 26 "sigs.k8s.io/cluster-api/cmd/clusterctl/client/cluster" 27 "sigs.k8s.io/cluster-api/cmd/clusterctl/internal/util" 28 ) 29 30 // RolloutRestartOptions carries the options supported by RolloutRestart. 31 type RolloutRestartOptions struct { 32 // Kubeconfig defines the kubeconfig to use for accessing the management cluster. If empty, 33 // default rules for kubeconfig discovery will be used. 34 Kubeconfig Kubeconfig 35 36 // Resources for the rollout command 37 Resources []string 38 39 // Namespace where the resource(s) live. If unspecified, the namespace name will be inferred 40 // from the current configuration. 41 Namespace string 42 } 43 44 // RolloutPauseOptions carries the options supported by RolloutPause. 45 type RolloutPauseOptions struct { 46 // Kubeconfig defines the kubeconfig to use for accessing the management cluster. If empty, 47 // default rules for kubeconfig discovery will be used. 48 Kubeconfig Kubeconfig 49 50 // Resources for the rollout command 51 Resources []string 52 53 // Namespace where the resource(s) live. If unspecified, the namespace name will be inferred 54 // from the current configuration. 55 Namespace string 56 } 57 58 // RolloutResumeOptions carries the options supported by RolloutResume. 59 type RolloutResumeOptions struct { 60 // Kubeconfig defines the kubeconfig to use for accessing the management cluster. If empty, 61 // default rules for kubeconfig discovery will be used. 62 Kubeconfig Kubeconfig 63 64 // Resources for the rollout command 65 Resources []string 66 67 // Namespace where the resource(s) live. If unspecified, the namespace name will be inferred 68 // from the current configuration. 69 Namespace string 70 } 71 72 // RolloutUndoOptions carries the options supported by RolloutUndo. 73 type RolloutUndoOptions struct { 74 // Kubeconfig defines the kubeconfig to use for accessing the management cluster. If empty, 75 // default rules for kubeconfig discovery will be used. 76 Kubeconfig Kubeconfig 77 78 // Resources for the rollout command 79 Resources []string 80 81 // Namespace where the resource(s) live. If unspecified, the namespace name will be inferred 82 // from the current configuration. 83 Namespace string 84 85 // Revision number to rollback to when issuing the undo command. 86 ToRevision int64 87 } 88 89 func (c *clusterctlClient) RolloutRestart(ctx context.Context, options RolloutRestartOptions) error { 90 clusterClient, err := c.clusterClientFactory(ClusterClientFactoryInput{Kubeconfig: options.Kubeconfig}) 91 if err != nil { 92 return err 93 } 94 objRefs, err := getObjectRefs(clusterClient, options.Namespace, options.Resources) 95 if err != nil { 96 return err 97 } 98 for _, ref := range objRefs { 99 if err := c.alphaClient.Rollout().ObjectRestarter(ctx, clusterClient.Proxy(), ref); err != nil { 100 return err 101 } 102 } 103 return nil 104 } 105 106 func (c *clusterctlClient) RolloutPause(ctx context.Context, options RolloutPauseOptions) error { 107 clusterClient, err := c.clusterClientFactory(ClusterClientFactoryInput{Kubeconfig: options.Kubeconfig}) 108 if err != nil { 109 return err 110 } 111 objRefs, err := getObjectRefs(clusterClient, options.Namespace, options.Resources) 112 if err != nil { 113 return err 114 } 115 for _, ref := range objRefs { 116 if err := c.alphaClient.Rollout().ObjectPauser(ctx, clusterClient.Proxy(), ref); err != nil { 117 return err 118 } 119 } 120 return nil 121 } 122 123 func (c *clusterctlClient) RolloutResume(ctx context.Context, options RolloutResumeOptions) error { 124 clusterClient, err := c.clusterClientFactory(ClusterClientFactoryInput{Kubeconfig: options.Kubeconfig}) 125 if err != nil { 126 return err 127 } 128 objRefs, err := getObjectRefs(clusterClient, options.Namespace, options.Resources) 129 if err != nil { 130 return err 131 } 132 for _, ref := range objRefs { 133 if err := c.alphaClient.Rollout().ObjectResumer(ctx, clusterClient.Proxy(), ref); err != nil { 134 return err 135 } 136 } 137 return nil 138 } 139 140 func (c *clusterctlClient) RolloutUndo(ctx context.Context, options RolloutUndoOptions) error { 141 clusterClient, err := c.clusterClientFactory(ClusterClientFactoryInput{Kubeconfig: options.Kubeconfig}) 142 if err != nil { 143 return err 144 } 145 objRefs, err := getObjectRefs(clusterClient, options.Namespace, options.Resources) 146 if err != nil { 147 return err 148 } 149 for _, ref := range objRefs { 150 if err := c.alphaClient.Rollout().ObjectRollbacker(ctx, clusterClient.Proxy(), ref, options.ToRevision); err != nil { 151 return err 152 } 153 } 154 return nil 155 } 156 157 func getObjectRefs(clusterClient cluster.Client, namespace string, resources []string) ([]corev1.ObjectReference, error) { 158 // If the option specifying the Namespace is empty, try to detect it. 159 if namespace == "" { 160 currentNamespace, err := clusterClient.Proxy().CurrentNamespace() 161 if err != nil { 162 return []corev1.ObjectReference{}, err 163 } 164 namespace = currentNamespace 165 } 166 167 if len(resources) == 0 { 168 return []corev1.ObjectReference{}, fmt.Errorf("required resource not specified") 169 } 170 normalized := normalizeResources(resources) 171 objRefs, err := util.GetObjectReferences(namespace, normalized...) 172 if err != nil { 173 return []corev1.ObjectReference{}, err 174 } 175 return objRefs, nil 176 } 177 178 func normalizeResources(input []string) []string { 179 normalized := make([]string, 0, len(input)) 180 for _, in := range input { 181 normalized = append(normalized, strings.ToLower(in)) 182 } 183 return normalized 184 }