github.com/percona/percona-xtradb-cluster-operator@v1.14.0/e2e-tests/smart-update2/run (about)

     1  #!/bin/bash
     2  # CASES:
     3  # - Check telemetry in minimal cluster with `upgradeOptions.apply: "disabled"` and `DISABLE_TELEMETRY=false` in the operator
     4  # - Check telemetry in minimal cluster with custom `upgradeOptions.apply` and `DISABLE_TELEMETRY=true` in the operator
     5  # - Check telemetry in minimal cluster with `upgradeOptions.apply: "disabled"` and `DISABLE_TELEMETRY=true` in the operator
     6  # - Update cluster with version service offline
     7  # - Update cluster with recommended image by version service
     8  # - Update cluster with the latest image by version service
     9  # - Update cluster with explicitly specified image inside version service
    10  
    11  set -o errexit
    12  
    13  test_dir=$(realpath $(dirname $0))
    14  . ${test_dir}/../functions
    15  
    16  set_debug
    17  
    18  API='pxc.percona.com/v9-9-9'
    19  TARGET_IMAGE_PXC=${IMAGE_PXC}
    20  CLUSTER="smart-update"
    21  CLUSTER_SIZE=3
    22  PROXY_SIZE=2
    23  
    24  if [[ ${TARGET_IMAGE_PXC} == *"percona-xtradb-cluster-operator"* ]]; then
    25  	PXC_VER=$(echo -n "${TARGET_IMAGE_PXC}" | $sed -r 's/.*([0-9].[0-9])$/\1/')
    26  else
    27  	PXC_VER=$(echo -n "${TARGET_IMAGE_PXC}" | $sed -r 's/.*:([0-9]+\.[0-9]+).*$/\1/')
    28  fi
    29  TARGET_IMAGE_PXC_VS="perconalab/percona-xtradb-cluster-operator:main-pxc${PXC_VER}"
    30  VS_URL="http://version-service"
    31  VS_PORT="11000"
    32  VS_ENDPOINT="${VS_URL}:${VS_PORT}"
    33  
    34  function get_pod_names_images {
    35  	local cluster=${1}
    36  	local type=${2:-pxc}
    37  
    38  	echo -e $(kubectl_bin get pods -l "app.kubernetes.io/instance=${cluster},app.kubernetes.io/component=${type}" \
    39  		-o jsonpath="{range .items[*]}{.metadata.name}{\",\"}{.spec.containers[?(@.name == \"${type}\")].image}{\"\n\"}{end}")
    40  }
    41  
    42  function check_last_pod_to_update {
    43  	local cluster=${1}
    44  	local initial_primary=${2}
    45  	local pxc_size=${3}
    46  	local target_image=${4}
    47  
    48  	set +x
    49  	echo -n "Waiting for the last pod to update"
    50  	local i=0
    51  	local max=720
    52  	until [[ "$(kubectl_bin get pxc "${cluster}" -o jsonpath='{.status.state}')" == "ready" ]]; do
    53  		echo -n "."
    54  		updated_pods_count=0
    55  		for entry in $(get_pod_names_images "${cluster}"); do
    56  			if [[ -n "$(echo ${entry} | grep ${target_image})" ]]; then
    57  				((updated_pods_count += 1))
    58  			fi
    59  		done
    60  
    61  		if [[ ${updated_pods_count} == $((pxc_size - 1)) ]]; then
    62  			if [[ -n $(get_pod_names_images "${cluster}" | grep "${initial_primary}" | grep "${IMAGE_PXC}") ]]; then
    63  				echo
    64  				echo "${initial_primary} is REALLY the last one to update"
    65  				break
    66  			else
    67  				echo "${initial_primary} is not the last one to update. Exiting..."
    68  				exit 1
    69  			fi
    70  		fi
    71  		if [[ $i -ge $max ]]; then
    72  			echo "Something went wrong waiting for the last pod to update!"
    73  			exit 1
    74  		fi
    75  		let i+=1
    76  		sleep 1
    77  	done
    78  	set -x
    79  }
    80  
    81  function deploy_version_service {
    82  	desc 'install version service'
    83  	kubectl_bin create configmap versions \
    84  		--from-file "${test_dir}/conf/operator.9.9.9.pxc-operator.dep.json" \
    85  		--from-file "${test_dir}/conf/operator.9.9.9.pxc-operator.json"
    86  	kubectl_bin apply -f "${test_dir}/conf/vs.yml"
    87  	sleep 10
    88  }
    89  
    90  function check_telemetry_transfer() {
    91  	local cr_vs_uri=${1}
    92  	local cr_vs_channel=${2:-"disabled"}
    93  	local telemetry_state=${3:-"enabled"}
    94  
    95  	desc 'create PXC minimal cluster'
    96  	cluster="minimal-cluster"
    97  
    98  	kubectl_bin apply -f "${conf_dir}/client.yml"
    99  	yq "${conf_dir}/secrets.yml" \
   100  		| yq eval "(. | select(.metadata.name == \"my-cluster-secrets\") | .metadata.name) = \"${cluster}\"" \
   101  		| kubectl_bin apply -f -
   102  
   103  	yq "${src_dir}/deploy/cr-minimal.yaml" \
   104  		| yq eval ".spec.upgradeOptions.versionServiceEndpoint=\"${cr_vs_uri}\"" \
   105  		| yq eval ".spec.upgradeOptions.apply=\"${cr_vs_channel}\"" \
   106  		| yq eval ".spec.initContainer.image=\"$IMAGE\"" \
   107  		| yq eval '.spec.crVersion="9.9.9"' \
   108  		| yq eval ".spec.pxc.image=\"$IMAGE_PXC\"" \
   109  		| yq eval ".spec.haproxy.image=\"$IMAGE_HAPROXY\"" \
   110  		| yq eval ".spec.logcollector.image=\"$IMAGE_LOGCOLLECTOR\"" \
   111  		| kubectl_bin apply -f -
   112  
   113  	desc 'check if Pod is started'
   114  	wait_for_running "$cluster-pxc" "1"
   115  	sleep 20
   116  	local proxy
   117  	proxy=$(get_proxy "$cluster")
   118  	wait_for_running "$proxy" 1
   119  
   120  	desc 'write data'
   121  	if [[ $IMAGE_PXC =~ 5\.7 ]] && [[ "$(is_keyring_plugin_in_use "$cluster")" ]]; then
   122  		encrypt='ENCRYPTION=\"Y\"'
   123  	fi
   124  	run_mysql \
   125  		"CREATE DATABASE IF NOT EXISTS myApp; use myApp; CREATE TABLE IF NOT EXISTS myApp (id int PRIMARY KEY) $encrypt;" \
   126  		"-h $proxy -uroot -proot_password -P$port"
   127  	run_mysql \
   128  		'INSERT myApp.myApp (id) VALUES (100500)' \
   129  		"-h $proxy -uroot -proot_password -P$port"
   130  
   131  	kubectl_bin logs "$(kubectl get pods --selector=run=version-service-cr -o jsonpath='{.items[0].metadata.name}')" \
   132  		| grep -E 'server request payload|unary call' \
   133  		| grep -Eo '\{.*\}' \
   134  		| jq 'del(."grpc.request.content".msg.customResourceUid)' \
   135  		| jq 'del(."grpc.request.content".msg.kubeVersion)' \
   136  		| jq 'del(."grpc.start_time")' \
   137  		| jq 'del(."grpc.time_ms")' \
   138  			>"${tmp_dir}/${telemetry_state}_telemetry.version-service-cr.log.json"
   139  
   140  	kubectl_bin logs "$(kubectl get pods --selector=run=version-service -o jsonpath='{.items[0].metadata.name}')" \
   141  		| grep -E 'server request payload|unary call' \
   142  		| grep -Eo '\{.*\}' \
   143  		| jq 'del(."grpc.request.content".msg.customResourceUid)' \
   144  		| jq 'del(."grpc.request.content".msg.kubeVersion)' \
   145  		| jq 'del(."grpc.start_time")' \
   146  		| jq 'del(."grpc.time_ms")' \
   147  			>"${tmp_dir}/${telemetry_state}_telemetry.version-service.log.json"
   148  
   149  	local telemetry_log_file="${telemetry_state}_telemetry.version-service${OPERATOR_NS:+-cw}.log.json"
   150  	desc "telemetry was disabled in CR but in operator not"
   151  	if [ "${cr_vs_channel}" == 'disabled' -a "${telemetry_state}" == 'enabled' ]; then
   152  		desc "operator fallback VS should have telemetry"
   153  		diff "${test_dir}/compare/${telemetry_log_file}" <(grep -f "${tmp_dir}/${telemetry_state}_telemetry.version-service.log.json" "${test_dir}/compare/${telemetry_log_file}")
   154  		desc "CR VS should not have telemetry"
   155  		[[ -s "${tmp_dir}/enabled_telemetry.version-service-cr.log.json" ]] && exit 1
   156  	fi
   157  
   158  	local image_prefix=${cr_vs_channel%'-recommended'}
   159  	local telemetry_cr_log_file="${telemetry_state}_telemetry.version-service-cr-${image_prefix}${OPERATOR_NS:+-cw}.log.json"
   160  	desc "telemetry was disabled in operator but not in CR"
   161  	if [ "${cr_vs_channel}" == "${image_prefix}-recommended" -a "${telemetry_state}" == 'disabled' ]; then
   162  		desc "cr VS should have telemetry"
   163  		diff "${test_dir}/compare/${telemetry_cr_log_file}" <(grep -f "${tmp_dir}/${telemetry_state}_telemetry.version-service-cr.log.json" "${test_dir}/compare/${telemetry_cr_log_file}")
   164  		desc "operator VS should not have telemetry"
   165  		[[ -s ${tmp_dir}/disabled_telemetry.version-service.log.json ]] && exit 1
   166  	fi
   167  
   168  	desc "telemetry was disabled in CR as well as in operator"
   169  	if [ "${cr_vs_channel}" == 'disabled' -a "${telemetry_state}" == 'disabled' ]; then
   170  		desc "CR VS should not have telemetry"
   171  		[[ -s ${tmp_dir}/disabled_telemetry.version-service-cr.log.json ]] && exit 1
   172  		desc "operator VS should not have telemetry"
   173  		[[ -s ${tmp_dir}/disabled_telemetry.version-service.log.json ]] && exit 1
   174  	fi
   175  
   176  	kubectl_bin patch pxc minimal-cluster --type=merge -p '{"metadata":{"finalizers":["delete-pxc-pvc"]}}'
   177  	kubectl_bin delete pod ${OPERATOR_NS:+-n $OPERATOR_NS} "$(get_operator_pod)"
   178  	kubectl_bin delete pxc --all
   179  	kubectl_bin delete deploy pxc-client
   180  	sleep 30
   181  }
   182  
   183  function main() {
   184  	create_infra "${namespace}"
   185  	deploy_version_service
   186  	deploy_cert_manager
   187  	IMAGE_PXC=$(kubectl_bin exec -ti "$(get_operator_pod)" ${OPERATOR_NS:+-n $OPERATOR_NS} -- curl -s "${VS_URL}.${namespace}.svc.cluster.local:${VS_PORT}/versions/v1/pxc-operator/9.9.9" | jq -r '.versions[].matrix.pxc[].imagePath' | grep ":${PXC_VER}" | sort -V | tail -n3 | head -n1)
   188  
   189  	kubectl_bin patch crd perconaxtradbclusters.pxc.percona.com --type='json' -p '[{"op":"add","path":"/spec/versions/-", "value":{"name": "v9-9-9","schema": {"openAPIV3Schema": {"properties": {"spec": {"type": "object","x-kubernetes-preserve-unknown-fields": true},"status": {"type": "object", "x-kubernetes-preserve-unknown-fields": true}}, "type": "object" }}, "served": true, "storage": false, "subresources": { "status": {}}}}]'
   190  	kubectl_bin ${OPERATOR_NS:+-n $OPERATOR_NS} set env deploy/percona-xtradb-cluster-operator "PERCONA_VS_FALLBACK_URI=http://version-service.${namespace}.svc.cluster.local:11000"
   191  
   192  	################################################
   193  	desc 'Starting telemetry testing'
   194  	$sed 's/version-service/version-service-cr/g' "${test_dir}/conf/vs.yml" \
   195  		| yq eval '(. | select(.kind == "Deployment") | .spec.template.spec.containers[0].image) = "'"$(yq 'select(.kind == "Deployment").spec.template.spec.containers[0].image' "${test_dir}/conf/vs.yml")"'"' \
   196  		| kubectl_bin apply -f -
   197  	kubectl_bin delete pod -l run=version-service
   198  	IMAGE_PREFIX="$(echo -n "$IMAGE_PXC" | sed -r 's/^.*:([0-9]+.[0-9]+).*/\1/')"
   199  	################################################
   200  	desc 'Enable telemetry on operator level'
   201  	kubectl_bin get deployment/percona-xtradb-cluster-operator -o yaml ${OPERATOR_NS:+-n $OPERATOR_NS} \
   202  		| yq '(.spec.template.spec.containers[0].env[] | select(.name == "DISABLE_TELEMETRY").value) = "false"' \
   203  		| kubectl_bin apply ${OPERATOR_NS:+-n $OPERATOR_NS} -f -
   204  	sleep 30
   205  
   206  	wait_pod "$(get_operator_pod)" "480" "${OPERATOR_NS}"
   207  
   208  	check_telemetry_transfer "http://version-service-cr.${namespace}.svc.cluster.local:11000" "disabled" "enabled"
   209  	################################################
   210  	desc "Disabling telemetry on the operator level"
   211  
   212  	kubectl_bin delete pod -l run=version-service-cr
   213  	kubectl_bin delete pod -l run=version-service
   214  	kubectl_bin get deployment/percona-xtradb-cluster-operator -o yaml ${OPERATOR_NS:+-n $OPERATOR_NS} \
   215  		| yq '(.spec.template.spec.containers[0].env[] | select(.name == "DISABLE_TELEMETRY").value) = "true"' \
   216  		| kubectl_bin apply ${OPERATOR_NS:+-n $OPERATOR_NS} -f -
   217  	sleep 30
   218  	wait_pod "$(get_operator_pod)" "480" "${OPERATOR_NS}"
   219  
   220  	check_telemetry_transfer "http://version-service-cr.${namespace}.svc.cluster.local:11000" "${IMAGE_PREFIX}-recommended" "disabled"
   221  	kubectl_bin delete pod -l run=version-service-cr
   222  	kubectl_bin delete pod -l run=version-service
   223  	check_telemetry_transfer "http://version-service-cr.${namespace}.svc.cluster.local:11000" "disabled" "disabled"
   224  	#################################################
   225  	kubectl_bin delete deployment version-service-cr
   226  	desc 'Telemetry testing finished'
   227  	##################################################
   228  	desc 'PXC cluster with version service offline'
   229  	cp -f "${test_dir}/conf/${CLUSTER}-version-service-unreachable.yml" "${tmp_dir}/${CLUSTER}-version-service-unreachable.yml"
   230  	yq -i eval ".spec.initContainer.image = \"${IMAGE}\"" "${tmp_dir}/${CLUSTER}-version-service-unreachable.yml"
   231  	spinup_pxc "${CLUSTER}" "${tmp_dir}/${CLUSTER}-version-service-unreachable.yml"
   232  
   233  	wait_cluster_consistency "${CLUSTER}" "${CLUSTER_SIZE}" "${PROXY_SIZE}"
   234  	if [[ "$(kubectl_bin get pxc/${CLUSTER} -o jsonpath='{.spec.pxc.image}')" != "${IMAGE_PXC}" ]]; then
   235  		echo "ERROR: PXC image has been changed. Exiting..."
   236  		exit 1
   237  	fi
   238  
   239  	##################################################
   240  	desc 'PXC cluster update with recommended image by version service'
   241  	vs_image="recommended"
   242  	initial_primary=$(run_mysql 'SELECT @@hostname hostname;' "-h ${CLUSTER}-haproxy -uroot -proot_password")
   243  
   244  	kubectl_bin patch pxc/"${CLUSTER}" --type=merge -p '{"spec":{"upgradeOptions":{"versionServiceEndpoint":"'${VS_ENDPOINT}'","apply":"'${vs_image}'","schedule": "* * * * *"}}}'
   245  	sleep 55
   246  
   247  	check_last_pod_to_update "${CLUSTER}" "${initial_primary}" "${CLUSTER_SIZE}" "${TARGET_IMAGE_PXC_VS}"
   248  	wait_cluster_consistency "${CLUSTER}" "${CLUSTER_SIZE}" "${PROXY_SIZE}"
   249  	for i in $(seq 0 $((CLUSTER_SIZE - 1))); do
   250  		compare_mysql_cmd "select-1" "SELECT * from myApp.myApp;" "-h ${CLUSTER}-pxc-${i}.${CLUSTER}-pxc -uroot -proot_password"
   251  	done
   252  
   253  	kubectl_bin delete -f "${tmp_dir}/${CLUSTER}-version-service-unreachable.yml"
   254  	kubectl_bin delete pvc --all
   255  
   256  	##################################################
   257  	desc 'PXC cluster update with the latest image by version service'
   258  	spinup_pxc "${CLUSTER}" "${tmp_dir}/${CLUSTER}-version-service-unreachable.yml"
   259  	vs_image="latest"
   260  	initial_primary=$(run_mysql 'SELECT @@hostname hostname;' "-h ${CLUSTER}-haproxy -uroot -proot_password")
   261  
   262  	kubectl_bin patch pxc/"${CLUSTER}" --type=merge -p '{"spec":{"upgradeOptions":{"versionServiceEndpoint":"'${VS_ENDPOINT}'","apply":"'${vs_image}'","schedule": "* * * * *"}}}'
   263  	sleep 55
   264  
   265  	check_last_pod_to_update "${CLUSTER}" "${initial_primary}" "${CLUSTER_SIZE}" "${TARGET_IMAGE_PXC_VS}"
   266  	wait_cluster_consistency "${CLUSTER}" "${CLUSTER_SIZE}" "${PROXY_SIZE}"
   267  	for i in $(seq 0 $((CLUSTER_SIZE - 1))); do
   268  		compare_mysql_cmd "select-1" "SELECT * from myApp.myApp;" "-h ${CLUSTER}-pxc-${i}.${CLUSTER}-pxc -uroot -proot_password"
   269  	done
   270  
   271  	kubectl_bin delete -f "${tmp_dir}/${CLUSTER}-version-service-unreachable.yml"
   272  	kubectl_bin delete pvc --all
   273  
   274  	##################################################
   275  	desc 'PXC cluster update with explicitly specified image inside version service'
   276  	spinup_pxc "${CLUSTER}" "${tmp_dir}/${CLUSTER}-version-service-unreachable.yml"
   277  	vs_image=$(kubectl_bin exec -ti "$(get_operator_pod)" ${OPERATOR_NS:+-n $OPERATOR_NS} -- curl -s "${VS_URL}.${namespace}.svc.cluster.local:${VS_PORT}/versions/v1/pxc-operator/9.9.9" | jq -r '.versions[].matrix.pxc[].imagePath' | grep ":${PXC_VER}" | sort -V | tail -n2 | head -n1)
   278  	initial_primary=$(run_mysql 'SELECT @@hostname hostname;' "-h ${CLUSTER}-haproxy -uroot -proot_password")
   279  
   280  	kubectl_bin patch pxc/"${CLUSTER}" --type=merge -p '{"spec":{"upgradeOptions":{"versionServiceEndpoint":"'${VS_ENDPOINT}'","apply":"'${vs_image}'","schedule": "* * * * *"}}}'
   281  	sleep 55
   282  
   283  	check_last_pod_to_update "${CLUSTER}" "${initial_primary}" "${CLUSTER_SIZE}" "percona/percona-xtradb-cluster:${vs_image}"
   284  	wait_cluster_consistency "${CLUSTER}" "${CLUSTER_SIZE}" "${PROXY_SIZE}"
   285  	for i in $(seq 0 $((CLUSTER_SIZE - 1))); do
   286  		compare_mysql_cmd "select-1" "SELECT * from myApp.myApp;" "-h ${CLUSTER}-pxc-${i}.${CLUSTER}-pxc -uroot -proot_password"
   287  	done
   288  
   289  	kubectl_bin delete -f "${tmp_dir}/${CLUSTER}-version-service-unreachable.yml"
   290  	kubectl_bin delete pvc --all
   291  
   292  	desc 'cleanup'
   293  	kubectl_bin delete -f "${test_dir}/conf/vs.yml"
   294  	destroy "${namespace}"
   295  	desc "test passed"
   296  }
   297  
   298  main