Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,6 @@ HELM_DEP_UPDATE=${HELM_DEP_UPDATE:-"false"}
binaries_check "${COMMON_BINS[@]}"
helm_check

cd "$SCRIPT_DIR/.."
cd "$PARENT_ROOT"

trap cleanup_tars EXIT
201 changes: 201 additions & 0 deletions scripts/staging/kubectl-oci.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
#!/usr/bin/env bash
# Manage kubectl plugin binaries as OCI artifacts.
# Supports both pushing and pulling operations.
# Usage:
# Push: ./kubectl-oci.sh push --tag <tag> --namespace <namespace> [--username <user> --password <token>]
# Pull: ./kubectl-oci.sh pull --tag <tag> --namespace <namespace> [--username <user> --password <token>]

set -euo pipefail

SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]:-"$0"}")")"
ROOT_DIR="$SCRIPT_DIR/../"

# shellcheck source=../utils/log.sh
source "$ROOT_DIR/utils/log.sh"

ACTION=""
TAG=""
NAMESPACE=""
USERNAME=""
PASSWORD=""
REGISTRY="ghcr.io"
PLUGIN="${PLUGIN:-"mayastor"}"
NO_LOGIN=false

usage() {
cat << EOF
Usage: $0 <action> [options]

Actions:
push Push kubectl binaries to $REGISTRY as OCI artifacts
pull Pull kubectl binaries from $REGISTRY OCI artifacts

Options:
--tag <tag> Release tag (required)
--registry <registry> The registry to push/pull from [default=$REGISTRY]
--namespace <namespace> Namespace path (required)
--username <username> Registry username (optional if already logged in)
--password <password> Registry token/password (optional if already logged in)
--no-login Skip login check (useful for CI/CD with pre-auth)
-h, --help Show this help message

Examples:
$0 push --tag v1.0.0 --namespace $PLUGIN/dev --username user --password token
$0 pull --tag v1.0.0 --namespace $PLUGIN/dev
EOF
}

parse_args() {
if [[ $# -lt 1 ]]; then
usage
log_fatal "Error: Action required (push or pull)"
fi

ACTION="$1"
shift

case "$ACTION" in
push|pull)
;;
*)
usage
log_fatal "Error: Invalid action '$ACTION'. Must be 'push' or 'pull'"
;;
esac

while [[ $# -gt 0 ]]; do
case $1 in
--tag)
TAG="$2"
shift 2
;;
--namespace)
NAMESPACE="$2"
shift 2
;;
--registry)
REGISTRY="$2"
shift 2
;;
--username)
USERNAME="$2"
shift 2
;;
--password)
PASSWORD="$2"
shift 2
;;
--no-login)
NO_LOGIN=true
shift
;;
-h|--help)
usage
exit 0
;;
*)
usage
log_fatal "Unknown option: $1"
;;
esac
done

if [[ -z "$TAG" ]] || [[ -z "$NAMESPACE" ]]; then
usage
log_fatal "Error: --tag and --namespace are required"
fi

if [[ -z "${USERNAME:-}" || -z "${PASSWORD:-}" ]]; then
echo "⚠️ No username/password provided — will attempt to use existing oras login session for ${REGISTRY}"
fi

REPOSITORY="${REGISTRY}/${NAMESPACE}/kubectl-${PLUGIN}"
}

# Login to registry (only if needed)
login_registry() {
echo "Checking login status for ${REGISTRY}..."

if oras login "${REGISTRY}" --get >/dev/null 2>&1; then
echo "Already logged in to ${REGISTRY}"
return 0
fi

if [[ -z "${USERNAME:-}" || -z "${PASSWORD:-}" ]]; then
log_fatal "Error: Not logged in to ${REGISTRY} and no credentials provided. Use --username and --password."
fi

echo "Logging in to ${REGISTRY}..."
echo "${PASSWORD}" | oras login "${REGISTRY}" --username "${USERNAME}" --password-stdin
}

# Push kubectl binaries to registry
push_artifacts() {
echo "Pushing kubectl binaries to ${REPOSITORY} with tag ${TAG}"

# Check if artifacts directory exists
if [[ ! -d "artifacts" ]]; then
log_fatal "Error: artifacts directory not found"
fi

# Create a combined tarball of all kubectl binaries
echo "Creating combined tarball of all kubectl binaries..."
local combined_tar="kubectl-$PLUGIN-all-platforms-${TAG}.tar.gz"

tar -czf "${combined_tar}" -C artifacts .

echo "Pushing combined tarball to ${REPOSITORY}:${TAG}"

oras push "${REPOSITORY}:${TAG}" \
--artifact-type application/vnd.$PLUGIN.kubectl.bundle.v1+tar+gzip \
"${combined_tar}"

rm -f "${combined_tar}"

echo "All kubectl binaries pushed successfully as a single bundle!"
echo "Bundle available at: ${REPOSITORY}:${TAG}"
}

