github.com/GoogleContainerTools/kpt@v1.0.0-beta.50.0.20240520170205-c25345ffcbee/e2e/live/end-to-end-test.sh (about)

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