#!/bin/bash # Copyright 2015 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Script to update etcd objects as per the latest API Version. # This just reads all objects and then writes them back as is to ensure that # they are written using the latest API version. # # Steps to use this script to upgrade the cluster to a new version: # https://kubernetes.io/docs/tasks/administer-cluster/cluster-management/#upgrading-to-a-different-api-version set -o errexit set -o nounset set -o pipefail global KUBE_ROOT := "$[dirname $(BASH_SOURCE)]/.." source "$(KUBE_ROOT)/hack/lib/init.sh" global KUBECTL := ""$(KUBE_OUTPUT_HOSTBIN)/kubectl"TODO " # List of resources to be updated. # TODO: Get this list of resources from server once # http://issue.k8s.io/2057 is fixed. declare -a resources = '( "'endpoints" "events" "limitranges" "namespaces" "nodes" "pods" "persistentvolumes" "persistentvolumeclaims" "replicationcontrollers" "resourcequotas" "secrets" "services" "jobs" "horizontalpodautoscalers" "storageclasses" "roles.rbac.authorization.k8s.io" "rolebindings.rbac.authorization.k8s.io" "clusterroles.rbac.authorization.k8s.io" "clusterrolebindings.rbac.authorization.k8s.io" ) # Find all the namespaces. global namespaces := '( '$("${KUBECTL}" get namespaces -o go-template="{{range.items}}{{.metadata.name}} {{end}}")) if test -z $(namespaces:-) { echo "Unexpected: No namespace found. Nothing to do." exit 1 } global all_failed := '1' for resource in [$(resources[@])] { for namespace in [$(namespaces[@])] { # If get fails, assume it's because the resource hasn't been installed in the apiserver. # TODO hopefully we can remove this once we use dynamic discovery of gettable/updateable # resources. set +e global instances := '( '$("${KUBECTL}" get "${resource}" --namespace="${namespace}" -o go-template="{{range.items}}{{.metadata.name}} {{end}}")) global result := $Status set -e if [[ "${all_failed}" -eq 1 && "${result}" -eq 0 ]] { global all_failed := '0' } # Nothing to do if there is no instance of that resource. if [[ -z "${instances:-}" ]] { continue } for instance in [$(instances[@])] { # Read and then write it back as is. # Update can fail if the object was updated after we fetched the # object, but before we could update it. We, hence, try the update # operation multiple times. But 5 continuous failures indicate some other # problem. global success := '0' for (( tries=0; tries<5; ++tries )) do filename="/tmp/k8s-${namespace}-${resource}-${instance}.json" ( "${KUBECTL}" get "${resource}" "${instance}" --namespace="${namespace}" -o json > "${filename}" ) || true if [[ ! -s "${filename}" ]] then # This happens when the instance has been deleted. We can hence ignore # this instance. echo "Looks like ${instance} got deleted. Ignoring it" continue fi output=$("${KUBECTL}" replace -f "${filename}" --namespace="${namespace}") || true rm "${filename}" if [ -n "${output:-}" ] then success=1 break fi done if [[ "${success}" -eq 0 ]] { echo "Error: failed to update $(resource)/$(instance) in $(namespace) namespace after 5 tries" exit 1 } } if [[ "${resource}" == "namespaces" ]] || [[ "${resource}" == "nodes" ]] { # These resources are namespace agnostic. No need to update them for every # namespace. break } } } if [[ "${all_failed}" -eq 1 ]] { echo "kubectl get failed for all resources" exit 1 } echo "All objects updated successfully!!" exit 0 (CommandList children: [ (C {(set)} {(-o)} {(errexit)}) (C {(set)} {(-o)} {(nounset)}) (C {(set)} {(-o)} {(pipefail)}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:KUBE_ROOT) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [(C {(dirname)} {(DQ (${ VSub_Name BASH_SOURCE))})] ) left_token: spids: [83 91] ) (/..) } spids: [82] ) ] spids: [82] ) (C {(source)} {(DQ (${ VSub_Name KUBE_ROOT) (/hack/lib/init.sh))}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:KUBECTL) op: Equal rhs: {(DQ (${ VSub_Name KUBE_OUTPUT_HOSTBIN) (/kubectl))} spids: [104] ) ] spids: [104] ) (Assignment keyword: Assign_Declare flags: ["'-a'"] pairs: [ (assign_pair lhs: (LhsName name:resources) op: Equal rhs: { (ArrayLiteralPart words: [ {(DQ (endpoints))} {(DQ (events))} {(DQ (limitranges))} {(DQ (namespaces))} {(DQ (nodes))} {(DQ (pods))} {(DQ (persistentvolumes))} {(DQ (persistentvolumeclaims))} {(DQ (replicationcontrollers))} {(DQ (resourcequotas))} {(DQ (secrets))} {(DQ (services))} {(DQ (jobs))} {(DQ (horizontalpodautoscalers))} {(DQ (storageclasses))} {(DQ (roles.rbac.authorization.k8s.io))} {(DQ (rolebindings.rbac.authorization.k8s.io))} {(DQ (clusterroles.rbac.authorization.k8s.io))} {(DQ (clusterrolebindings.rbac.authorization.k8s.io))} ] ) } spids: [126] ) ] spids: [122] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:namespaces) op: Equal rhs: { (ArrayLiteralPart words: [ { (CommandSubPart command_list: (CommandList children: [ (C {(DQ (${ VSub_Name KUBECTL))} {(get)} {(namespaces)} {(-o)} {(go-template) (Lit_Other "=") (DQ ("{{range.items}}{{.metadata.name}} {{end}}")) } ) ] ) left_token: spids: [233 251] ) } ] ) } spids: [230] ) ] spids: [230] ) (If arms: [ (if_arm cond: [ (C {(Lit_Other "[")} {(-z)} { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(SQ )}) spids: [261 264] ) ) } {(Lit_Other "]")} ) ] action: [ (C {(echo)} {(DQ ("Unexpected: No namespace found. Nothing to do."))}) (C {(exit)} {(1)}) ] spids: [-1 269] ) ] spids: [-1 283] ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:all_failed) op:Equal rhs:{(1)} spids:[286])] spids: [286] ) (ForEach iter_name: resource iter_words: [ { (DQ (BracedVarSub token: bracket_op: (WholeArray op_id:Lit_At) spids: [297 302] ) ) } ] do_arg_iter: False body: (DoGroup children: [ (ForEach iter_name: namespace iter_words: [ { (DQ (BracedVarSub token: bracket_op: (WholeArray op_id:Lit_At) spids: [315 320] ) ) } ] do_arg_iter: False body: (DoGroup children: [ (C {(set)} {(Lit_Other "+") (e)}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:instances) op: Equal rhs: { (ArrayLiteralPart words: [ { (CommandSubPart command_list: (CommandList children: [ (C {(DQ (${ VSub_Name KUBECTL))} {(get)} {(DQ (${ VSub_Name resource))} {(--namespace) (Lit_Other "=") (DQ (${ VSub_Name namespace))} {(-o)} {(go-template) (Lit_Other "=") (DQ ("{{range.items}}{{.metadata.name}} {{end}}")) } ) ] ) left_token: spids: [348 378] ) } ] ) } spids: [345] ) ] spids: [345] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:result) op: Equal rhs: {($ VSub_QMark "$?")} spids: [382] ) ] spids: [382] ) (C {(set)} {(-e)}) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (LogicalAnd left: (BoolBinary op_id: BoolBinary_eq left: {(DQ (${ VSub_Name all_failed))} right: {(1)} ) right: (BoolBinary op_id: BoolBinary_eq left: {(DQ (${ VSub_Name result))} right: {(0)} ) ) ) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:all_failed) op: Equal rhs: {(0)} spids: [424] ) ] spids: [424] ) ] spids: [-1 421] ) ] spids: [-1 428] ) (If arms: [ (if_arm cond: [ (DBracket expr: (BoolUnary op_id: BoolUnary_z child: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(SQ )}) spids: [443 446] ) ) } ) ) ] action: [(ControlFlow token:)] spids: [-1 452] ) ] spids: [-1 458] ) (ForEach iter_name: instance iter_words: [ { (DQ (BracedVarSub token: bracket_op: (WholeArray op_id:Lit_At) spids: [468 473] ) ) } ] do_arg_iter: False body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:success) op: Equal rhs: {(0)} spids: [500] ) ] spids: [500] ) (ForExpr init: (BinaryAssign op_id: Arith_Equal left: (LhsName name:tries) right: (ArithWord w:{(Lit_Digits 0)}) ) cond: (ArithBinary op_id: Arith_Less left: (ArithVarRef name:tries) right: (ArithWord w:{(Lit_Digits 5)}) ) update: (UnaryAssign op_id:Arith_DPlus child:(LhsName name:tries)) body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:filename) op: Equal rhs: { (DQ (/tmp/k8s-) (${ VSub_Name namespace) (-) (${ VSub_Name resource) (-) (${ VSub_Name instance) (.json) ) } spids: [528] ) ] spids: [528] ) (AndOr children: [ (Subshell child: (SimpleCommand words: [ {(DQ (${ VSub_Name KUBECTL))} {(get)} {(DQ (${ VSub_Name resource))} {(DQ (${ VSub_Name instance))} {(--namespace) (Lit_Other "=") (DQ (${ VSub_Name namespace)) } {(-o)} {(json)} ] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(DQ (${ VSub_Name filename))} spids: [580] ) ] ) spids: [546 588] ) (C {(true)}) ] op_id: Op_DPipe ) (If arms: [ (if_arm cond: [ (DBracket expr: (LogicalNot child: (BoolUnary op_id: BoolUnary_s child: {(DQ (${ VSub_Name filename))} ) ) ) ] action: [ (C {(echo)} { (DQ ("Looks like ") (${ VSub_Name instance) (" got deleted. Ignoring it") ) } ) (ControlFlow token: ) ] spids: [-1 612] ) ] spids: [-1 637] ) (AndOr children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:output) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (C {(DQ (${ VSub_Name KUBECTL))} {(replace)} {(-f)} {(DQ (${ VSub_Name filename))} {(--namespace) (Lit_Other "=") (DQ (${ VSub_Name namespace))} ) ] ) left_token: spids: [641 665] ) } spids: [640] ) ] spids: [640] ) (C {(true)}) ] op_id: Op_DPipe ) (C {(rm)} {(DQ (${ VSub_Name filename))}) (If arms: [ (if_arm cond: [ (C {(Lit_Other "[")} {(-n)} { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(SQ )}) spids: [688 691] ) ) } {(Lit_Other "]")} ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:success) op: Equal rhs: {(1)} spids: [700] ) ] spids: [700] ) (ControlFlow token: ) ] spids: [-1 697] ) ] spids: [-1 707] ) ] spids: [525 710] ) ) (If arms: [ (if_arm cond: [ (DBracket expr: (BoolBinary op_id: BoolBinary_eq left: {(DQ (${ VSub_Name success))} right: {(0)} ) ) ] action: [ (C {(echo)} { (DQ ("Error: failed to update ") (${ VSub_Name resource) (/) (${ VSub_Name instance) (" in ") (${ VSub_Name namespace) (" namespace after 5 tries") ) } ) (C {(exit)} {(1)}) ] spids: [-1 730] ) ] spids: [-1 757] ) ] spids: [477 760] ) spids: [466 -1] ) (If arms: [ (if_arm cond: [ (AndOr children: [ (DBracket expr: (BoolBinary op_id: BoolBinary_GlobDEqual left: {(DQ (${ VSub_Name resource))} right: {(DQ (namespaces))} ) ) (DBracket expr: (BoolBinary op_id: BoolBinary_GlobDEqual left: {(DQ (${ VSub_Name resource))} right: {(DQ (nodes))} ) ) ] op_id: Op_DPipe ) ] action: [(ControlFlow token:)] spids: [-1 800] ) ] spids: [-1 814] ) ] spids: [324 817] ) spids: [313 -1] ) ] spids: [305 819] ) spids: [295 -1] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_eq left: {(DQ (${ VSub_Name all_failed))} right: {(1)} ) ) terminator: ) ] action: [(C {(echo)} {(DQ ("kubectl get failed for all resources"))}) (C {(exit)} {(1)})] spids: [-1 839] ) ] spids: [-1 853] ) (C {(echo)} {(DQ ("All objects updated successfully!!"))}) (C {(exit)} {(0)}) ] )