# Pull kubectl binaries from registry
pull_artifacts() {
echo "Pulling kubectl binaries bundle from ${REPOSITORY} for release ${TAG}"

echo "Pulling kubectl bundle..."
oras pull "${REPOSITORY}:${TAG}"

local bundle_tar="kubectl-$PLUGIN-all-platforms-${TAG}.tar.gz"

if [[ ! -f "$bundle_tar" ]]; then
log_fatal "Error: Could not find kubectl bundle tarball"
fi

echo "Extracting bundle to artifacts directory"

mkdir -p artifacts/
tar -xzf "$bundle_tar" -C artifacts/
rm -f "$bundle_tar"

echo "Contents of artifacts directory after extraction:"
ls -la artifacts/

echo "All kubectl binaries pulled successfully!"
}

main() {
parse_args "$@"

if [[ "$NO_LOGIN" == false ]]; then
login_registry
fi

case "$ACTION" in
push)
push_artifacts
;;
pull)
pull_artifacts
;;
esac
}

main "$@"
93 changes: 93 additions & 0 deletions scripts/staging/mirror-images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/usr/bin/env bash

# Mirror container images from source registry to target registry using crane.
# Preserves multi-platform support and image digests.

set -euo pipefail

# --- Determine paths based on CHART_REPO ---
SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]:-"$0"}")")"
source "${SCRIPT_DIR}/../utils/log.sh"

# --- Default Variables ---
CHART_REPO="false"
SOURCE=""
TARGET=""
TAG=""

# --- Parse arguments ---
for ((i=1; i <= $#; i++)); do
case "${!i}" in
--chart)
next=$((i+1))
if [[ $next -le $# ]]; then
CHART_REPO="${!next}"
fi
;;
esac
done

while [[ $# -gt 0 ]]; do
case $1 in
--source)
SOURCE="$2"
shift 2
;;
--target)
TARGET="$2"
shift 2
;;
--tag)
TAG="$2"
shift 2
;;
--chart)
CHART_REPO="$2";
shift 2
;;
*)
log_fatal "Unknown option: $1"
;;
esac
done

if [[ -z "$SOURCE" ]] || [[ -z "$TARGET" ]] || [[ -z "$TAG" ]]; then
log_fatal "Usage: $0 --source <source> --target <target> --tag <tag> [--chart true|false]"
fi

# --- Determine paths based on CHART_REPO ---
if [[ "${CHART_REPO}" == "true" ]]; then
ROOT_DIR="${SCRIPT_DIR}/../../../../../../"
: "${PARENT_ROOT_DIR:=$ROOT_DIR}"
export SOURCE_REL="$PARENT_ROOT_DIR/dependencies/control-plane/utils/dependencies/scripts/release.sh"
else
ROOT_DIR="${SCRIPT_DIR}/../../../../"
: "${PARENT_ROOT_DIR:=$ROOT_DIR}"
export SOURCE_REL="$PARENT_ROOT_DIR/utils/dependencies/scripts/release.sh"
fi

# Store the tag as it gets overriden by release.sh
input_tag="$TAG"

NO_RUN=true . "$PARENT_ROOT_DIR/scripts/release.sh"

# Restore it post sourcing release.sh
TAG="$input_tag"

IMAGES=()
for name in $DEFAULT_IMAGES; do
image=$($NIX_EVAL -f "$PARENT_ROOT_DIR" "images.$BUILD_TYPE.$name.imageName" --raw --quiet --argstr product_prefix "$PRODUCT_PREFIX")
IMAGES+=("${image##*/}")
done

echo "Mirroring images from ${SOURCE} to ${TARGET} with tag ${TAG}"

for IMAGE in "${IMAGES[@]}"; do
echo "Mirroring ${IMAGE}:${TAG}..."

SRC="${SOURCE}/${IMAGE}:${TAG}"
DEST="${TARGET}/${IMAGE}:${TAG}"
crane copy --platform all "${SRC}" "${DEST}"

echo "Successfully mirrored ${IMAGE}:${TAG}"
done
20 changes: 20 additions & 0 deletions scripts/staging/shell.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{ pkgs ? import (import ../../nix/sources.nix).nixpkgs {
overlays = [ (_: _: { inherit (import ../../nix/sources.nix); }) (import ../../nix/overlay.nix { }) ];
}
}:
pkgs.mkShellNoCC {
name = "staging-shell";
buildInputs = with pkgs; [
oras
crane
yq-go
jq
] ++ pkgs.lib.optional (builtins.getEnv "IN_NIX_SHELL" == "pure" && pkgs.system != "aarch64-darwin") [
docker
git
curl
nix
kubernetes-helm-wrapped
cacert
];
}
Loading