Skip to content

Commit

Permalink
Merge pull request #2010 from sthaha/login-as-cmo
Browse files Browse the repository at this point in the history
MON-3253: refactor local-cmo.sh to use CMO SA by default
  • Loading branch information
openshift-merge-robot committed Jun 26, 2023
2 parents 899104b + edf4728 commit 8d67591
Show file tree
Hide file tree
Showing 3 changed files with 215 additions and 89 deletions.
2 changes: 1 addition & 1 deletion .gitignore
@@ -1,7 +1,7 @@
/operator

jsonnet/vendor/
tmp/
/tmp

# These are empty target files, created on every docker build. Their sole
# purpose is to track the last target execution time to evaluate, whether the
Expand Down
12 changes: 11 additions & 1 deletion Makefile
Expand Up @@ -62,9 +62,19 @@ clean:
# Building #
############

# run-local builds and runs operator out of cluster.
# use make run-local SWITCH_TO_CMO=false to not switch the login to CMO
# service-account. E.g. when logged in kube:admin and what to run operator
# as kube:admin
.PHONY: run-local
run-local: build
PATH="$(PATH):$(BIN_DIR)" KUBECONFIG=$(KUBECONFIG) ./hack/local-cmo.sh
@if $${SWITCH_TO_CMO:-true} ; then \
PATH="$(PATH):$(BIN_DIR)" \
KUBECONFIG=$(KUBECONFIG) ./hack/local-cmo.sh ;\
else \
PATH="$(PATH):$(BIN_DIR)" \
KUBECONFIG=$(KUBECONFIG) ./hack/local-cmo.sh --no-cmo-login ;\
fi

.PHONY: build
build: operator
Expand Down
290 changes: 203 additions & 87 deletions hack/local-cmo.sh
@@ -1,112 +1,228 @@
#!/usr/bin/env bash
set -eu -o pipefail

# Script will:
# 1. Patch CVO to exclude CMO from being managed
# 2. Scale in-cluster CMO to 0
# 3. Try to run CMO locally (CMO needs to be built before starting)
# Global Config
declare LOGIN_AS_CMO=true
declare SHOW_USAGE=false
declare DRY_RUN=${DRY_RUN:-false}

# constants
PROJECT_ROOT="$(git rev-parse --show-toplevel)"

validate() {
local ret=0

[[ -z ${KUBECONFIG+xxx} ]] && {
echo "ERROR: KUBECONFIG is not defined"
ret=1
}

[[ -x operator ]] || {
echo "ERROR: Failed to find 'operator' binary."
echo " Did you run 'make run-local' or 'make build' ?"
ret=1
}

gojsontoyaml --help 2>/dev/null || {
echo "ERROR: gojsontoyaml not found. See: https://github.com/brancz/gojsontoyaml#install"
ret=1
}

jq --version >/dev/null || {
echo "ERROR: jq not found. See: https://stedolan.github.io/jq/download/"
ret=1
}

return $ret
declare -r PROJECT_ROOT
declare -r CMO_KUBECONFIG="$PROJECT_ROOT/tmp/cmo-kubeconfig"
declare -r MON_NS='openshift-monitoring'

info() {
echo " 🔔 $*" >&2
}

ok() {
echo "$*" >&2
}

err() {
echo " 🛑 $*" >&2
}

die() {
echo -e "\n ✋ $* " >&2
echo -e "──────────────────── ⛔️⛔️⛔️ ────────────────────────\n" >&2
exit 1
}

run() {
echo -e "$*\n" >&2
$DRY_RUN && return 0

"$@"
}

kc() {
kubectl -n openshift-monitoring "$@"
run kubectl -n "$MON_NS" "$@"
}

validate() {
local ret=0

[[ -z ${KUBECONFIG+xxx} ]] && {
err "KUBECONFIG is not defined"
ret=1
}

gojsontoyaml --help 2>/dev/null || {
err "gojsontoyaml not found. See: https://github.com/brancz/gojsontoyaml#install"
ret=1
}

jq --version >/dev/null || {
err "jq not found. See: https://stedolan.github.io/jq/download/"
ret=1
}

ok "validations passed"

return $ret
}

disable_managed_cmo(){
# NOTE: we can't kubectl patch the spec.overrides since 'overrides'
# does not define the patch strategy.
# See: https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/#notes-on-the-strategic-merge-patch
#
# So, as a workaround, we get the entire contents of the `spec.overrides` and
# use jq to merge the override that puts "cluster-monitoring-operator" in
# unmanaged state.

local merge
merge=$(cat <<-__EOF
{
"spec": {
"overrides": [
[ .spec | .? | .overrides[] | .? | select(.name != "cluster-monitoring-operator")] +
[{
"group": "apps",
"kind": "Deployment",
"name": "cluster-monitoring-operator",
"namespace": "openshift-monitoring",
"unmanaged": true
}]
] | flatten
}
}
__EOF
)

local overrides
overrides=$(kubectl get clusterversion version -o json | jq "$merge" | gojsontoyaml)
kubectl patch clusterversion/version --type=merge -p="$overrides"

echo "Disabling incluster operator "
kc scale --replicas=0 deployment/cluster-monitoring-operator
disable_managed_cmo() {
# NOTE: we can't kubectl patch the spec.overrides since 'overrides'
# does not define the patch strategy.
# See: https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/#notes-on-the-strategic-merge-patch
#
# So, as a workaround, we get the entire contents of the `spec.overrides` and
# use jq to merge the override that puts "cluster-monitoring-operator" in
# unmanaged state.

local merge
merge=$(
cat <<-__EOF
{
"spec": {
"overrides": [
[ .spec | .? | .overrides[] | .? | select(.name != "cluster-monitoring-operator")] +
[{
"group": "apps",
"kind": "Deployment",
"name": "cluster-monitoring-operator",
"namespace": "$MON_NS",
"unmanaged": true
}]
] | flatten
}
}
__EOF
)

local overrides
overrides=$(kubectl get clusterversion version -o json | jq "$merge" | gojsontoyaml)
run kubectl patch clusterversion/version --type=merge -p="$overrides"

info "Disabling incluster operator "
kc scale --replicas=0 deployment/cluster-monitoring-operator
}

images_from_deployment() {
kc get deployment cluster-monitoring-operator -o json | jq -r '.spec.template.spec.containers[] | select(.name=="cluster-monitoring-operator") | .args[] | select(.|test("\\-images.*"))'
kubectl -n "$MON_NS" get deployment cluster-monitoring-operator -o json |
jq -r '.spec.template.spec.containers[] | select(.name=="cluster-monitoring-operator") | .args[] | select(.|test("\\-images.*"))'
}

run() {
echo "Running: $*"
"$@"
#create as new kubeconfig for cmo service-account
create_cmo_kubeconfig() {
local cmo_kubeconfig="$1"
shift

local cmo_token="$PROJECT_ROOT/tmp/cmo-token"
local api_server
api_server=$(oc whoami --show-server)

# NOTE: do not generate KUBECONFIG if the its already usable
if [[ -f "$cmo_kubeconfig" ]]; then
run oc --kubeconfig="$cmo_kubeconfig" get prometheus -n "$MON_NS" && return 0
fi

info "Generating a new token for CMO at - $cmo_token"
run oc create -n "$MON_NS" token cluster-monitoring-operator >"$cmo_token"
echo -n >"$cmo_kubeconfig"

info "Creating a new KUBECONFIG file for CMO at - $cmo_kubeconfig"
run oc --kubeconfig="$cmo_kubeconfig" login --token="$(cat "$cmo_token")" "$api_server"
run oc --kubeconfig="$cmo_kubeconfig" whoami
run oc --kubeconfig="$cmo_kubeconfig" project openshift-monitoring
run oc --kubeconfig="$cmo_kubeconfig" get prometheus -n "$MON_NS"
}

parse_args() {
### while there are args parse them
while [[ -n "${1+xxx}" ]]; do
case $1 in
-h | --help)
SHOW_USAGE=true
break
;; # exit the loop
--dry-run)
DRY_RUN=true
shift
;;
-x | --no-cmo-login)
LOGIN_AS_CMO=false
shift
;;
*) return 1 ;; # show usage on everything else
esac
done
return 0
}

