github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/e2e/live/end-to-end-test.sh (about)

     1  #!/usr/bin/env bash
     2  ###########################################################################
     3  # Copyright 2020 Google LLC
     4  #
     5  # Licensed under the Apache License, Version 2.0 (the "License");
     6  # you may not use this file except in compliance with the License.
     7  # You may obtain a copy of the License at
     8  #
     9  #      http://www.apache.org/licenses/LICENSE-2.0
    10  #
    11  # Unless required by applicable law or agreed to in writing, software
    12  # distributed under the License is distributed on an "AS IS" BASIS,
    13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  # See the License for the specific language governing permissions and
    15  # limitations under the License.
    16  #
    17  # Description:
    18  #   Validates multiple scenarios for kpt live commands.
    19  #
    20  # How to use this script:
    21  #   FROM KPT ROOT DIR: ./e2e/live/end-to-end-test.sh
    22  #
    23  # Example KPT ROOT DIR:
    24  #   ~/go/src/github.com/GoogleContainerTools/kpt
    25  #
    26  # Flags:
    27  #   -b) Build the kpt binary with dependencies at HEAD. Downloads HEAD
    28  #       for cli-utils and kustomize repositories, and builds kpt using
    29  #       these downloaded repositories.
    30  #   -k) Run against this Kubernetes version. Creates a local Kubernetes
    31  #       cluster at this version using "kind". Only accepts MAJOR.MINOR.
    32  #       Example: 1.17. This is translated to a patch version. Example:
    33  #       1.17 runs version 1.17.11.
    34  #
    35  # Prerequisites (must be in $PATH):
    36  #   kind - Kubernetes in Docker
    37  #   kubectl - version of kubectl should be within +/- 1 version of cluster.
    38  #     CHECK: $ kubectl version
    39  #
    40  # Examples:
    41  #   $ ./e2e/live/end-to-end-test.sh -b
    42  #   $ ./e2e/live/end-to-end-test.sh -k 1.17
    43  #   $ ./e2e/live/end-to-end-test.sh -bk 1.17
    44  #
    45  ###########################################################################
    46  
    47  # TODO
    48  #  1) Validate prerequisites (e.g. kind, kubectl)
    49  #  2) Refactor helper functions into another file
    50  #  3) Fix -k <UNKNOWN K8S VERSION>
    51  #  4) Add "-v" verbosity level flags
    52  #  5) Count the test cases and print it out
    53  #  6) Print timing for the tests
    54  
    55  
    56  ###########################################################################
    57  #  Parameters/args
    58  ###########################################################################
    59  
    60  # A POSIX variable; reset in case getopts has been used previously in the shell.
    61  OPTIND=1
    62  
    63  # Kind/Kubernetes versions.
    64  KIND_1_24_VERSION=1.24.0
    65  KIND_1_23_VERSION=1.23.6
    66  KIND_1_22_VERSION=1.22.9
    67  KIND_1_21_VERSION=1.21.12
    68  KIND_1_20_VERSION=1.20.15
    69  KIND_1_19_VERSION=1.19.16
    70  KIND_1_18_VERSION=1.18.20
    71  KIND_1_17_VERSION=1.17.17
    72  KIND_1_16_VERSION=1.16.15
    73  DEFAULT_K8S_VERSION=${KIND_1_21_VERSION}
    74  
    75  # Change from empty string to build the kpt binary from the downloaded
    76  # repositories at HEAD, including dependencies cli-utils and kustomize.
    77  BUILD_DEPS_AT_HEAD=""
    78  
    79  # Default Kubernetes cluster version to run test against.
    80  K8S_VERSION=${DEFAULT_K8S_VERSION}
    81  
    82  HAS_TEST_FAILURE=0
    83  
    84  # Parse/validate parameters
    85  options="bk:"
    86  while getopts $options opt; do
    87      case "$opt" in
    88  	b)  BUILD_DEPS_AT_HEAD=1;;
    89  	k)  short_version=$OPTARG
    90  	    case "$short_version" in
    91  		1.16) K8S_VERSION=$KIND_1_16_VERSION
    92  		      ;;
    93  		1.17) K8S_VERSION=$KIND_1_17_VERSION
    94  		      ;;
    95  		1.18) K8S_VERSION=$KIND_1_18_VERSION
    96  		      ;;
    97  		1.19) K8S_VERSION=$KIND_1_19_VERSION
    98  		      ;;
    99  		1.20) K8S_VERSION=$KIND_1_20_VERSION
   100  		      ;;
   101  		1.21) K8S_VERSION=$KIND_1_21_VERSION
   102  		      ;;
   103  		1.22) K8S_VERSION=$KIND_1_22_VERSION
   104  		      ;;
   105  		1.23) K8S_VERSION=$KIND_1_23_VERSION
   106  		      ;;
   107  		1.24) K8S_VERSION=$KIND_1_24_VERSION
   108  		      ;;
   109          *) K8S_VERSION=$short_version
   110  		      ;;
   111  	    esac
   112  	    ;;
   113  	\? ) echo "Usage: $0 [-b] [-k k8s-version]" >&2; exit 1;;
   114      esac
   115  done
   116  
   117  shift $((OPTIND-1))
   118  
   119  [ "${1:-}" = "--" ] && shift
   120  
   121  ###########################################################################
   122  #  Colors
   123  ###########################################################################
   124  
   125  GREEN='\033[0;32m'
   126  RED='\033[0;31m'
   127  NC='\033[0m' # No Color
   128  
   129  ###########################################################################
   130  #  Helper functions
   131  ###########################################################################
   132  
   133  function downloadPreviousKpt {
   134    set -e
   135    KPT_VERSION=0.39.2
   136    echo "Downloading v${KPT_VERSION} kpt binary..."
   137    uname="$(uname -s)"
   138    if [[ "$uname" == "Linux" ]]
   139    then
   140      echo "Running on Linux"
   141      curl -LJ -o kpt.tar.gz https://github.com/GoogleContainerTools/kpt/releases/download/v${KPT_VERSION}/kpt_linux_amd64-${KPT_VERSION}.tar.gz > $OUTPUT_DIR/kptdownload 2>&1
   142    elif [[ "$uname" == "Darwin" ]]
   143    then
   144      echo "Running on Darwin"
   145      curl -LJ -o kpt.tar.gz https://github.com/GoogleContainerTools/kpt/releases/download/v${KPT_VERSION}/kpt_darwin_amd64-${KPT_VERSION}.tar.gz > $OUTPUT_DIR/kptdownload 2>&1
   146    else
   147      echo -e "${RED}ERROR${NC}: Unknown OS $uname"
   148      exit 1
   149    fi
   150    tar -xvf kpt.tar.gz > $OUTPUT_DIR/kptdownload 2>&1
   151    mv kpt $BIN_DIR/previouskpt
   152    echo -e "Downloading previous kpt binary...${GREEN}SUCCESS${NC}"
   153    rm kpt.tar.gz LICENSES.txt lib.zip
   154    set +e
   155  }
   156  
   157  function downloadKpt1.0 {
   158    set -e
   159    KPT_VERSION=1.0.0-beta.13
   160    echo "Downloading v${KPT_VERSION} kpt binary..."
   161    uname="$(uname -s)"
   162    if [[ "$uname" == "Linux" ]]
   163    then
   164      echo "Running on Linux"
   165      curl -LJ -o kpt.tar.gz https://github.com/GoogleContainerTools/kpt/releases/download/v${KPT_VERSION}/kpt_linux_amd64-${KPT_VERSION}.tar.gz > $OUTPUT_DIR/kptdownload 2>&1
   166    elif [[ "$uname" == "Darwin" ]]
   167    then
   168      echo "Running on Darwin"
   169        curl -LJ -o kpt.tar.gz https://github.com/GoogleContainerTools/kpt/releases/download/v${KPT_VERSION}/kpt_darwin_amd64-${KPT_VERSION}.tar.gz > $OUTPUT_DIR/kptdownload 2>&1
   170      else
   171        echo -e "${RED}ERROR${NC}: Unknown OS $uname"
   172        exit 1
   173    fi
   174    tar -xvf kpt.tar.gz > $OUTPUT_DIR/kptdownload 2>&1
   175    mv kpt $BIN_DIR/kpt1.0.0
   176    echo -e "Downloading 1.0.0 kpt binary...${GREEN}SUCCESS${NC}"
   177    rm kpt.tar.gz LICENSES.txt lib.zip
   178    set +e
   179  }
   180  
   181  # buildKpt builds the kpt binary, storing it in the temporary directory.
   182  # To check the stdout output of the build check $OUTPUT_DIR/kptbuild.
   183  # stderr output will be output to the terminal.
   184  function buildKpt {
   185      set -e
   186      if [ -z $BUILD_DEPS_AT_HEAD ]; then
   187  	echo "checking go version"
   188  	go version
   189  	echo "Building kpt locally..."
   190  	go build -o $BIN_DIR -v . > $OUTPUT_DIR/kptbuild 2>&1
   191  	echo -e "Building kpt locally...${GREEN}SUCCESS${NC}"
   192  
   193      else
   194  	echo "Building kpt using dependencies at HEAD..."
   195  	echo
   196  	# Clone kpt repository into kpt source directory
   197  	KPT_SRC_DIR="${SRC_DIR}/github.com/GoogleContainerTools/kpt"
   198  	mkdir -p $KPT_SRC_DIR
   199  	echo "Downloading kpt repository at HEAD..."
   200  	git clone https://github.com/GoogleContainerTools/kpt ${KPT_SRC_DIR} > ${OUTPUT_DIR}/kptbuild 2>&1
   201  	echo -e "Downloading kpt repository at HEAD...${GREEN}SUCCESS${NC}"
   202  	# Clone cli-utils repository into source directory
   203  	CLI_UTILS_SRC_DIR="${SRC_DIR}/sigs.k8s.io/cli-utils"
   204  	mkdir -p $CLI_UTILS_SRC_DIR
   205  	echo "Downloading cli-utils repository at HEAD..."
   206  	git clone https://github.com/kubernetes-sigs/cli-utils ${CLI_UTILS_SRC_DIR} > ${OUTPUT_DIR}/kptbuild 2>&1
   207  	echo -e "Downloading cli-utils repository at HEAD...${GREEN}SUCCESS${NC}"
   208  	# Clone kustomize respository into source directory
   209  	KUSTOMIZE_SRC_DIR="${SRC_DIR}/sigs.k8s.io/kustomize"
   210  	mkdir -p $KUSTOMIZE_SRC_DIR
   211  	echo "Downloading kustomize repository at HEAD..."
   212  	git clone https://github.com/kubernetes-sigs/kustomize ${KUSTOMIZE_SRC_DIR} > ${OUTPUT_DIR}/kptbuild 2>&1
   213  	echo -e "Downloading kustomize repository at HEAD...${GREEN}SUCCESS${NC}"
   214  	# Tell kpt to build using the locally downloaded dependencies
   215  	echo "Updating kpt/go.mod to reference locally downloaded repositories..."
   216  	echo -e "\n\nreplace sigs.k8s.io/cli-utils => ../../../sigs.k8s.io/cli-utils" >> ${KPT_SRC_DIR}/go.mod
   217  	echo -e "replace sigs.k8s.io/kustomize/cmd/config => ../../../sigs.k8s.io/kustomize/cmd/config" >> ${KPT_SRC_DIR}/go.mod
   218  	echo -e "replace sigs.k8s.io/kustomize/kyaml => ../../../sigs.k8s.io/kustomize/kyaml\n" >> ${KPT_SRC_DIR}/go.mod
   219  	echo -e "Updating kpt/go.mod to reference locally downloaded repositories...${GREEN}SUCCESS${NC}"
   220  	# Build kpt using the cloned directories
   221  	export GOPATH=${TMP_DIR}
   222  	echo "Building kpt..."
   223  	(cd -- ${KPT_SRC_DIR} && go build -o $BIN_DIR -v . > ${OUTPUT_DIR}/kptbuild)
   224  	echo -e "Building kpt...${GREEN}SUCCESS${NC}"
   225  	echo
   226  	echo -e "Building kpt using dependencies at HEAD...${GREEN}SUCCESS${NC}"
   227      fi
   228      set +e
   229  }
   230  
   231  # createTestSuite deletes then creates the kind cluster. We wait for the node
   232  # to become ready before we run the tests.
   233  function createTestSuite {
   234      set -e
   235      echo "Setting Up Test Suite..."
   236      echo
   237      # Create the k8s cluster
   238      echo "Deleting kind cluster..."
   239      kind delete cluster > /dev/null 2>&1
   240      echo -e "Deleting kind cluster...${GREEN}SUCCESS${NC}"
   241      echo "Creating kind cluster..."
   242      kind create cluster --image=kindest/node:v${K8S_VERSION} --wait=2m > $OUTPUT_DIR/k8sstartup 2>&1
   243      kubectl wait node/kind-control-plane --for condition=ready --timeout=2m
   244      echo -e "Creating kind cluster...${GREEN}SUCCESS${NC}"
   245      echo
   246      echo -e "Setting Up Test Suite...${GREEN}SUCCESS${NC}"
   247      echo
   248      set +e
   249  }
   250  
   251  function waitForDefaultServiceAccount {
   252      # Necessary to ensure default service account is created before pods.
   253      echo -n "Waiting for default service account..."
   254      echo -n ' '
   255      sp="/-\|"
   256      n=1
   257      until ((n >= 300)); do
   258  	kubectl -n default get serviceaccount default -o name 2>&1 | tee $OUTPUT_DIR/status
   259  	test 1 == $(grep "serviceaccount/default" $OUTPUT_DIR/status | wc -l)
   260  	if [ $? == 0 ]; then
   261  	    echo
   262  	    break
   263  	fi
   264  	printf "\b${sp:n++%${#sp}:1}"
   265  	sleep 0.2
   266      done
   267      ((n < 300))
   268      echo "Waiting for default service account...CREATED"
   269      echo
   270  }
   271  
   272  # assertKptLiveApplyEquals checks that the STDIN equals the content of the
   273  # $OUTPUT_DIR/status file, after filtering and sorting.
   274  function assertKptLiveApplyEquals {
   275    local expected="$(cat | processKptLiveOutput)"
   276    local received="$(cat "$OUTPUT_DIR/status" | processKptLiveOutput)"
   277    local diff_result="$( diff -u <(echo -e "${expected}") <(echo -e "${received}") --label "expected" --label "received")"
   278    if [[ -z "${diff_result}" ]]; then
   279      echo -n '.'
   280    else
   281      echo -n 'E'
   282      echo -e "error: expected output ():\n${diff_result}" >> "$OUTPUT_DIR/errors"
   283      HAS_TEST_FAILURE=1
   284    fi
   285  }
   286  
   287  function processKptLiveOutput {
   288      trimTrailingNewlines | \
   289      filterReconcilePending | \
   290      sortReconcileEvents | \
   291      sortActuationEvents
   292  }
   293  
   294  function trimTrailingNewlines {
   295      sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'
   296  }
   297  
   298  function filterReconcilePending {
   299    grep -v " reconcile pending$" || true
   300  }
   301  
   302  # sortReconcileEvents sorts reconcile events: successful > failed.
   303  # Not sorted: skipped (always first) & timeout (always last).
   304  function sortReconcileEvents {
   305    local input="$(cat)" # read full input before sorting
   306    local status=""
   307    local successfulBuffer=""
   308    local failedBuffer=""
   309    local pattern="^.* reconcile (successful|failed).*$"
   310    while IFS="" read -r line; do
   311      if [[ "${line}" =~ ${pattern} ]]; then
   312        # match - add line to buffer
   313        status="${BASH_REMATCH[1]}"
   314        if [[ "${status}" == "successful" ]]; then
   315          successfulBuffer+="${line}\n"
   316        elif [[ "${status}" == "failed" ]]; then
   317          failedBuffer+="${line}\n"
   318        else
   319          echo "ERROR: Unexpected reconcile status: ${status}"
   320          return
   321        fi
   322      else
   323        # no match - dump buffers & print line
   324        if [[ -n "${successfulBuffer}" ]]; then
   325          echo -en "${successfulBuffer}" | sort
   326          successfulBuffer=""
   327        fi
   328        if [[ -n "${failedBuffer}" ]]; then
   329          echo -en "${failedBuffer}" | sort
   330          failedBuffer=""
   331        fi
   332        echo "${line}"
   333      fi
   334    done <<< "${input}"
   335    # end of input - dump buffers
   336    if [[ -n "${successfulBuffer}" ]]; then
   337      echo -en "${successfulBuffer}" | sort
   338      successfulBuffer=""
   339    fi
   340    if [[ -n "${failedBuffer}" ]]; then
   341      echo -en "${failedBuffer}" | sort
   342      failedBuffer=""
   343    fi
   344  }
   345  
   346  # sortActuationEvents sorts apply/prune/delete events: skipped > successful > failed.
   347  # Only events with the same actuation type and resource type are sorted.
   348  function sortActuationEvents {
   349    local input="$(cat)" # read full input before sorting
   350    local status=""
   351    local resource=""
   352    local actuation=""
   353    local skippedBuffer=""
   354    local successfulBuffer=""
   355    local failedBuffer=""
   356    local pattern="^(.*)/(.*) (apply|prune|delete) (skipped|successful|failed).*$"
   357    while IFS="" read -r line; do
   358      if [[ "${line}" =~ ${pattern} ]]; then
   359        # match
   360        if [[ "${resource}" != "${BASH_REMATCH[1]}" ]] || [[ "${actuation}" != "${BASH_REMATCH[3]}" ]]; then
   361          # different resource/actuation - dump buffers & update resource/actuation
   362          if [[ -n "${skippedBuffer}" ]]; then
   363            echo -en "${skippedBuffer}" | sort
   364            skippedBuffer=""
   365          fi
   366          if [[ -n "${successfulBuffer}" ]]; then
   367            echo -en "${successfulBuffer}" | sort
   368            successfulBuffer=""
   369          fi
   370          if [[ -n "${failedBuffer}" ]]; then
   371            echo -en "${failedBuffer}" | sort
   372            failedBuffer=""
   373          fi
   374          resource="${BASH_REMATCH[1]}"
   375          actuation="${BASH_REMATCH[3]}"
   376        fi
   377  
   378        # add line to buffer
   379        status="${BASH_REMATCH[4]}"
   380        if [[ "${status}" == "skipped" ]]; then
   381          skippedBuffer+="${line}\n"
   382        elif [[ "${status}" == "successful" ]]; then
   383          successfulBuffer+="${line}\n"
   384        elif [[ "${status}" == "failed" ]]; then
   385          failedBuffer+="${line}\n"
   386        else
   387          echo "ERROR: Unexpected ${actuation} status: ${status}"
   388          return
   389        fi
   390      else
   391        # no match - dump buffers & print line
   392        if [[ -n "${skippedBuffer}" ]]; then
   393          echo -en "${skippedBuffer}" | sort
   394          skippedBuffer=""
   395        fi
   396        if [[ -n "${successfulBuffer}" ]]; then
   397          echo -en "${successfulBuffer}" | sort
   398          successfulBuffer=""
   399        fi
   400        if [[ -n "${failedBuffer}" ]]; then
   401          echo -en "${failedBuffer}" | sort
   402          failedBuffer=""
   403        fi
   404        echo "${line}"
   405        resource=""
   406        actuation=""
   407      fi
   408    done <<< "${input}"
   409    # end of input - dump buffers
   410    if [[ -n "${skippedBuffer}" ]]; then
   411      echo -en "${skippedBuffer}" | sort
   412      skippedBuffer=""
   413    fi
   414    if [[ -n "${successfulBuffer}" ]]; then
   415      echo -en "${successfulBuffer}" | sort
   416      successfulBuffer=""
   417    fi
   418    if [[ -n "${failedBuffer}" ]]; then
   419      echo -en "${failedBuffer}" | sort
   420      failedBuffer=""
   421    fi
   422  }
   423  
   424  # assertContains checks that the passed string is a substring of
   425  # the $OUTPUT_DIR/status file.
   426  function assertContains {
   427    local test_arg="$@"
   428    test 1 == \
   429    $(grep "$test_arg" $OUTPUT_DIR/status | wc -l); \
   430    if [ $? == 0 ]; then
   431        echo -n '.'
   432    else
   433        echo -n 'E'
   434        if [ ! -f $OUTPUT_DIR/errors ]; then
   435  	  touch $OUTPUT_DIR/errors
   436        fi
   437        echo "error: expected missing text \"${test_arg}\"" >> $OUTPUT_DIR/errors
   438        HAS_TEST_FAILURE=1
   439    fi
   440  }
   441  
   442  # assertNotContains checks that the passed string is NOT a substring of
   443  # the $OUTPUT_DIR/status file.
   444  function assertNotContains {
   445    local test_arg="$@"
   446    test 0 == \
   447    $(grep "$test_arg" $OUTPUT_DIR/status | wc -l); \
   448    if [ $? == 0 ]; then
   449        echo -n '.'
   450    else
   451        echo -n 'E'
   452        if [ ! -f $OUTPUT_DIR/errors ]; then
   453  	  touch $OUTPUT_DIR/errors
   454        fi
   455        echo "error: unexpected text \"${test_arg}\" found" >> $OUTPUT_DIR/errors
   456        HAS_TEST_FAILURE=1
   457    fi
   458  }
   459  
   460  # assertCMInventory checks that a ConfigMap inventory object exists in
   461  # the passed namespace with the passed number of inventory items.
   462  # Assumes the inventory object name begins with "inventory-".
   463  function assertCMInventory {
   464      local ns=$1
   465      local numInv=$2
   466      
   467      echo "kubectl get cm -n $ns --selector='cli-utils.sigs.k8s.io/inventory-id' --no-headers"
   468      inv=$(kubectl get cm -n $ns --selector='cli-utils.sigs.k8s.io/inventory-id' --no-headers)
   469      echo $inv | awk '{print $1}' > $OUTPUT_DIR/invname
   470      echo $inv | awk '{print $2}' > $OUTPUT_DIR/numinv
   471  
   472      test 1 == $(grep "inventory-" $OUTPUT_DIR/invname | wc -l);
   473      if [ $? == 0 ]; then
   474  	echo -n '.'
   475      else
   476  	echo -n 'E'
   477  	if [ ! -f $OUTPUT_DIR/errors ]; then
   478  	    touch $OUTPUT_DIR/errors
   479  	fi
   480  	echo "error: expected missing ConfigMap inventory object in ${ns} namespace" >> $OUTPUT_DIR/errors
   481      HAS_TEST_FAILURE=1
   482      fi
   483  
   484      test 1 == $(grep $numInv $OUTPUT_DIR/numinv | wc -l);
   485      if [ $? == 0 ]; then
   486  	echo -n '.'
   487      else
   488  	echo -n 'E'
   489  	if [ ! -f $OUTPUT_DIR/errors ]; then
   490  	    touch $OUTPUT_DIR/errors
   491  	fi
   492  	echo "error: expected ConfigMap inventory to have $numInv inventory items" >> $OUTPUT_DIR/errors
   493      HAS_TEST_FAILURE=1
   494      fi
   495  }
   496  
   497  # assertRGInventory checks that a ResourceGroup inventory object exists
   498  # in the passed namespace. Assumes the inventory object name begins
   499  # with "inventory-".
   500  function assertRGInventory {
   501      local ns=$1
   502      
   503      echo "kubectl get resourcegroups.kpt.dev -n $ns --selector='cli-utils.sigs.k8s.io/inventory-id' --no-headers | awk '{print $1}'"
   504      kubectl get resourcegroups.kpt.dev -n $ns --selector='cli-utils.sigs.k8s.io/inventory-id' --no-headers | awk '{print $1}' > $OUTPUT_DIR/invname
   505  
   506      test 1 == $(grep "inventory-" $OUTPUT_DIR/invname | wc -l);
   507      if [ $? == 0 ]; then
   508  	echo -n '.'
   509      else
   510  	echo -n 'E'
   511  	if [ ! -f $OUTPUT_DIR/errors ]; then
   512  	    touch $OUTPUT_DIR/errors
   513  	fi
   514  	echo "error: expected missing ResourceGroup inventory in ${ns} namespace" >> $OUTPUT_DIR/errors
   515      HAS_TEST_FAILURE=1
   516      fi
   517  }
   518  
   519  # assertPodExists checks that a pod with the passed podName and passed
   520  # namespace exists in the cluster.
   521  TIMEOUT_SECS=30
   522  function assertPodExists {
   523      local podName=$1
   524      local namespace=$2
   525  
   526      echo "kubectl wait --for=condition=Ready -n $namespace pod/$podName --timeout=${TIMEOUT_SECS}s"
   527      kubectl wait --for=condition=Ready -n $namespace pod/$podName --timeout=${TIMEOUT_SECS}s > /dev/null 2>&1
   528      echo "kubectl get po -n $namespace $podName -o name | awk '{print $1}'"
   529      kubectl get po -n $namespace $podName -o name | awk '{print $1}' > $OUTPUT_DIR/podname
   530  
   531      test 1 == $(grep $podName $OUTPUT_DIR/podname | wc -l);
   532      if [ $? == 0 ]; then
   533  	echo -n '.'
   534      else
   535  	echo -n 'E'
   536  	if [ ! -f $OUTPUT_DIR/errors ]; then
   537  	    touch $OUTPUT_DIR/errors
   538  	fi
   539  	echo "error: expected missing pod $namespace/$podName in ${namespace} namespace" >> $OUTPUT_DIR/errors
   540      HAS_TEST_FAILURE=1
   541      fi
   542  }
   543  
   544  # assertPodNotExists checks that a pod with the passed podName and passed
   545  # namespace DOES NOT exist in the cluster. Waits 20 seconds for pod
   546  # termination if pod has not finished deleting.
   547  function assertPodNotExists {
   548      local podName=$1
   549      local namespace=$2
   550  
   551      echo "kubectl wait --for=delete -n $namespace pod/$podName --timeout=${TIMEOUT_SECS}s"
   552      kubectl wait --for=delete -n $namespace pod/$podName --timeout=${TIMEOUT_SECS}s > /dev/null 2>&1
   553      echo "kubectl get po -n $namespace $podName -o name"
   554      kubectl get po -n $namespace $podName -o name > $OUTPUT_DIR/podname 2>&1
   555      
   556      test 1 == $(grep "(NotFound)" $OUTPUT_DIR/podname | wc -l);
   557      if [ $? == 0 ]; then
   558  	echo -n '.'
   559      else
   560  	echo -n 'E'
   561  	if [ ! -f $OUTPUT_DIR/errors ]; then
   562  	    touch $OUTPUT_DIR/errors
   563  	fi
   564  	echo "error: unexpected pod $namespace/$podName found in ${namespace} namespace" >> $OUTPUT_DIR/errors
   565      HAS_TEST_FAILURE=1
   566      fi
   567  }
   568  
   569  # printResult prints the results of the previous assert statements
   570  function printResult {
   571      if [ -f $OUTPUT_DIR/errors ]; then
   572  	echo -e "${RED}ERROR${NC}"
   573  	cat $OUTPUT_DIR/errors
   574  	echo
   575  	rm -f $OUTPUT_DIR/errors
   576      else
   577  	echo -e "${GREEN}SUCCESS${NC}"
   578      fi
   579      echo
   580  }
   581  
   582  # wait sleeps for the passed number of seconds.
   583  function wait {
   584      local numSecs=$1
   585  
   586      sleep $numSecs
   587  }
   588  
   589  SEMVER_PATTERN="v(.*)\.(.*)\.(.*)"
   590  
   591  function kubeServerVersion {
   592    kubectl version --output=json | jq -r '.serverVersion.gitVersion'
   593  }
   594  
   595  function kubeServerMinorVersion {
   596    if [[ "$(kubeServerVersion)" =~ ${SEMVER_PATTERN} ]]; then
   597      echo "${BASH_REMATCH[2]}"
   598    else
   599      return 1
   600    fi
   601  }
   602  
   603  ###########################################################################
   604  #  Main
   605  ###########################################################################
   606  
   607  # Setup temporary directory for src, bin, and output.
   608  TMP_DIR=$(mktemp -d -t kpt-e2e-XXXXXXXXXX)
   609  SRC_DIR="${TMP_DIR}/src"
   610  mkdir -p $SRC_DIR
   611  BIN_DIR="${TMP_DIR}/bin"
   612  mkdir -p ${BIN_DIR}
   613  OUTPUT_DIR="${TMP_DIR}/output"
   614  mkdir -p $OUTPUT_DIR
   615  
   616  # Build the kpt binary and copy it to the temp dir. If BUILD_DEPS_AT_HEAD
   617  # is set, then copy the kpt repository AND dependency directories into
   618  # TMP_DIR and build from there.
   619  echo "kpt end-to-end test"
   620  echo
   621  echo "Kubernetes Version: ${K8S_VERSION}"
   622  echo "Temp Dir: $TMP_DIR"
   623  echo
   624  
   625  buildKpt
   626  
   627  downloadPreviousKpt
   628  downloadKpt1.0
   629  
   630  echo
   631  set +e                          # Do not stop the test for errors
   632  
   633  #############################################################
   634  #  Tests without initial ResourceGroup inventory installation
   635  #############################################################
   636  
   637  createTestSuite
   638  waitForDefaultServiceAccount
   639  
   640  # Basic init as setup for follow-on tests
   641  # Test: Apply dry-run without ResourceGroup CRD installation fails
   642  echo "[ResourceGroup] Testing initial apply dry-run without ResourceGroup inventory CRD"
   643  cp -f e2e/live/testdata/Kptfile e2e/live/testdata/rg-test-case-1a/
   644  echo "kpt live init --quiet e2e/live/testdata/rg-test-case-1a"
   645  ${BIN_DIR}/kpt live init --quiet e2e/live/testdata/rg-test-case-1a
   646  echo "kpt live apply --dry-run e2e/live/testdata/rg-test-case-1a"
   647  ${BIN_DIR}/kpt live apply --dry-run e2e/live/testdata/rg-test-case-1a 2>&1 | tee $OUTPUT_DIR/status
   648  assertContains "Error: The ResourceGroup CRD was not found in the cluster. Please install it either by using the '--install-resource-group' flag or the 'kpt live install-resource-group' command."
   649  printResult
   650  
   651  # Test: Apply installs ResourceGroup CRD
   652  echo "[ResourceGroup] Testing create inventory CRD before basic apply"
   653  echo "kpt live apply e2e/live/testdata/rg-test-case-1a"
   654  ${BIN_DIR}/kpt live apply e2e/live/testdata/rg-test-case-1a 2>&1 | tee $OUTPUT_DIR/status
   655  # The ResourceGroup inventory CRD is automatically installed on the initial apply.
   656  assertKptLiveApplyEquals << EOF
   657  installing inventory ResourceGroup CRD.
   658  inventory update started
   659  inventory update finished
   660  apply phase started
   661  namespace/rg-test-namespace apply successful
   662  apply phase finished
   663  reconcile phase started
   664  namespace/rg-test-namespace reconcile successful
   665  reconcile phase finished
   666  apply phase started
   667  pod/pod-a apply successful
   668  pod/pod-b apply successful
   669  pod/pod-c apply successful
   670  apply phase finished
   671  reconcile phase started
   672  pod/pod-a reconcile successful
   673  pod/pod-b reconcile successful
   674  pod/pod-c reconcile successful
   675  reconcile phase finished
   676  inventory update started
   677  inventory update finished
   678  apply result: 4 attempted, 4 successful, 0 skipped, 0 failed
   679  reconcile result: 4 attempted, 4 successful, 0 skipped, 0 failed, 0 timed out
   680  EOF
   681  printResult
   682  
   683  # Validate resources in the cluster
   684  # ConfigMap inventory with four inventory items.
   685  assertRGInventory "rg-test-namespace" "4"
   686  printResult
   687  
   688  # Apply again, but the ResourceGroup CRD is not re-installed.
   689  echo "kpt live apply e2e/live/testdata/rg-test-case-1a"
   690  ${BIN_DIR}/kpt live apply e2e/live/testdata/rg-test-case-1a 2>&1 | tee $OUTPUT_DIR/status
   691  assertNotContains "installing inventory ResourceGroup CRD"  # Not applied again
   692  assertKptLiveApplyEquals << EOF
   693  inventory update started
   694  inventory update finished
   695  apply phase started
   696  namespace/rg-test-namespace apply successful
   697  apply phase finished
   698  reconcile phase started
   699  namespace/rg-test-namespace reconcile successful
   700  reconcile phase finished
   701  apply phase started
   702  pod/pod-a apply successful
   703  pod/pod-b apply successful
   704  pod/pod-c apply successful
   705  apply phase finished
   706  reconcile phase started
   707  pod/pod-a reconcile successful
   708  pod/pod-b reconcile successful
   709  pod/pod-c reconcile successful
   710  reconcile phase finished
   711  inventory update started
   712  inventory update finished
   713  apply result: 4 attempted, 4 successful, 0 skipped, 0 failed
   714  reconcile result: 4 attempted, 4 successful, 0 skipped, 0 failed, 0 timed out
   715  EOF
   716  printResult
   717  
   718  # Cleanup by resetting Kptfile and deleting resourcegroup file
   719  cp -f e2e/live/testdata/Kptfile e2e/live/testdata/rg-test-case-1a/
   720  rm e2e/live/testdata/rg-test-case-1a/resourcegroup.yaml
   721  
   722  ###########################################################
   723  #  Tests operations with ResourceGroup inventory CRD
   724  ###########################################################
   725  
   726  createTestSuite
   727  waitForDefaultServiceAccount
   728  
   729  # Test: Installing ResourceGroup CRD
   730  echo "Installing ResourceGroup CRD"
   731  # First, check that the ResourceGroup CRD does NOT exist
   732  echo "kubectl get resourcegroups.kpt.dev"
   733  kubectl get resourcegroups.kpt.dev 2>&1 | tee $OUTPUT_DIR/status
   734  assertContains "error: the server doesn't have a resource type \"resourcegroups\""
   735  # Next, add the ResourceGroup CRD
   736  echo "kpt live install-resource-group"
   737  ${BIN_DIR}/kpt live install-resource-group 2>&1 | tee $OUTPUT_DIR/status
   738  assertContains "installing inventory ResourceGroup CRD...success"
   739  echo "kubectl get resourcegroups.kpt.dev"
   740  kubectl get resourcegroups.kpt.dev 2>&1 | tee $OUTPUT_DIR/status
   741  assertContains "No resources found"
   742  # Add a simple ResourceGroup custom resource, and verify it exists in the cluster.
   743  echo "kubectl apply -f e2e/live/testdata/install-rg-crd/example-resource-group.yaml"
   744  kubectl apply -f e2e/live/testdata/install-rg-crd/example-resource-group.yaml 2>&1 | tee $OUTPUT_DIR/status
   745  assertContains "resourcegroup.kpt.dev/example-inventory created"
   746  echo "kubectl get resourcegroups.kpt.dev --no-headers"
   747  kubectl get resourcegroups.kpt.dev --no-headers 2>&1 | tee $OUTPUT_DIR/status
   748  assertContains "example-inventory"
   749  # Finally, add the ResourceGroup CRD again, and check it says it already exists.
   750  echo "kpt live install-resource-group"
   751  ${BIN_DIR}/kpt live install-resource-group 2>&1 | tee $OUTPUT_DIR/status
   752  assertContains "...success"
   753  printResult
   754  
   755  # Test: Basic Kptfile/ResourceGroup inititalizing inventory info
   756  echo "Testing init for Kptfile/ResourceGroup"
   757  cp -f e2e/live/testdata/Kptfile e2e/live/testdata/rg-test-case-1a/
   758  echo "kpt live init e2e/live/testdata/rg-test-case-1a"
   759  cp -f e2e/live/testdata/Kptfile e2e/live/testdata/rg-test-case-1a
   760  ${BIN_DIR}/kpt live init e2e/live/testdata/rg-test-case-1a 2>&1 | tee $OUTPUT_DIR/status
   761  assertContains "initializing \"resourcegroup.yaml\" data (namespace: rg-test-namespace)...success"
   762  # Difference in Kptfile should have inventory data
   763  diff e2e/live/testdata/Kptfile e2e/live/testdata/rg-test-case-1a/Kptfile 2>&1 | tee $OUTPUT_DIR/status
   764  assertNotContains "inventory:"
   765  assertNotContains "namespace: rg-test-namespace"
   766  assertNotContains "name: inventory-"
   767  assertNotContains "inventoryID:"
   768  # ResourceGroup file should contain inventory information
   769  cat e2e/live/testdata/rg-test-case-1a/resourcegroup.yaml 2>&1 | tee $OUTPUT_DIR/status
   770  assertContains "kind: ResourceGroup"
   771  assertContains "namespace: rg-test-namespace"
   772  assertContains "name: inventory-"
   773  printResult
   774  
   775  echo "Testing init Kptfile/ResourceGroup already initialized"
   776  echo "kpt live init e2e/live/testdata/rg-test-case-1a"
   777  ${BIN_DIR}/kpt live init e2e/live/testdata/rg-test-case-1a 2>&1 | tee $OUTPUT_DIR/status
   778  assertContains "initializing \"resourcegroup.yaml\" data (namespace: rg-test-namespace)...failed"
   779  assertContains "Error: Inventory information has already been added to the package ResourceGroup object."
   780  printResult
   781  
   782  echo "Testing init force Kptfile/ResourceGroup"
   783  echo "kpt live init --force --name inventory-18030002 e2e/live/testdata/rg-test-case-1a"
   784  ${BIN_DIR}/kpt live init --force --name inventory-18030002 e2e/live/testdata/rg-test-case-1a 2>&1 | tee $OUTPUT_DIR/status
   785  assertContains "initializing \"resourcegroup.yaml\" data (namespace: rg-test-namespace)...success"
   786  cat e2e/live/testdata/rg-test-case-1a/resourcegroup.yaml 2>&1 | tee $OUTPUT_DIR/status
   787  assertContains "name: inventory-18030002"
   788  printResult
   789  
   790  echo "Testing init quiet Kptfile/ResourceGroup"
   791  echo "kpt live init --quiet e2e/live/testdata/rg-test-case-1a"
   792  ${BIN_DIR}/kpt live init --quiet e2e/live/testdata/rg-test-case-1a 2>&1 | tee $OUTPUT_DIR/status
   793  assertNotContains "initializing resourcegroup"
   794  printResult
   795  
   796  # Test: Basic kpt live apply dry-run
   797  # Apply run-run for "rg-test-case-1a" directory
   798  echo "[ResourceGroup] Testing initial apply dry-run"
   799  echo "kpt live apply --dry-run e2e/live/testdata/rg-test-case-1a"
   800  ${BIN_DIR}/kpt live apply --dry-run e2e/live/testdata/rg-test-case-1a 2>&1 | tee $OUTPUT_DIR/status
   801  assertKptLiveApplyEquals << EOF
   802  Dry-run strategy: client
   803  inventory update started
   804  inventory update finished
   805  apply phase started
   806  namespace/rg-test-namespace apply successful
   807  apply phase finished
   808  apply phase started
   809  pod/pod-a apply successful
   810  pod/pod-b apply successful
   811  pod/pod-c apply successful
   812  apply phase finished
   813  inventory update started
   814  inventory update finished
   815  apply result: 4 attempted, 4 successful, 0 skipped, 0 failed
   816  EOF
   817  printResult
   818  
   819  # Test: Basic kpt live apply
   820  # Apply run for "rg-test-case-1a" directory
   821  echo "[ResourceGroup] Testing basic apply"
   822  echo "kpt live apply e2e/live/testdata/rg-test-case-1a"
   823  ${BIN_DIR}/kpt live apply e2e/live/testdata/rg-test-case-1a 2>&1 | tee $OUTPUT_DIR/status
   824  # The ResourceGroup CRD is already installed.
   825  assertKptLiveApplyEquals << EOF
   826  inventory update started
   827  inventory update finished
   828  apply phase started
   829  namespace/rg-test-namespace apply successful
   830  apply phase finished
   831  reconcile phase started
   832  namespace/rg-test-namespace reconcile successful
   833  reconcile phase finished
   834  apply phase started
   835  pod/pod-a apply successful
   836  pod/pod-b apply successful
   837  pod/pod-c apply successful
   838  apply phase finished
   839  reconcile phase started
   840  pod/pod-a reconcile successful
   841  pod/pod-b reconcile successful
   842  pod/pod-c reconcile successful
   843  reconcile phase finished
   844  inventory update started
   845  inventory update finished
   846  apply result: 4 attempted, 4 successful, 0 skipped, 0 failed
   847  reconcile result: 4 attempted, 4 successful, 0 skipped, 0 failed, 0 timed out
   848  EOF
   849  printResult
   850  
   851  # Validate resources in the cluster
   852  # ConfigMap inventory with four inventory items.
   853  assertRGInventory "rg-test-namespace" "4"
   854  printResult
   855  
   856  # Test: Basic kpt live apply on symlink
   857  # Apply run for "rg-test-case-1a" directory
   858  echo "[ResourceGroup] Testing basic apply on symlink"
   859  rm -f link-to-rg-test-case-1a # Delete if exists
   860  ln -s e2e/live/testdata/rg-test-case-1a/ link-to-rg-test-case-1a
   861  trap "rm -f ${PWD}/link-to-rg-test-case-1a" EXIT
   862  echo "kpt live apply link-to-rg-test-case-1a"
   863  ${BIN_DIR}/kpt live apply link-to-rg-test-case-1a 2>&1 | tee $OUTPUT_DIR/status
   864  # The ResourceGroup CRD is already installed.
   865  assertNotContains "installing inventory ResourceGroup CRD"
   866  assertKptLiveApplyEquals << EOF
   867  [WARN] resolved symlink "link-to-rg-test-case-1a" to "e2e/live/testdata/rg-test-case-1a", please note that the symlinks within the package are ignored
   868  inventory update started
   869  inventory update finished
   870  apply phase started
   871  namespace/rg-test-namespace apply successful
   872  apply phase finished
   873  reconcile phase started
   874  namespace/rg-test-namespace reconcile successful
   875  reconcile phase finished
   876  apply phase started
   877  pod/pod-a apply successful
   878  pod/pod-b apply successful
   879  pod/pod-c apply successful
   880  apply phase finished
   881  reconcile phase started
   882  pod/pod-a reconcile successful
   883  pod/pod-b reconcile successful
   884  pod/pod-c reconcile successful
   885  reconcile phase finished
   886  inventory update started
   887  inventory update finished
   888  apply result: 4 attempted, 4 successful, 0 skipped, 0 failed
   889  reconcile result: 4 attempted, 4 successful, 0 skipped, 0 failed, 0 timed out
   890  EOF
   891  printResult
   892  
   893  # Validate resources in the cluster
   894  # ConfigMap inventory with four inventory items.
   895  assertRGInventory "rg-test-namespace" "4"
   896  printResult
   897  
   898  # Test: Basic kpt live status on symlink
   899  # Apply run for "rg-test-case-1a" directory
   900  echo "[ResourceGroup] Testing basic status on symlink"
   901  rm -f link-to-rg-test-case-1a # Delete if exists
   902  ln -s e2e/live/testdata/rg-test-case-1a/ link-to-rg-test-case-1a
   903  trap "rm -f ${PWD}/link-to-rg-test-case-1a" EXIT
   904  echo "kpt live status link-to-rg-test-case-1a"
   905  ${BIN_DIR}/kpt live status link-to-rg-test-case-1a 2>&1 | tee $OUTPUT_DIR/status
   906  # The ResourceGroup CRD is already installed.
   907  assertNotContains "installing inventory ResourceGroup CRD"
   908  assertKptLiveApplyEquals << EOF
   909  [WARN] resolved symlink "link-to-rg-test-case-1a" to "e2e/live/testdata/rg-test-case-1a", please note that the symlinks within the package are ignored
   910  inventory-18030002/namespace//rg-test-namespace is Current: Resource is current
   911  inventory-18030002/pod/rg-test-namespace/pod-a is Current: Pod is Ready
   912  inventory-18030002/pod/rg-test-namespace/pod-b is Current: Pod is Ready
   913  inventory-18030002/pod/rg-test-namespace/pod-c is Current: Pod is Ready
   914  EOF
   915  printResult
   916  
   917  # Validate resources in the cluster
   918  # ConfigMap inventory with four inventory items.
   919  assertRGInventory "rg-test-namespace" "4"
   920  printResult
   921  
   922  rm -rf link-to-rg-test-case-1a
   923  
   924  # Test: kpt live apply dry-run of with prune
   925  # "rg-test-case-1b" directory is "rg-test-case-1a" directory with "pod-a" removed and "pod-d" added.
   926  echo "[ResourceGroup] Testing basic apply dry-run"
   927  cp -f e2e/live/testdata/rg-test-case-1a/Kptfile e2e/live/testdata/rg-test-case-1b/
   928  echo "kpt live apply --dry-run e2e/live/testdata/rg-test-case-1b"
   929  cp -f e2e/live/testdata/rg-test-case-1a/Kptfile e2e/live/testdata/rg-test-case-1b
   930  cp -f e2e/live/testdata/rg-test-case-1a/resourcegroup.yaml e2e/live/testdata/rg-test-case-1b
   931  ${BIN_DIR}/kpt live apply --dry-run e2e/live/testdata/rg-test-case-1b 2>&1 | tee $OUTPUT_DIR/status
   932  assertKptLiveApplyEquals << EOF
   933  Dry-run strategy: client
   934  inventory update started
   935  inventory update finished
   936  apply phase started
   937  namespace/rg-test-namespace apply successful
   938  apply phase finished
   939  apply phase started
   940  pod/pod-b apply successful
   941  pod/pod-c apply successful
   942  pod/pod-d apply successful
   943  apply phase finished
   944  prune phase started
   945  pod/pod-a prune successful
   946  prune phase finished
   947  inventory update started
   948  inventory update finished
   949  apply result: 4 attempted, 4 successful, 0 skipped, 0 failed
   950  prune result: 1 attempted, 1 successful, 0 skipped, 0 failed
   951  EOF
   952  printResult
   953  
   954  # Validate resources in the cluster
   955  # ConfigMap inventory with four inventory items.
   956  assertRGInventory "rg-test-namespace" "4"
   957  assertPodExists "pod-a" "rg-test-namespace"
   958  assertPodExists "pod-b" "rg-test-namespace"
   959  assertPodExists "pod-c" "rg-test-namespace"
   960  printResult
   961  
   962  # Test: Basic kpt live apply/prune
   963  # "rg-test-case-1b" directory is "rg-test-case-1a" directory with "pod-a" removed and "pod-d" added.
   964  echo "[ResourceGroup] Testing basic prune"
   965  echo "kpt live apply e2e/live/testdata/rg-test-case-1b"
   966  ${BIN_DIR}/kpt live apply e2e/live/testdata/rg-test-case-1b 2>&1 | tee $OUTPUT_DIR/status
   967  assertNotContains "installing inventory ResourceGroup CRD"  # CRD already installed
   968  assertKptLiveApplyEquals << EOF
   969  inventory update started
   970  inventory update finished
   971  apply phase started
   972  namespace/rg-test-namespace apply successful
   973  apply phase finished
   974  reconcile phase started
   975  namespace/rg-test-namespace reconcile successful
   976  reconcile phase finished
   977  apply phase started
   978  pod/pod-b apply successful
   979  pod/pod-c apply successful
   980  pod/pod-d apply successful
   981  apply phase finished
   982  reconcile phase started
   983  pod/pod-b reconcile successful
   984  pod/pod-c reconcile successful
   985  pod/pod-d reconcile successful
   986  reconcile phase finished
   987  prune phase started
   988  pod/pod-a prune successful
   989  prune phase finished
   990  reconcile phase started
   991  pod/pod-a reconcile successful
   992  reconcile phase finished
   993  inventory update started
   994  inventory update finished
   995  apply result: 4 attempted, 4 successful, 0 skipped, 0 failed
   996  prune result: 1 attempted, 1 successful, 0 skipped, 0 failed
   997  reconcile result: 5 attempted, 5 successful, 0 skipped, 0 failed, 0 timed out
   998  EOF
   999  printResult
  1000  
  1001  # Validate resources in the cluster
  1002  # ConfigMap inventory with four inventory items.
  1003  assertRGInventory "rg-test-namespace" "4"
  1004  assertPodExists "pod-b" "rg-test-namespace"
  1005  assertPodExists "pod-c" "rg-test-namespace"
  1006  assertPodExists "pod-d" "rg-test-namespace"
  1007  assertPodNotExists "pod-a" "rg-test-namespace"
  1008  printResult
  1009  
  1010  # Basic kpt live destroy --dry-run
  1011  echo "[ResourceGroup] Testing basic destroy dry-run"
  1012  echo "kpt live destroy --dry-run e2e/live/testdata/rg-test-case-1b"
  1013  ${BIN_DIR}/kpt live destroy --dry-run e2e/live/testdata/rg-test-case-1b 2>&1 | tee $OUTPUT_DIR/status
  1014  assertKptLiveApplyEquals << EOF
  1015  Dry-run strategy: client
  1016  delete phase started
  1017  pod/pod-d delete successful
  1018  pod/pod-c delete successful
  1019  pod/pod-b delete successful
  1020  delete phase finished
  1021  delete phase started
  1022  namespace/rg-test-namespace delete successful
  1023  delete phase finished
  1024  inventory update started
  1025  inventory update finished
  1026  delete result: 4 attempted, 4 successful, 0 skipped, 0 failed
  1027  EOF
  1028  printResult
  1029  
  1030  # Validate resources NOT DESTROYED in the cluster
  1031  assertPodExists "pod-b" "rg-test-namespace"
  1032  assertPodExists "pod-c" "rg-test-namespace"
  1033  assertPodExists "pod-d" "rg-test-namespace"
  1034  printResult
  1035  
  1036  # Test: Basic kpt live destroy
  1037  # "rg-test-case-1b" directory is "rg-test-case-1a" directory with "pod-a" removed and "pod-d" added.
  1038  echo "[ResourceGroup] Testing basic destroy"
  1039  echo "kpt live destroy e2e/live/testdata/rg-test-case-1b"
  1040  ${BIN_DIR}/kpt live destroy e2e/live/testdata/rg-test-case-1b 2>&1 | tee $OUTPUT_DIR/status
  1041  assertKptLiveApplyEquals << EOF
  1042  delete phase started
  1043  pod/pod-d delete successful
  1044  pod/pod-c delete successful
  1045  pod/pod-b delete successful
  1046  delete phase finished
  1047  reconcile phase started
  1048  pod/pod-c reconcile successful
  1049  pod/pod-b reconcile successful
  1050  pod/pod-d reconcile successful
  1051  reconcile phase finished
  1052  delete phase started
  1053  namespace/rg-test-namespace delete successful
  1054  delete phase finished
  1055  reconcile phase started
  1056  namespace/rg-test-namespace reconcile successful
  1057  reconcile phase finished
  1058  inventory update started
  1059  inventory update finished
  1060  delete result: 4 attempted, 4 successful, 0 skipped, 0 failed
  1061  reconcile result: 4 attempted, 4 successful, 0 skipped, 0 failed, 0 timed out
  1062  EOF
  1063  printResult
  1064  
  1065  # Validate resources NOT in the cluster
  1066  assertPodNotExists "pod-b" "rg-test-namespace"
  1067  assertPodNotExists "pod-c" "rg-test-namespace"
  1068  assertPodNotExists "pod-d" "rg-test-namespace"
  1069  printResult
  1070  
  1071  # Test: Basic kpt live apply/status/destroy from stdin
  1072  # 
  1073  echo "Testing apply/status/destroy from stdin"
  1074  echo "cat e2e/live/testdata/stdin-test/pods.yaml | kpt live apply -"
  1075  cat e2e/live/testdata/stdin-test/pods.yaml | ${BIN_DIR}/kpt live apply - 2>&1 | tee $OUTPUT_DIR/status
  1076  assertKptLiveApplyEquals << EOF
  1077  inventory update started
  1078  inventory update finished
  1079  apply phase started
  1080  namespace/stdin-test-namespace apply successful
  1081  apply phase finished
  1082  reconcile phase started
  1083  namespace/stdin-test-namespace reconcile successful
  1084  reconcile phase finished
  1085  apply phase started
  1086  pod/pod-a apply successful
  1087  pod/pod-b apply successful
  1088  pod/pod-c apply successful
  1089  apply phase finished
  1090  reconcile phase started
  1091  pod/pod-a reconcile successful
  1092  pod/pod-b reconcile successful
  1093  pod/pod-c reconcile successful
  1094  reconcile phase finished
  1095  inventory update started
  1096  inventory update finished
  1097  apply result: 4 attempted, 4 successful, 0 skipped, 0 failed
  1098  reconcile result: 4 attempted, 4 successful, 0 skipped, 0 failed, 0 timed out
  1099  EOF
  1100  printResult
  1101  
  1102  echo "cat e2e/live/testdata/stdin-test/pods.yaml | kpt live status -"
  1103  cat e2e/live/testdata/stdin-test/pods.yaml | ${BIN_DIR}/kpt live status - 2>&1 | tee $OUTPUT_DIR/status
  1104  assertContains "inventory-18030002/namespace//stdin-test-namespace is Current: Resource is current"
  1105  assertContains "inventory-18030002/pod/stdin-test-namespace/pod-a is Current: Pod is Ready"
  1106  assertContains "inventory-18030002/pod/stdin-test-namespace/pod-b is Current: Pod is Ready"
  1107  assertContains "inventory-18030002/pod/stdin-test-namespace/pod-c is Current: Pod is Ready"
  1108  printResult
  1109  
  1110  echo "cat e2e/live/testdata/stdin-test/pods.yaml | kpt live destroy -"
  1111  cat e2e/live/testdata/stdin-test/pods.yaml | ${BIN_DIR}/kpt live destroy - 2>&1 | tee $OUTPUT_DIR/status
  1112  assertKptLiveApplyEquals << EOF
  1113  delete phase started
  1114  pod/pod-c delete successful
  1115  pod/pod-b delete successful
  1116  pod/pod-a delete successful
  1117  delete phase finished
  1118  reconcile phase started
  1119  pod/pod-c reconcile successful
  1120  pod/pod-b reconcile successful
  1121  pod/pod-a reconcile successful
  1122  reconcile phase finished
  1123  delete phase started
  1124  namespace/stdin-test-namespace delete successful
  1125  delete phase finished
  1126  reconcile phase started
  1127  namespace/stdin-test-namespace reconcile successful
  1128  reconcile phase finished
  1129  inventory update started
  1130  inventory update finished
  1131  delete result: 4 attempted, 4 successful, 0 skipped, 0 failed
  1132  reconcile result: 4 attempted, 4 successful, 0 skipped, 0 failed, 0 timed out
  1133  EOF
  1134  printResult
  1135  
  1136  # Test: kpt live apply continue-on-error
  1137  echo "[ResourceGroup] Testing continue-on-error"
  1138  echo "kpt live apply e2e/live/testdata/continue-on-error"
  1139  cp -f e2e/live/testdata/Kptfile e2e/live/testdata/continue-on-error
  1140  ${BIN_DIR}/kpt live init e2e/live/testdata/continue-on-error 2>&1 | tee $OUTPUT_DIR/status
  1141  diff e2e/live/testdata/Kptfile e2e/live/testdata/continue-on-error/resourcegroup.yaml 2>&1 | tee $OUTPUT_DIR/status
  1142  assertContains "namespace: continue-err-namespace"
  1143  printResult
  1144  
  1145  echo "kpt live apply e2e/live/testdata/continue-on-error"
  1146  ${BIN_DIR}/kpt live apply e2e/live/testdata/continue-on-error 2>&1 | tee $OUTPUT_DIR/status
  1147  
  1148  if [[ "$(kubeServerMinorVersion)" -ge 20 ]]; then # >= 1.20.x
  1149    # https://github.com/kubernetes/kubernetes/blob/v1.20.0/staging/src/k8s.io/apimachinery/pkg/util/validation/validation.go#L199
  1150    RFC1123_ERROR="a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character"
  1151  else # < 1.20.x
  1152    # https://github.com/kubernetes/kubernetes/blob/v1.19.0/staging/src/k8s.io/apimachinery/pkg/util/validation/validation.go#L199
  1153    RFC1123_ERROR="a DNS-1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character"
  1154  fi
  1155  
  1156  assertKptLiveApplyEquals << EOF
  1157  inventory update started
  1158  inventory update finished
  1159  apply phase started
  1160  namespace/continue-err-namespace apply successful
  1161  apply phase finished
  1162  reconcile phase started
  1163  namespace/continue-err-namespace reconcile successful
  1164  reconcile phase finished
  1165  apply phase started
  1166  pod/pod-a apply successful
  1167  pod/pod-B apply failed: error when creating "pod-b.yaml": Pod "pod-B" is invalid: metadata.name: Invalid value: "pod-B": ${RFC1123_ERROR} (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')
  1168  apply phase finished
  1169  reconcile phase started
  1170  pod/pod-B reconcile skipped
  1171  pod/pod-a reconcile successful
  1172  reconcile phase finished
  1173  inventory update started
  1174  inventory update finished
  1175  apply result: 3 attempted, 2 successful, 0 skipped, 1 failed
  1176  reconcile result: 3 attempted, 2 successful, 1 skipped, 0 failed, 0 timed out
  1177  EOF
  1178  printResult
  1179  
  1180  assertRGInventory "continue-err-namespace" "2"
  1181  assertPodExists "pod-a" "continue-err-namespace"
  1182  assertPodNotExists "pod-B" "continue-err-namespace"
  1183  printResult
  1184  
  1185  # Test: RBAC error applying a resource
  1186  echo "Testing RBAC error during apply"
  1187  # Setup: create a service account and bind a Role to it so it has administrative
  1188  # privileges on the "test" namespace, but no permissions on the default
  1189  # namespace.
  1190  echo "kubectl apply -f e2e/live/testdata/rbac-error-step-1"
  1191  kubectl apply -f e2e/live/testdata/rbac-error-step-1 2>&1 | tee $OUTPUT_DIR/status
  1192  assertContains "namespace/rbac-error created"
  1193  assertContains "rolebinding.rbac.authorization.k8s.io/admin created"
  1194  assertContains "serviceaccount/user created"
  1195  printResult
  1196  wait 2
  1197  
  1198  # Setup: use the service account just created. It does not have permissions
  1199  # on the default namespace, so it will give a permissions error on apply
  1200  # for anything attempted to apply to the default namespace.
  1201  echo "kubectl apply -f e2e/live/testdata/rbac-error-step-2"
  1202  kubectl apply -f e2e/live/testdata/rbac-error-step-2 2>&1 | tee $OUTPUT_DIR/status
  1203  assertContains "secret/user-credentials created"
  1204  wait 2
  1205  SECRET_NAME="user-credentials"
  1206  echo "kubectl get secrets -ojsonpath='{.data.token}' "${SECRET_NAME}" | base64 -d"
  1207  SECRET_TOKEN="$(kubectl get secrets -ojsonpath='{.data.token}' "${SECRET_NAME}" | base64 -d)"
  1208  echo "kubectl config set-credentials user --token \"<REDACTED>\""
  1209  kubectl config set-credentials user --token "${SECRET_TOKEN}" 2>&1 | tee $OUTPUT_DIR/status
  1210  echo "kubectl config set-context kind-kind:user --cluster=kind-kind"
  1211  kubectl config set-context kind-kind:user --cluster=kind-kind --user=user 2>&1 | tee $OUTPUT_DIR/status
  1212  echo "kubectl config use-context kind-kind:user"
  1213  kubectl config use-context kind-kind:user 2>&1 | tee $OUTPUT_DIR/status
  1214  printResult
  1215  wait 2
  1216  
  1217  # Attempt to apply two ConfigMaps: one in the default namespace (fails), and one
  1218  # in the "rbac-error" namespace (succeeds).
  1219  echo "kpt live apply --install-resource-group=false e2e/live/testdata/rbac-error-step-3"
  1220  ${BIN_DIR}/kpt live apply --install-resource-group=false e2e/live/testdata/rbac-error-step-3 2>&1 | tee $OUTPUT_DIR/status
  1221  assertNotContains "installing inventory ResourceGroup CRD"  # CRD already installed
  1222  assertContains 'error: polling for status failed: failed to list /v1, Kind=ConfigMap: configmaps is forbidden: User "system:serviceaccount:default:user" cannot list resource "configmaps" in API group "" at the cluster scope'
  1223  printResult
  1224  
  1225  # No inventory expected - permission error causes early exit
  1226  echo "kubectl get resourcegroups.kpt.dev -n 'rbac-error' --selector='cli-utils.sigs.k8s.io/inventory-id' --no-headers"
  1227  kubectl get resourcegroups.kpt.dev -n 'rbac-error' --selector='cli-utils.sigs.k8s.io/inventory-id' --no-headers 2>&1 | tee $OUTPUT_DIR/status
  1228  assertContains "No resources found"
  1229  printResult
  1230  
  1231  ###########################################################
  1232  #  Test Migrate from ConfigMap inventory to ResourceGroup
  1233  ###########################################################
  1234  
  1235  createTestSuite
  1236  waitForDefaultServiceAccount
  1237  
  1238  # Setup: kpt live apply ConfigMap inventory
  1239  # Applies resources in "migrate-case-1a" directory.
  1240  echo "Testing kpt live apply with ConfigMap inventory"
  1241  # Prerequisite: set up the ConfigMap inventory file
  1242  # Copy Kptfile into "migrate-case-1a" WITHOUT inventory information. This ensures
  1243  # the apply uses the ConfigMap inventory-template.yaml during the apply.
  1244  cp -f e2e/live/testdata/Kptfile e2e/live/testdata/migrate-case-1a/
  1245  cp -f e2e/live/testdata/template-rg-namespace.yaml e2e/live/testdata/migrate-case-1a/inventory-template.yaml
  1246  echo "previouskpt live apply e2e/live/testdata/migrate-case-1a"
  1247  ${BIN_DIR}/previouskpt live apply e2e/live/testdata/migrate-case-1a 2>&1 | tee $OUTPUT_DIR/status
  1248  assertContains "namespace/test-rg-namespace unchanged"
  1249  assertContains "pod/pod-a created"
  1250  assertContains "pod/pod-b created"
  1251  assertContains "pod/pod-c created"
  1252  assertContains "4 resource(s) applied. 3 created, 1 unchanged, 0 configured, 0 failed"
  1253  assertContains "0 resource(s) pruned, 0 skipped, 0 failed"
  1254  printResult
  1255  
  1256  # Validate resources in the cluster
  1257  assertCMInventory "test-rg-namespace" "4"
  1258  assertPodExists "pod-a" "test-rg-namespace"
  1259  assertPodExists "pod-b" "test-rg-namespace"
  1260  assertPodExists "pod-c" "test-rg-namespace"
  1261  printResult
  1262  
  1263  # Test: kpt live migrate from ConfigMap to ResourceGroup inventory
  1264  # Migrates resources in "migrate-case-1a" directory.
  1265  echo "Testing migrate dry-run from ConfigMap to ResourceGroup inventory"
  1266  # Run migrate dry-run and verify that the migrate did not actually happen
  1267  echo "kpt live migrate --dry-run e2e/live/testdata/migrate-case-1a"
  1268  ${BIN_DIR}/kpt live migrate --dry-run e2e/live/testdata/migrate-case-1a 2>&1 | tee $OUTPUT_DIR/status
  1269  assertContains "ensuring ResourceGroup CRD exists in cluster...success"
  1270  assertContains "retrieve the current ConfigMap inventory...success (inventory-id:"
  1271  assertContains "creating ResourceGroup object file...success"
  1272  assertContains "retrieve ConfigMap inventory objs...success (4 inventory objects)"
  1273  assertContains "migrate inventory to ResourceGroup...success"
  1274  assertContains "deleting old ConfigMap inventory object...success"
  1275  assertContains "deleting inventory template file"
  1276  assertContains "inventory migration...success"
  1277  printResult
  1278  
  1279  # Migrate did not actually happen in dry-run, so ConfigMap inventory still exists
  1280  assertCMInventory "test-rg-namespace" "4"
  1281  printResult
  1282  
  1283  # Now actually run the migrate and verify the new ResourceGroup inventory exists
  1284  echo "Testing migrate from ConfigMap to ResourceGroup inventory"
  1285  # Prerequisite: set up the ConfigMap inventory file
  1286  cp -f e2e/live/testdata/template-rg-namespace.yaml e2e/live/testdata/migrate-case-1a/inventory-template.yaml
  1287  echo "kpt live migrate e2e/live/testdata/migrate-case-1a"
  1288  ${BIN_DIR}/kpt live migrate e2e/live/testdata/migrate-case-1a 2>&1 | tee $OUTPUT_DIR/status
  1289  assertContains "ensuring ResourceGroup CRD exists in cluster...success"
  1290  assertContains "retrieve the current ConfigMap inventory...success (inventory-id:"
  1291  assertContains "creating ResourceGroup object file...success"
  1292  assertContains "retrieve ConfigMap inventory objs...success (4 inventory objects)"
  1293  assertContains "migrate inventory to ResourceGroup...success"
  1294  assertContains "deleting old ConfigMap inventory object...success"
  1295  assertContains "deleting inventory template file"
  1296  assertContains "inventory migration...success"
  1297  printResult
  1298  
  1299  # Validate resources in the cluster
  1300  assertPodExists "pod-a" "test-rg-namespace"
  1301  assertPodExists "pod-b" "test-rg-namespace"
  1302  assertPodExists "pod-c" "test-rg-namespace"
  1303  assertRGInventory "test-rg-namespace"
  1304  printResult
  1305  
  1306  # Run it again, and validate the output
  1307  ${BIN_DIR}/kpt live migrate e2e/live/testdata/migrate-case-1a 2>&1 | tee $OUTPUT_DIR/status
  1308  assertContains "ensuring ResourceGroup CRD exists in cluster...success"
  1309  assertContains "retrieve the current ConfigMap inventory...no ConfigMap inventory...completed"
  1310  assertContains "inventory migration...success"
  1311  printResult
  1312  
  1313  # Test: kpt live apply/prune
  1314  # "rg-test-case-1b" directory is "rg-test-case-1a" directory with "pod-a" removed and "pod-d" added.
  1315  echo "Testing apply/prune after migrate"
  1316  cp -f e2e/live/testdata/migrate-case-1a/Kptfile e2e/live/testdata/migrate-case-1b/
  1317  echo "kpt live apply e2e/live/testdata/migrate-case-1b"
  1318  cp -f e2e/live/testdata/migrate-case-1a/Kptfile e2e/live/testdata/migrate-case-1b
  1319  cp -f e2e/live/testdata/migrate-case-1a/resourcegroup.yaml e2e/live/testdata/migrate-case-1b
  1320  ${BIN_DIR}/kpt live apply e2e/live/testdata/migrate-case-1b 2>&1 | tee $OUTPUT_DIR/status
  1321  assertKptLiveApplyEquals << EOF
  1322  inventory update started
  1323  inventory update finished
  1324  apply phase started
  1325  namespace/test-rg-namespace apply successful
  1326  apply phase finished
  1327  reconcile phase started
  1328  namespace/test-rg-namespace reconcile successful
  1329  reconcile phase finished
  1330  apply phase started
  1331  pod/pod-b apply successful
  1332  pod/pod-c apply successful
  1333  pod/pod-d apply successful
  1334  apply phase finished
  1335  reconcile phase started
  1336  pod/pod-b reconcile successful
  1337  pod/pod-c reconcile successful
  1338  pod/pod-d reconcile successful
  1339  reconcile phase finished
  1340  prune phase started
  1341  pod/pod-a prune successful
  1342  prune phase finished
  1343  reconcile phase started
  1344  pod/pod-a reconcile successful
  1345  reconcile phase finished
  1346  inventory update started
  1347  inventory update finished
  1348  apply result: 4 attempted, 4 successful, 0 skipped, 0 failed
  1349  prune result: 1 attempted, 1 successful, 0 skipped, 0 failed
  1350  reconcile result: 5 attempted, 5 successful, 0 skipped, 0 failed, 0 timed out
  1351  EOF
  1352  printResult
  1353  
  1354  # Validate resources in the cluster
  1355  # ResourceGroup inventory with four inventory items.
  1356  assertRGInventory "test-rg-namespace" "4"
  1357  assertPodNotExists "pod-a" "test-rg-namespace"
  1358  assertPodExists "pod-b" "test-rg-namespace"
  1359  assertPodExists "pod-c" "test-rg-namespace"
  1360  assertPodExists "pod-d" "test-rg-namespace"
  1361  printResult
  1362  
  1363  ###########################################################
  1364  #  Test Update ResourceGroup CRD during apply
  1365  ###########################################################
  1366  
  1367  createTestSuite
  1368  waitForDefaultServiceAccount
  1369  
  1370  # This test first applies a kpt package with kpt1.0.0,
  1371  # which uses the previous ResourceGroup CRD.
  1372  # Then it re-apply the same kpt package with the built kpt,
  1373  # which uses a new ResourceGroup CRD.
  1374  # It updates the ResourceGroup CRD and apply/prune works as expected.
  1375  echo "Testing apply with kpt 1.0.0 and re-apply/prune with built kpt"
  1376  echo "cat e2e/live/testdata/stdin-test/pods.yaml | kpt1.0.0 live apply -"
  1377  cat e2e/live/testdata/stdin-test/pods.yaml | ${BIN_DIR}/kpt1.0.0 live apply - 2>&1 | tee $OUTPUT_DIR/status
  1378  assertContains "pod/pod-a created"
  1379  assertContains "pod/pod-b created"
  1380  assertContains "pod/pod-c created"
  1381  assertContains "4 resource(s) applied. 3 created, 1 unchanged, 0 configured, 0 failed"
  1382  printResult
  1383  
  1384  echo "cat e2e/live/testdata/stdin-test/pods.yaml | kpt live apply -"
  1385  cat e2e/live/testdata/stdin-test/pods.yaml | ${BIN_DIR}/kpt live apply - 2>&1 | tee $OUTPUT_DIR/status
  1386  assertKptLiveApplyEquals << EOF
  1387  installing inventory ResourceGroup CRD.
  1388  inventory update started
  1389  inventory update finished
  1390  apply phase started
  1391  namespace/stdin-test-namespace apply successful
  1392  apply phase finished
  1393  reconcile phase started
  1394  namespace/stdin-test-namespace reconcile successful
  1395  reconcile phase finished
  1396  apply phase started
  1397  pod/pod-a apply successful
  1398  pod/pod-b apply successful
  1399  pod/pod-c apply successful
  1400  apply phase finished
  1401  reconcile phase started
  1402  pod/pod-a reconcile successful
  1403  pod/pod-b reconcile successful
  1404  pod/pod-c reconcile successful
  1405  reconcile phase finished
  1406  inventory update started
  1407  inventory update finished
  1408  apply result: 4 attempted, 4 successful, 0 skipped, 0 failed
  1409  reconcile result: 4 attempted, 4 successful, 0 skipped, 0 failed, 0 timed out
  1410  EOF
  1411  printResult
  1412  
  1413  echo "cat e2e/live/testdata/stdin-test/pods.yaml | kpt live destroy -"
  1414  cat e2e/live/testdata/stdin-test/pods.yaml | ${BIN_DIR}/kpt live destroy - 2>&1 | tee $OUTPUT_DIR/status
  1415  assertKptLiveApplyEquals << EOF
  1416  delete phase started
  1417  pod/pod-c delete successful
  1418  pod/pod-b delete successful
  1419  pod/pod-a delete successful
  1420  delete phase finished
  1421  reconcile phase started
  1422  pod/pod-b reconcile successful
  1423  pod/pod-c reconcile successful
  1424  pod/pod-a reconcile successful
  1425  reconcile phase finished
  1426  delete phase started
  1427  namespace/stdin-test-namespace delete successful
  1428  delete phase finished
  1429  reconcile phase started
  1430  namespace/stdin-test-namespace reconcile successful
  1431  reconcile phase finished
  1432  inventory update started
  1433  inventory update finished
  1434  delete result: 4 attempted, 4 successful, 0 skipped, 0 failed
  1435  reconcile result: 4 attempted, 4 successful, 0 skipped, 0 failed, 0 timed out
  1436  EOF
  1437  printResult
  1438  
  1439  # Test: don't have permission to update the ResourceGroup CRD
  1440  # should see an error message
  1441  echo "Testing updating ResourceGroup CRD during apply"
  1442  echo "Apply the previous ResourceGroup CRD"
  1443  echo "kpt1.0.0 live install-resource-group"
  1444  ${BIN_DIR}/kpt1.0.0 live install-resource-group 2>&1 | tee $OUTPUT_DIR/status
  1445  # Setup: create a service account and bind a Role to it so it has administrative
  1446  # privileges on the "test" namespace, but no permissions to Get or Update CRD.
  1447  echo "kubectl apply -f e2e/live/testdata/rbac-error-step-1"
  1448  kubectl apply -f e2e/live/testdata/rbac-error-step-1 2>&1 | tee $OUTPUT_DIR/status
  1449  assertContains "namespace/rbac-error created"
  1450  assertContains "rolebinding.rbac.authorization.k8s.io/admin created"
  1451  assertContains "serviceaccount/user created"
  1452  wait 2
  1453  
  1454  # Setup: use the service account just created. It does not have permissions
  1455  # on the default namespace, so it will give a permissions error on apply
  1456  # for anything attempted to apply to the default namespace.
  1457  echo "kubectl apply -f e2e/live/testdata/rbac-error-step-2"
  1458  kubectl apply -f e2e/live/testdata/rbac-error-step-2 2>&1 | tee $OUTPUT_DIR/status
  1459  assertContains "secret/user-credentials created"
  1460  wait 2
  1461  SECRET_NAME="user-credentials"
  1462  echo "kubectl get secrets -ojsonpath='{.data.token}' "${SECRET_NAME}" | base64 -d"
  1463  SECRET_TOKEN="$(kubectl get secrets -ojsonpath='{.data.token}' "${SECRET_NAME}" | base64 -d)"
  1464  echo "kubectl config set-credentials user --token \"<REDACTED>\""
  1465  kubectl config set-credentials user --token "${SECRET_TOKEN}" 2>&1 | tee $OUTPUT_DIR/status
  1466  echo "kubectl config set-context kind-kind:user --cluster=kind-kind --user=user"
  1467  kubectl config set-context kind-kind:user --cluster=kind-kind --user=user 2>&1 | tee $OUTPUT_DIR/status
  1468  echo "kubectl config use-context kind-kind:user"
  1469  kubectl config use-context kind-kind:user 2>&1 | tee $OUTPUT_DIR/status
  1470  wait 2
  1471  
  1472  # Attempt to apply a kpt package. It fails with an error message.
  1473  echo "kpt live apply e2e/live/testdata/rbac-error-step-3"
  1474  ${BIN_DIR}/kpt live apply e2e/live/testdata/rbac-error-step-3 2>&1 | tee $OUTPUT_DIR/status
  1475  assertContains "error: Type ResourceGroup CRD needs update."
  1476  printResult
  1477  
  1478  ###########################################################
  1479  #  Test Migrate from Kptfile inventory to ResourceGroup
  1480  ###########################################################
  1481  
  1482  createTestSuite
  1483  waitForDefaultServiceAccount
  1484  
  1485  # Setup: kpt live apply ConfigMap inventory
  1486  # Applies resources in "migrate-case-2a" directory.
  1487  echo "Initialize Kptfile with inventory for migration to ResourceGroup tests"
  1488  echo "kpt live init e2e/live/testdata/migrate-case-2a"
  1489  ${BIN_DIR}/kpt1.0.0 live init e2e/live/testdata/migrate-case-2a 2>&1 | tee $OUTPUT_DIR/status
  1490  assertContains "initializing Kptfile inventory info (namespace: test-namespace)...success"
  1491  printResult
  1492  
  1493  echo "Testing kpt live apply with Kptfile inventory"
  1494  echo "kpt live apply e2e/live/testdata/migrate-case-2a"
  1495  ${BIN_DIR}/kpt1.0.0 live apply e2e/live/testdata/migrate-case-2a 2>&1 | tee $OUTPUT_DIR/status
  1496  assertContains "installing inventory ResourceGroup CRD"
  1497  assertContains "namespace/test-namespace unchanged"
  1498  assertContains "pod/pod-a created"
  1499  assertContains "pod/pod-b created"
  1500  assertContains "pod/pod-c created"
  1501  assertContains "4 resource(s) applied. 3 created, 1 unchanged, 0 configured, 0 failed"
  1502  # Validate resources in the cluster
  1503  assertRGInventory "test-namespace" "4"
  1504  assertPodExists "pod-a" "test-namespace"
  1505  assertPodExists "pod-b" "test-namespace"
  1506  assertPodExists "pod-c" "test-namespace"
  1507  printResult
  1508  
  1509  # Test: kpt live migrate from Kptfile inventory to ResourceGroup inventory
  1510  # Migrates resources in "migrate-case-2" directory.
  1511  echo "Testing migrate dry-run from Kptfile to ResourceGroup inventory"
  1512  echo "kpt live migrate --dry-run e2e/live/testdata/migrate-case-2a"
  1513  # Run migrate dry-run and verify that the migrate did not actually happen
  1514  ${BIN_DIR}/kpt live migrate --dry-run e2e/live/testdata/migrate-case-2a 2>&1 | tee $OUTPUT_DIR/status
  1515  assertContains "ensuring ResourceGroup CRD exists in cluster...success"
  1516  assertContains "retrieve the current ConfigMap inventory...no ConfigMap inventory...completed"
  1517  assertContains "reading existing Kptfile...success"
  1518  assertContains "inventory migration...success"
  1519  printResult
  1520  # Ensure resourcegroup.yaml was not created
  1521  ls e2e/live/testdata/migrate-case-2a/resourcegroup.yaml 2>&1 | tee $OUTPUT_DIR/status
  1522  assertContains "ls: cannot access 'e2e/live/testdata/migrate-case-2a/resourcegroup.yaml': No such file or directory"
  1523  printResult
  1524  
  1525  # Now actually run the migrate and verify the new ResourceGroup file exists
  1526  echo "Testing migrate from Kptfile to ResourceGroup inventory"
  1527  echo "kpt live migrate e2e/live/testdata/migrate-case-2a"
  1528  ${BIN_DIR}/kpt live migrate e2e/live/testdata/migrate-case-2a 2>&1 | tee $OUTPUT_DIR/status
  1529  assertContains "ensuring ResourceGroup CRD exists in cluster...success"
  1530  assertContains "retrieve the current ConfigMap inventory...no ConfigMap inventory...completed"
  1531  assertContains "reading existing Kptfile...success"
  1532  assertContains "inventory migration...success"
  1533  # Validate resources in the cluster
  1534  assertPodExists "pod-a" "test-namespace"
  1535  assertPodExists "pod-b" "test-namespace"
  1536  assertPodExists "pod-c" "test-namespace"
  1537  assertRGInventory "test-namespace"
  1538  # ResourceGroup file should contain inventory information
  1539  cat e2e/live/testdata/migrate-case-2a/resourcegroup.yaml 2>&1 | tee $OUTPUT_DIR/status
  1540  assertContains "kind: ResourceGroup"
  1541  assertContains "namespace: test-namespace"
  1542  assertContains "name: inventory-"
  1543  printResult
  1544  
  1545  # Run it again, and validate the output
  1546  ${BIN_DIR}/kpt live migrate e2e/live/testdata/migrate-case-2a 2>&1 | tee $OUTPUT_DIR/status
  1547  assertContains "ensuring ResourceGroup CRD exists in cluster...success"
  1548  assertContains "retrieve the current ConfigMap inventory...no ConfigMap inventory...completed"
  1549  assertContains "reading existing Kptfile...inventory migration...success"
  1550  printResult
  1551  
  1552  # Test: kpt live apply/prune
  1553  # "migrate-case-2b" directory is "migrate-case-2a" directory with "pod-a" removed and "pod-d" added.
  1554  echo "Testing apply/prune after migrate"
  1555  echo "kpt live apply e2e/live/testdata/migrate-case-2b"
  1556  cp -f e2e/live/testdata/migrate-case-2a/Kptfile e2e/live/testdata/migrate-case-2b
  1557  cp -f e2e/live/testdata/migrate-case-2a/resourcegroup.yaml e2e/live/testdata/migrate-case-2b
  1558  ${BIN_DIR}/kpt live apply e2e/live/testdata/migrate-case-2b 2>&1 | tee $OUTPUT_DIR/status
  1559  assertKptLiveApplyEquals << EOF
  1560  installing inventory ResourceGroup CRD.
  1561  inventory update started
  1562  inventory update finished
  1563  apply phase started
  1564  namespace/test-namespace apply successful
  1565  apply phase finished
  1566  reconcile phase started
  1567  namespace/test-namespace reconcile successful
  1568  reconcile phase finished
  1569  apply phase started
  1570  pod/pod-b apply successful
  1571  pod/pod-c apply successful
  1572  pod/pod-d apply successful
  1573  apply phase finished
  1574  reconcile phase started
  1575  pod/pod-b reconcile successful
  1576  pod/pod-c reconcile successful
  1577  pod/pod-d reconcile pending
  1578  pod/pod-d reconcile successful
  1579  reconcile phase finished
  1580  prune phase started
  1581  pod/pod-a prune successful
  1582  prune phase finished
  1583  reconcile phase started
  1584  pod/pod-a reconcile pending
  1585  pod/pod-a reconcile successful
  1586  reconcile phase finished
  1587  inventory update started
  1588  inventory update finished
  1589  apply result: 4 attempted, 4 successful, 0 skipped, 0 failed
  1590  prune result: 1 attempted, 1 successful, 0 skipped, 0 failed
  1591  reconcile result: 5 attempted, 5 successful, 0 skipped, 0 failed, 0 timed out
  1592  EOF
  1593  # Validate resources in the cluster
  1594  # ResourceGroup inventory with four inventory items.
  1595  assertRGInventory "test-namespace" "4"
  1596  assertPodNotExists "pod-a" "test-namespace"
  1597  assertPodExists "pod-b" "test-namespace"
  1598  assertPodExists "pod-c" "test-namespace"
  1599  assertPodExists "pod-d" "test-namespace"
  1600  printResult
  1601  
  1602  ###########################################################
  1603  #  Test --rg-file flag on live init commands
  1604  ###########################################################
  1605  
  1606  createTestSuite
  1607  waitForDefaultServiceAccount
  1608  
  1609  # Setup: kpt live init with custom resourcegroup file
  1610  # Applies resources in "test-case-1c" directory
  1611  echo "Testing kpt live init with custom ResourceGroup file"
  1612  echo "kpt live init --rg-file=custom-rg.yaml e2e/live/testdata/test-case-1c"
  1613  ${BIN_DIR}/kpt live init --rg-file=custom-rg.yaml e2e/live/testdata/test-case-1c 2>&1 | tee $OUTPUT_DIR/status
  1614  assertContains "initializing \"custom-rg.yaml\" data (namespace: test-namespace)...success"
  1615  printResult
  1616  # Re-running live init should fail as ResourceGroup file already exists
  1617  ${BIN_DIR}/kpt live init --rg-file=custom-rg.yaml e2e/live/testdata/test-case-1c 2>&1 | tee $OUTPUT_DIR/status
  1618  assertContains "initializing \"custom-rg.yaml\" data (namespace: test-namespace)...failed"
  1619  printResult
  1620  
  1621  # Run: kpt live apply with custom resourcegroup file
  1622  echo "Testing kpt live apply with custom ResourceGroup filename"
  1623  echo "kpt live apply e2e/live/testdata/test-case-1c"
  1624  ${BIN_DIR}/kpt live apply e2e/live/testdata/test-case-1c 2>&1 | tee $OUTPUT_DIR/status
  1625  cat $OUTPUT_DIR/status
  1626  assertKptLiveApplyEquals << EOF
  1627  installing inventory ResourceGroup CRD.
  1628  inventory update started
  1629  inventory update finished
  1630  apply phase started
  1631  namespace/test-namespace apply successful
  1632  apply phase finished
  1633  reconcile phase started
  1634  namespace/test-namespace reconcile successful
  1635  reconcile phase finished
  1636  apply phase started
  1637  pod/pod-a apply successful
  1638  pod/pod-b apply successful
  1639  pod/pod-c apply successful
  1640  apply phase finished
  1641  reconcile phase started
  1642  pod/pod-a reconcile pending
  1643  pod/pod-b reconcile pending
  1644  pod/pod-c reconcile pending
  1645  pod/pod-a reconcile successful
  1646  pod/pod-b reconcile successful
  1647  pod/pod-c reconcile successful
  1648  reconcile phase finished
  1649  inventory update started
  1650  inventory update finished
  1651  apply result: 4 attempted, 4 successful, 0 skipped, 0 failed
  1652  reconcile result: 4 attempted, 4 successful, 0 skipped, 0 failed, 0 timed out
  1653  EOF
  1654  # Validate resources in the cluster
  1655  # ResourceGroup inventory with four inventory items.
  1656  assertRGInventory "test-namespace" "4"
  1657  assertPodExists "pod-a" "test-namespace"
  1658  assertPodExists "pod-b" "test-namespace"
  1659  assertPodExists "pod-c" "test-namespace"
  1660  printResult
  1661  
  1662  echo "Testing live destroy with custom ResourceGroup filename"
  1663  echo "kpt live destroy --rg-file=custom-rg.yaml e2e/live/testdata/test-case-1c"
  1664  ${BIN_DIR}/kpt live destroy e2e/live/testdata/test-case-1c 2>&1 | tee $OUTPUT_DIR/status
  1665  assertKptLiveApplyEquals << EOF
  1666  delete phase started
  1667  pod/pod-c delete successful
  1668  pod/pod-b delete successful
  1669  pod/pod-a delete successful
  1670  delete phase finished
  1671  reconcile phase started
  1672  pod/pod-c reconcile pending
  1673  pod/pod-b reconcile pending
  1674  pod/pod-a reconcile pending
  1675  pod/pod-b reconcile successful
  1676  pod/pod-c reconcile successful
  1677  pod/pod-a reconcile successful
  1678  reconcile phase finished
  1679  delete phase started
  1680  namespace/test-namespace delete successful
  1681  delete phase finished
  1682  reconcile phase started
  1683  namespace/test-namespace reconcile pending
  1684  namespace/test-namespace reconcile successful
  1685  reconcile phase finished
  1686  inventory update started
  1687  inventory update finished
  1688  delete result: 4 attempted, 4 successful, 0 skipped, 0 failed
  1689  reconcile result: 4 attempted, 4 successful, 0 skipped, 0 failed, 0 timed out
  1690  EOF
  1691  # Validate resources DESTROYED in the cluster
  1692  assertPodNotExists "pod-a" "test-namespace"
  1693  assertPodNotExists "pod-b" "test-namespace"
  1694  assertPodNotExists "pod-c" "test-namespace"
  1695  printResult
  1696  
  1697  # Clean-up the k8s cluster
  1698  echo "Cleaning up cluster"
  1699  cp -f e2e/live/testdata/Kptfile e2e/live/testdata/rg-test-case-1a/
  1700  cp -f e2e/live/testdata/Kptfile e2e/live/testdata/rg-test-case-1b/
  1701  cp -f e2e/live/testdata/Kptfile e2e/live/testdata/continue-on-error/
  1702  cp -f e2e/live/testdata/Kptfile e2e/live/testdata/migrate-case-1a/
  1703  cp -f e2e/live/testdata/Kptfile e2e/live/testdata/migrate-case-1b/
  1704  cp -f e2e/live/testdata/Kptfile e2e/live/testdata/migrate-error/
  1705  kind delete cluster
  1706  echo -e "Cleaning up cluster...${GREEN}SUCCESS${NC}"
  1707  
  1708  # Return error code if tests have failed
  1709  if [[ ${HAS_TEST_FAILURE} -gt 0 ]]; then
  1710      echo -e "${RED}ERROR: E2E Tests Failed${NC}"
  1711      exit ${HAS_TEST_FAILURE}
  1712  else
  1713      echo -e "${GREEN}SUCCESS: E2E Tests Passed${NC}"
  1714      exit 0
  1715  fi