main(){
# go to project root
cd "$(git rev-parse --show-cdup)"
print_usage() {
local scr
scr="$(basename "$0")"

validate || exit 1
disable_managed_cmo
read -r -d '' help <<-EOF_HELP || true
$scr performs the following actions:
1. Patches CVO to configure the cluster-monitoring-operator (CMO) in unmanaged mode.
2. Scales down the in-cluster CMO to 0.
3. Creates a new kubeconfig files for CMO service-account.
4. Changes the currently logged-in user to the CMO service account.
5. Executes the CMO locally (using go run)
local operator_config=manifests/0000_50_cluster-monitoring-operator_04-config.yaml
local telemetry_conf=/tmp/telemetry-config.yaml
Usage: $scr [options]
gojsontoyaml -yamltojson < $operator_config |
jq -r '.data["metrics.yaml"]' > $telemetry_conf
Options:
* -h | --help: Display this help message.
* -x | --no-cmo-login: Run the operator as the currently logged-in user. (default: false)
* --dry-run: Do not execute and command, only print them
# NOTE: can't use readarray as it is missing in OSX
local -a images
while read -r img; do images+=( "$img" ); done < <(images_from_deployment)
EOF_HELP

echo -e "$help"
return 0

}

run ./operator "${images[@]}" \
-assets assets/ \
-telemetry-config $telemetry_conf \
-kubeconfig "${KUBECONFIG}" \
-namespace=openshift-monitoring \
-configmap=cluster-monitoring-config \
-logtostderr=true -v=4 2>&1 | tee operator.log
main() {
parse_args "$@" || {
print_usage
die "parsing arguments failed; see usage and options above"
}

$SHOW_USAGE && {
print_usage
exit 0
}

# go to project root so that all paths are relative to it
cd "$PROJECT_ROOT"
run mkdir -p "$PROJECT_ROOT/tmp"

validate || exit 1
disable_managed_cmo

local operator_config=manifests/0000_50_cluster-monitoring-operator_04-config.yaml
local telemetry_conf=/tmp/telemetry-config.yaml

gojsontoyaml -yamltojson <$operator_config |
jq -r '.data["metrics.yaml"]' >$telemetry_conf

# NOTE: can't use readarray as it is missing in OSX
local -a images
while read -r img; do images+=("$img"); done < <(images_from_deployment)

local kubeconfig="$KUBECONFIG"
$LOGIN_AS_CMO && {
create_cmo_kubeconfig "$CMO_KUBECONFIG"
kubeconfig="$CMO_KUBECONFIG"
}

info "Running operator as $(oc whoami)"

run go run ./cmd/operator/... "${images[@]}" \
-assets assets/ \
-telemetry-config $telemetry_conf \
-kubeconfig="$kubeconfig" \
-namespace=openshift-monitoring \
-configmap=cluster-monitoring-config \
-logtostderr=true -v=4 2>&1 | tee tmp/operator.log
}

main "$@"

0 comments on commit 8d67591

Please sign in to comment.