Merge branch 'main' into update-strategy-feature
This commit is contained in:
commit
32afe9de42
|
|
@ -0,0 +1,234 @@
|
||||||
|
# Copilot Instructions for Helmfile
|
||||||
|
|
||||||
|
## Repository Overview
|
||||||
|
|
||||||
|
Helmfile is a tool for deploying Helm charts that manages Kubernetes deployments as code. It provides templating, environment management, and GitOps workflows for Helm chart deployments.
|
||||||
|
|
||||||
|
Helmfile is a declarative tool. In Helmfile, all elements of the desired state for deployments must be included in the `helmfile.yaml` config file and any associated files. Only operational matters can be provided dynamically, via command-line flags and environment variables.
|
||||||
|
|
||||||
|
**Key Details:**
|
||||||
|
- **Language:** Go 1.24.2+
|
||||||
|
- **Type:** CLI tool / Kubernetes deployment management
|
||||||
|
- **Size:** Large codebase (~229MB binary, 200+ dependencies)
|
||||||
|
- **Runtime:** Requires Helm 3.x as external dependency
|
||||||
|
- **Target Platform:** Linux/macOS/Windows, Kubernetes clusters
|
||||||
|
|
||||||
|
## Build and Validation Commands
|
||||||
|
|
||||||
|
### Essential Setup
|
||||||
|
Helmfile requires Helm 3.x and Kustomize 5.x as runtime dependencies:
|
||||||
|
```bash
|
||||||
|
# Check for Helm dependency (REQUIRED)
|
||||||
|
helm version # Must show version 3.x
|
||||||
|
|
||||||
|
# Initialize Helm plugins after helmfile installation
|
||||||
|
./helmfile init # Installs required helm-diff plugin
|
||||||
|
|
||||||
|
# Alternative: Force install without prompts
|
||||||
|
./helmfile init --force
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build Process
|
||||||
|
```bash
|
||||||
|
# Standard build (takes 2-3 minutes due to many dependencies)
|
||||||
|
make build
|
||||||
|
|
||||||
|
# Alternative direct build
|
||||||
|
go build -o helmfile .
|
||||||
|
|
||||||
|
# Build with test tools (required for integration tests, ~1 minute)
|
||||||
|
make build-test-tools # Creates diff-yamls and downloads dyff
|
||||||
|
|
||||||
|
# Cross-platform builds
|
||||||
|
make cross
|
||||||
|
```
|
||||||
|
|
||||||
|
**Build Timing:** First build downloads 200+ Go packages and takes 2-3 minutes. Subsequent builds are faster due to module cache. Test tools build is faster (~1 minute).
|
||||||
|
|
||||||
|
### Validation Pipeline
|
||||||
|
Run in this exact order to match CI requirements:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Code formatting and linting
|
||||||
|
make check # Run go vet (required - always works)
|
||||||
|
# Note: make fmt requires gci tool (go install github.com/daixiang0/gci@latest)
|
||||||
|
|
||||||
|
# 2. Unit tests (fast, ~30 seconds)
|
||||||
|
go test -v ./pkg/... -race -p=1
|
||||||
|
|
||||||
|
# 3. Integration tests (requires Kubernetes - see Environment Setup)
|
||||||
|
make integration # Takes 5-10 minutes, needs minikube/k8s cluster
|
||||||
|
|
||||||
|
# 4. E2E tests (optional, needs expect package)
|
||||||
|
sudo apt-get install expect # On Ubuntu/Debian
|
||||||
|
bash test/e2e/helmfile-init/init_linux.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linting Configuration
|
||||||
|
Uses golangci-lint with configuration in `.golangci.yaml`. Install via:
|
||||||
|
```bash
|
||||||
|
# For local development
|
||||||
|
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.1.6
|
||||||
|
golangci-lint run
|
||||||
|
```
|
||||||
|
|
||||||
|
**Critical Lint Rules:** staticcheck, errcheck, revive, unused. Fix lint errors before committing.
|
||||||
|
|
||||||
|
## Environment Setup Requirements
|
||||||
|
|
||||||
|
### Dependencies for Development
|
||||||
|
```bash
|
||||||
|
# Required for building/testing
|
||||||
|
go version # Must be 1.24.2+
|
||||||
|
helm version # Must be 3.x
|
||||||
|
kubectl version # For K8s integration
|
||||||
|
|
||||||
|
# Required for integration tests
|
||||||
|
minikube start # Or other K8s cluster
|
||||||
|
kustomize version # v5.2.1+ for some tests
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integration Test Environment
|
||||||
|
Integration tests require a running Kubernetes cluster:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using minikube (recommended for CI)
|
||||||
|
minikube start
|
||||||
|
export KUBECONFIG=$(minikube kubeconfig-path)
|
||||||
|
|
||||||
|
# Using kind (alternative)
|
||||||
|
kind create cluster --name helmfile-test
|
||||||
|
|
||||||
|
# Verify cluster access
|
||||||
|
kubectl cluster-info
|
||||||
|
```
|
||||||
|
|
||||||
|
**Timing:** Integration tests take 5-10 minutes and may fail due to timing issues in resource-constrained environments.
|
||||||
|
|
||||||
|
## Project Architecture and Layout
|
||||||
|
|
||||||
|
### Core Directory Structure
|
||||||
|
```
|
||||||
|
/
|
||||||
|
├── main.go # Entry point - CLI initialization and signal handling
|
||||||
|
├── cmd/ # CLI commands (apply, diff, sync, template, etc.)
|
||||||
|
│ ├── root.go # Main cobra command setup and global flags
|
||||||
|
│ ├── apply.go # helmfile apply command
|
||||||
|
│ ├── diff.go # helmfile diff command
|
||||||
|
│ └── ... # Other subcommands
|
||||||
|
├── pkg/ # Core library packages
|
||||||
|
│ ├── app/ # Main application logic and execution
|
||||||
|
│ ├── state/ # Helmfile state management and chart dependencies
|
||||||
|
│ ├── helmexec/ # Helm execution and command wrapper
|
||||||
|
│ ├── tmpl/ # Go template processing and functions
|
||||||
|
│ ├── environment/ # Environment and values management
|
||||||
|
│ └── ... # Other core packages
|
||||||
|
├── test/ # Test suites
|
||||||
|
│ ├── integration/ # Integration tests with real K8s clusters
|
||||||
|
│ ├── e2e/ # End-to-end user workflow tests
|
||||||
|
│ └── advanced/ # Advanced feature tests
|
||||||
|
├── docs/ # Documentation (mkdocs format)
|
||||||
|
├── examples/ # Example helmfile configurations
|
||||||
|
└── .github/workflows/ # CI/CD pipeline definitions
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Source Files
|
||||||
|
- **main.go:** Signal handling, CLI execution entry point
|
||||||
|
- **cmd/root.go:** Global CLI configuration, error handling, logging setup
|
||||||
|
- **pkg/app/app.go:** Main application orchestration, state management
|
||||||
|
- **pkg/state/state.go:** Helmfile state parsing, release management
|
||||||
|
- **pkg/helmexec/exec.go:** Helm command execution, version detection
|
||||||
|
|
||||||
|
### Configuration Files
|
||||||
|
- **go.mod/go.sum:** Go dependencies (many cloud providers, k8s libraries)
|
||||||
|
- **.golangci.yaml:** Linting rules and settings
|
||||||
|
- **Makefile:** Build targets and development workflows
|
||||||
|
- **mkdocs.yml:** Documentation generation configuration
|
||||||
|
- **.github/workflows/ci.yaml:** Complete CI pipeline definition
|
||||||
|
|
||||||
|
## Continuous Integration Pipeline
|
||||||
|
|
||||||
|
### GitHub Actions Workflow (`.github/workflows/ci.yaml`)
|
||||||
|
1. **Lint Job:** golangci-lint with custom configuration (~5 minutes)
|
||||||
|
2. **Test Job:** Unit tests + binary build (~10 minutes)
|
||||||
|
3. **Integration Job:** Tests with multiple Helm/Kustomize versions (~15-20 minutes each)
|
||||||
|
4. **E2E Job:** User workflow validation (~5 minutes)
|
||||||
|
|
||||||
|
**Matrix Testing:** CI tests against multiple Helm versions (3.17.x, 3.18.x) and Kustomize versions (5.2.x, 5.4.x).
|
||||||
|
|
||||||
|
### Pre-commit Validation Steps
|
||||||
|
Always run these locally before pushing:
|
||||||
|
```bash
|
||||||
|
make check # Format and vet (required)
|
||||||
|
go test ./pkg/... # Unit tests
|
||||||
|
make build # Verify build works
|
||||||
|
# Note: make fmt requires gci tool: go install github.com/daixiang0/gci@latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common CI Failure Causes
|
||||||
|
- **Linting errors:** Run `golangci-lint run` locally first
|
||||||
|
- **Integration test timeouts:** K8s cluster setup timing issues
|
||||||
|
- **Version compatibility:** Ensure Go 1.24.2+ and Helm 3.x
|
||||||
|
- **Race conditions:** Some tests are sensitive to parallel execution
|
||||||
|
|
||||||
|
## Development Gotchas and Known Issues
|
||||||
|
|
||||||
|
### Build Issues
|
||||||
|
- **Long initial build time:** First `make build` downloads 200+ packages (~2-3 minutes)
|
||||||
|
- **Memory usage:** Large binary size due to embedded dependencies
|
||||||
|
- **Git tags:** Build may show version warnings if not on tagged commit
|
||||||
|
- **Tool dependencies:** `make fmt` requires `gci` tool installation
|
||||||
|
|
||||||
|
### Testing Issues
|
||||||
|
- **Integration tests require K8s:** Will fail without cluster access
|
||||||
|
- **Test isolation:** Use `-p=1` flag to avoid race conditions
|
||||||
|
- **Minikube timing:** May need to wait for cluster ready state
|
||||||
|
- **Plugin dependencies:** Tests need helm-diff and helm-secrets plugins
|
||||||
|
|
||||||
|
### Runtime Requirements
|
||||||
|
- **Helm dependency:** Always required at runtime, not just build time (available in CI)
|
||||||
|
- **kubectl access:** Most operations need valid kubeconfig
|
||||||
|
- **Plugin management:** `helmfile init` must be run after installation
|
||||||
|
|
||||||
|
### Common Error Patterns
|
||||||
|
```bash
|
||||||
|
# Missing Helm
|
||||||
|
"helm: command not found" → Install Helm first
|
||||||
|
|
||||||
|
# Plugin missing
|
||||||
|
"Error: plugin 'diff' not found" → Run helmfile init
|
||||||
|
|
||||||
|
# K8s access
|
||||||
|
"connection refused" → Check kubectl cluster-info
|
||||||
|
|
||||||
|
# Permission errors
|
||||||
|
"permission denied" → Check kubeconfig and cluster access
|
||||||
|
|
||||||
|
# Missing tools
|
||||||
|
"gci: No such file or directory" → go install github.com/daixiang0/gci@latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Working with the Codebase
|
||||||
|
|
||||||
|
### Making Changes
|
||||||
|
- **Follow Helmfile design**: Helmfile is a declarative deployment tool. Anything that is part of the desired state of the deployments needs to be managed by Helmfile configs. Only operational knowledge that affects "how" to apply the desired state needs to be runtime options, like command-like flags and environment variables.
|
||||||
|
- **Small, focused changes:** Each PR should address single concern
|
||||||
|
- **Test coverage:** Add unit tests for new pkg/ functionality
|
||||||
|
- **Integration tests:** Update test-cases/ for new CLI features
|
||||||
|
- **Documentation:** Update docs/ for user-facing changes
|
||||||
|
|
||||||
|
### Key Packages to Understand
|
||||||
|
- **pkg/app:** Main business logic, start here for feature changes
|
||||||
|
- **pkg/state:** Helmfile parsing and release orchestration
|
||||||
|
- **cmd/:** CLI interface changes and new subcommands
|
||||||
|
- **pkg/helmexec:** Helm integration and command execution
|
||||||
|
|
||||||
|
### Architecture Patterns
|
||||||
|
- **Dependency injection:** App uses interfaces for testability
|
||||||
|
- **State management:** Immutable state objects, functional transforms
|
||||||
|
- **Error handling:** Custom error types with exit codes
|
||||||
|
- **Plugin system:** Extensible via Helm plugins and Go templates
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Trust these instructions:** This information is validated against the current codebase. Only search for additional details if these instructions are incomplete or found to be incorrect for your specific task.
|
||||||
|
|
@ -13,8 +13,8 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
cache: false
|
cache: false
|
||||||
|
|
@ -25,10 +25,10 @@ jobs:
|
||||||
tests:
|
tests:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|
@ -54,12 +54,12 @@ jobs:
|
||||||
# Helm maintains the latest minor version only and therefore each Helmfile version supports 2 Helm minor versions.
|
# Helm maintains the latest minor version only and therefore each Helmfile version supports 2 Helm minor versions.
|
||||||
# That's why we cover only 2 Helm minor versions in this matrix.
|
# That's why we cover only 2 Helm minor versions in this matrix.
|
||||||
# See https://github.com/helmfile/helmfile/pull/286#issuecomment-1250161182 for more context.
|
# See https://github.com/helmfile/helmfile/pull/286#issuecomment-1250161182 for more context.
|
||||||
- helm-version: v3.17.4
|
- helm-version: v3.18.6
|
||||||
kustomize-version: v5.2.1
|
kustomize-version: v5.2.1
|
||||||
plugin-secrets-version: 4.6.5
|
plugin-secrets-version: 4.6.5
|
||||||
plugin-diff-version: 3.11.0
|
plugin-diff-version: 3.11.0
|
||||||
extra-helmfile-flags: ''
|
extra-helmfile-flags: ''
|
||||||
- helm-version: v3.17.4
|
- helm-version: v3.18.6
|
||||||
kustomize-version: v5.4.3
|
kustomize-version: v5.4.3
|
||||||
# We assume that the helm-secrets plugin is supposed to
|
# We assume that the helm-secrets plugin is supposed to
|
||||||
# work with the two most recent helm minor versions.
|
# work with the two most recent helm minor versions.
|
||||||
|
|
@ -67,32 +67,32 @@ jobs:
|
||||||
# we will mark this combination as failable,
|
# we will mark this combination as failable,
|
||||||
# and instruct users to upgrade helm and helm-secrets at once.
|
# and instruct users to upgrade helm and helm-secrets at once.
|
||||||
plugin-secrets-version: 4.6.5
|
plugin-secrets-version: 4.6.5
|
||||||
plugin-diff-version: 3.12.3
|
plugin-diff-version: 3.12.5
|
||||||
extra-helmfile-flags: ''
|
extra-helmfile-flags: ''
|
||||||
- helm-version: v3.18.4
|
- helm-version: v3.19.0
|
||||||
kustomize-version: v5.2.1
|
kustomize-version: v5.2.1
|
||||||
plugin-secrets-version: 4.6.5
|
plugin-secrets-version: 4.6.5
|
||||||
plugin-diff-version: 3.11.0
|
plugin-diff-version: 3.11.0
|
||||||
extra-helmfile-flags: ''
|
extra-helmfile-flags: ''
|
||||||
- helm-version: v3.18.4
|
- helm-version: v3.19.0
|
||||||
kustomize-version: v5.4.3
|
kustomize-version: v5.4.3
|
||||||
plugin-secrets-version: 4.6.5
|
plugin-secrets-version: 4.6.5
|
||||||
plugin-diff-version: 3.12.3
|
plugin-diff-version: 3.12.5
|
||||||
extra-helmfile-flags: ''
|
extra-helmfile-flags: ''
|
||||||
# In case you need to test some optional helmfile features,
|
# In case you need to test some optional helmfile features,
|
||||||
# enable it via extra-helmfile-flags below.
|
# enable it via extra-helmfile-flags below.
|
||||||
- helm-version: v3.18.4
|
- helm-version: v3.19.0
|
||||||
kustomize-version: v5.4.3
|
kustomize-version: v5.4.3
|
||||||
plugin-secrets-version: 4.6.5
|
plugin-secrets-version: 4.6.5
|
||||||
plugin-diff-version: 3.12.3
|
plugin-diff-version: 3.12.5
|
||||||
extra-helmfile-flags: '--enable-live-output'
|
extra-helmfile-flags: '--enable-live-output'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v5
|
||||||
with:
|
with:
|
||||||
name: built-binaries-${{ github.run_id }}
|
name: built-binaries-${{ github.run_id }}
|
||||||
- name: install semver
|
- name: install semver
|
||||||
|
|
@ -109,6 +109,8 @@ jobs:
|
||||||
run: make -C .github/workflows helm vault sops kustomize
|
run: make -C .github/workflows helm vault sops kustomize
|
||||||
- name: Start minikube
|
- name: Start minikube
|
||||||
uses: medyagh/setup-minikube@latest
|
uses: medyagh/setup-minikube@latest
|
||||||
|
with:
|
||||||
|
kubernetes-version: v1.33.1
|
||||||
- name: Execute integration tests
|
- name: Execute integration tests
|
||||||
run: make integration
|
run: make integration
|
||||||
env:
|
env:
|
||||||
|
|
@ -122,10 +124,10 @@ jobs:
|
||||||
needs: tests
|
needs: tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v5
|
||||||
with:
|
with:
|
||||||
name: built-binaries-${{ github.run_id }}
|
name: built-binaries-${{ github.run_id }}
|
||||||
- name: Extract tar to get built binaries
|
- name: Extract tar to get built binaries
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ jobs:
|
||||||
suffix: "-ubuntu"
|
suffix: "-ubuntu"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,14 @@ jobs:
|
||||||
goreleaser:
|
goreleaser:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
|
- name: check disk usage
|
||||||
|
run: df -h
|
||||||
- uses: goreleaser/goreleaser-action@v6
|
- uses: goreleaser/goreleaser-action@v6
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ ENV HELM_CONFIG_HOME="${HELM_CONFIG_HOME}"
|
||||||
ARG HELM_DATA_HOME="${HOME}/.local/share/helm"
|
ARG HELM_DATA_HOME="${HOME}/.local/share/helm"
|
||||||
ENV HELM_DATA_HOME="${HELM_DATA_HOME}"
|
ENV HELM_DATA_HOME="${HELM_DATA_HOME}"
|
||||||
|
|
||||||
ARG HELM_VERSION="v3.18.4"
|
ARG HELM_VERSION="v3.19.0"
|
||||||
ENV HELM_VERSION="${HELM_VERSION}"
|
ENV HELM_VERSION="${HELM_VERSION}"
|
||||||
ARG HELM_LOCATION="https://get.helm.sh"
|
ARG HELM_LOCATION="https://get.helm.sh"
|
||||||
ARG HELM_FILENAME="helm-${HELM_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz"
|
ARG HELM_FILENAME="helm-${HELM_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz"
|
||||||
|
|
@ -38,8 +38,8 @@ RUN set -x && \
|
||||||
curl --retry 5 --retry-connrefused -LO "${HELM_LOCATION}/${HELM_FILENAME}" && \
|
curl --retry 5 --retry-connrefused -LO "${HELM_LOCATION}/${HELM_FILENAME}" && \
|
||||||
echo Verifying ${HELM_FILENAME}... && \
|
echo Verifying ${HELM_FILENAME}... && \
|
||||||
case ${TARGETPLATFORM} in \
|
case ${TARGETPLATFORM} in \
|
||||||
"linux/amd64") HELM_SHA256="f8180838c23d7c7d797b208861fecb591d9ce1690d8704ed1e4cb8e2add966c1" ;; \
|
"linux/amd64") HELM_SHA256="a7f81ce08007091b86d8bd696eb4d86b8d0f2e1b9f6c714be62f82f96a594496" ;; \
|
||||||
"linux/arm64") HELM_SHA256="c0a45e67eef0c7416a8a8c9e9d5d2d30d70e4f4d3f7bea5de28241fffa8f3b89" ;; \
|
"linux/arm64") HELM_SHA256="440cf7add0aee27ebc93fada965523c1dc2e0ab340d4348da2215737fc0d76ad" ;; \
|
||||||
esac && \
|
esac && \
|
||||||
echo "${HELM_SHA256} ${HELM_FILENAME}" | sha256sum -c && \
|
echo "${HELM_SHA256} ${HELM_FILENAME}" | sha256sum -c && \
|
||||||
echo Extracting ${HELM_FILENAME}... && \
|
echo Extracting ${HELM_FILENAME}... && \
|
||||||
|
|
@ -93,7 +93,7 @@ RUN set -x && \
|
||||||
[ "$(age --version)" = "${AGE_VERSION}" ] && \
|
[ "$(age --version)" = "${AGE_VERSION}" ] && \
|
||||||
[ "$(age-keygen --version)" = "${AGE_VERSION}" ]
|
[ "$(age-keygen --version)" = "${AGE_VERSION}" ]
|
||||||
|
|
||||||
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.12.3 && \
|
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.13.0 && \
|
||||||
helm plugin install https://github.com/jkroepke/helm-secrets --version v4.6.5 && \
|
helm plugin install https://github.com/jkroepke/helm-secrets --version v4.6.5 && \
|
||||||
helm plugin install https://github.com/hypnoglow/helm-s3.git --version v0.16.3 && \
|
helm plugin install https://github.com/hypnoglow/helm-s3.git --version v0.16.3 && \
|
||||||
helm plugin install https://github.com/aslafy-z/helm-git.git --version v1.3.0 && \
|
helm plugin install https://github.com/aslafy-z/helm-git.git --version v1.3.0 && \
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ ENV HELM_CONFIG_HOME="${HELM_CONFIG_HOME}"
|
||||||
ARG HELM_DATA_HOME="${HOME}/.local/share/helm"
|
ARG HELM_DATA_HOME="${HOME}/.local/share/helm"
|
||||||
ENV HELM_DATA_HOME="${HELM_DATA_HOME}"
|
ENV HELM_DATA_HOME="${HELM_DATA_HOME}"
|
||||||
|
|
||||||
ARG HELM_VERSION="v3.18.4"
|
ARG HELM_VERSION="v3.19.0"
|
||||||
ENV HELM_VERSION="${HELM_VERSION}"
|
ENV HELM_VERSION="${HELM_VERSION}"
|
||||||
ARG HELM_LOCATION="https://get.helm.sh"
|
ARG HELM_LOCATION="https://get.helm.sh"
|
||||||
ARG HELM_FILENAME="helm-${HELM_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz"
|
ARG HELM_FILENAME="helm-${HELM_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz"
|
||||||
|
|
@ -43,8 +43,8 @@ RUN set -x && \
|
||||||
curl --retry 5 --retry-connrefused -LO "${HELM_LOCATION}/${HELM_FILENAME}" && \
|
curl --retry 5 --retry-connrefused -LO "${HELM_LOCATION}/${HELM_FILENAME}" && \
|
||||||
echo Verifying ${HELM_FILENAME}... && \
|
echo Verifying ${HELM_FILENAME}... && \
|
||||||
case ${TARGETPLATFORM} in \
|
case ${TARGETPLATFORM} in \
|
||||||
"linux/amd64") HELM_SHA256="f8180838c23d7c7d797b208861fecb591d9ce1690d8704ed1e4cb8e2add966c1" ;; \
|
"linux/amd64") HELM_SHA256="a7f81ce08007091b86d8bd696eb4d86b8d0f2e1b9f6c714be62f82f96a594496" ;; \
|
||||||
"linux/arm64") HELM_SHA256="c0a45e67eef0c7416a8a8c9e9d5d2d30d70e4f4d3f7bea5de28241fffa8f3b89" ;; \
|
"linux/arm64") HELM_SHA256="440cf7add0aee27ebc93fada965523c1dc2e0ab340d4348da2215737fc0d76ad" ;; \
|
||||||
esac && \
|
esac && \
|
||||||
echo "${HELM_SHA256} ${HELM_FILENAME}" | sha256sum -c && \
|
echo "${HELM_SHA256} ${HELM_FILENAME}" | sha256sum -c && \
|
||||||
echo Extracting ${HELM_FILENAME}... && \
|
echo Extracting ${HELM_FILENAME}... && \
|
||||||
|
|
@ -99,7 +99,7 @@ RUN set -x && \
|
||||||
[ "$(age --version)" = "${AGE_VERSION}" ] && \
|
[ "$(age --version)" = "${AGE_VERSION}" ] && \
|
||||||
[ "$(age-keygen --version)" = "${AGE_VERSION}" ]
|
[ "$(age-keygen --version)" = "${AGE_VERSION}" ]
|
||||||
|
|
||||||
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.12.3 && \
|
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.13.0 && \
|
||||||
helm plugin install https://github.com/jkroepke/helm-secrets --version v4.6.5 && \
|
helm plugin install https://github.com/jkroepke/helm-secrets --version v4.6.5 && \
|
||||||
helm plugin install https://github.com/hypnoglow/helm-s3.git --version v0.16.3 && \
|
helm plugin install https://github.com/hypnoglow/helm-s3.git --version v0.16.3 && \
|
||||||
helm plugin install https://github.com/aslafy-z/helm-git.git --version v1.3.0 && \
|
helm plugin install https://github.com/aslafy-z/helm-git.git --version v1.3.0 && \
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ RUN make static-${TARGETOS}-${TARGETARCH}
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
FROM ubuntu:24.10
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
LABEL org.opencontainers.image.source=https://github.com/helmfile/helmfile
|
LABEL org.opencontainers.image.source=https://github.com/helmfile/helmfile
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ ENV HELM_CONFIG_HOME="${HELM_CONFIG_HOME}"
|
||||||
ARG HELM_DATA_HOME="${HOME}/.local/share/helm"
|
ARG HELM_DATA_HOME="${HOME}/.local/share/helm"
|
||||||
ENV HELM_DATA_HOME="${HELM_DATA_HOME}"
|
ENV HELM_DATA_HOME="${HELM_DATA_HOME}"
|
||||||
|
|
||||||
ARG HELM_VERSION="v3.18.4"
|
ARG HELM_VERSION="v3.19.0"
|
||||||
ENV HELM_VERSION="${HELM_VERSION}"
|
ENV HELM_VERSION="${HELM_VERSION}"
|
||||||
ARG HELM_LOCATION="https://get.helm.sh"
|
ARG HELM_LOCATION="https://get.helm.sh"
|
||||||
ARG HELM_FILENAME="helm-${HELM_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz"
|
ARG HELM_FILENAME="helm-${HELM_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz"
|
||||||
|
|
@ -43,8 +43,8 @@ RUN set -x && \
|
||||||
curl --retry 5 --retry-connrefused -LO "${HELM_LOCATION}/${HELM_FILENAME}" && \
|
curl --retry 5 --retry-connrefused -LO "${HELM_LOCATION}/${HELM_FILENAME}" && \
|
||||||
echo Verifying ${HELM_FILENAME}... && \
|
echo Verifying ${HELM_FILENAME}... && \
|
||||||
case ${TARGETPLATFORM} in \
|
case ${TARGETPLATFORM} in \
|
||||||
"linux/amd64") HELM_SHA256="f8180838c23d7c7d797b208861fecb591d9ce1690d8704ed1e4cb8e2add966c1" ;; \
|
"linux/amd64") HELM_SHA256="a7f81ce08007091b86d8bd696eb4d86b8d0f2e1b9f6c714be62f82f96a594496" ;; \
|
||||||
"linux/arm64") HELM_SHA256="c0a45e67eef0c7416a8a8c9e9d5d2d30d70e4f4d3f7bea5de28241fffa8f3b89" ;; \
|
"linux/arm64") HELM_SHA256="440cf7add0aee27ebc93fada965523c1dc2e0ab340d4348da2215737fc0d76ad" ;; \
|
||||||
esac && \
|
esac && \
|
||||||
echo "${HELM_SHA256} ${HELM_FILENAME}" | sha256sum -c && \
|
echo "${HELM_SHA256} ${HELM_FILENAME}" | sha256sum -c && \
|
||||||
echo Extracting ${HELM_FILENAME}... && \
|
echo Extracting ${HELM_FILENAME}... && \
|
||||||
|
|
@ -99,7 +99,7 @@ RUN set -x && \
|
||||||
[ "$(age --version)" = "${AGE_VERSION}" ] && \
|
[ "$(age --version)" = "${AGE_VERSION}" ] && \
|
||||||
[ "$(age-keygen --version)" = "${AGE_VERSION}" ]
|
[ "$(age-keygen --version)" = "${AGE_VERSION}" ]
|
||||||
|
|
||||||
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.12.3 && \
|
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.13.0 && \
|
||||||
helm plugin install https://github.com/jkroepke/helm-secrets --version v4.6.5 && \
|
helm plugin install https://github.com/jkroepke/helm-secrets --version v4.6.5 && \
|
||||||
helm plugin install https://github.com/hypnoglow/helm-s3.git --version v0.16.3 && \
|
helm plugin install https://github.com/hypnoglow/helm-s3.git --version v0.16.3 && \
|
||||||
helm plugin install https://github.com/aslafy-z/helm-git.git --version v1.3.0 && \
|
helm plugin install https://github.com/aslafy-z/helm-git.git --version v1.3.0 && \
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,9 @@ Helmfile is a declarative spec for deploying helm charts. It lets you...
|
||||||
* Apply CI/CD to configuration changes.
|
* Apply CI/CD to configuration changes.
|
||||||
* Periodically sync to avoid skew in environments.
|
* Periodically sync to avoid skew in environments.
|
||||||
|
|
||||||
To avoid upgrades for each iteration of `helm`, the `helmfile` executable delegates to `helm` - as a result, `helm` must be installed.
|
To avoid upgrades for each iteration of `helm`, the `helmfile` executable delegates to `helm` - as a result, the following must be installed
|
||||||
|
- [helm](https://helm.sh/docs/intro/install/)
|
||||||
|
- [helm-diff](https://github.com/databus23/helm-diff)
|
||||||
|
|
||||||
## Highlights
|
## Highlights
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ func NewRootCmd(globalConfig *config.GlobalOptions) (*cobra.Command, error) {
|
||||||
// Set the global options for the root command.
|
// Set the global options for the root command.
|
||||||
setGlobalOptionsForRootCmd(flags, globalConfig)
|
setGlobalOptionsForRootCmd(flags, globalConfig)
|
||||||
|
|
||||||
flags.ParseErrorsWhitelist.UnknownFlags = true
|
flags.ParseErrorsAllowlist.UnknownFlags = true
|
||||||
|
|
||||||
globalImpl := config.NewGlobalImpl(globalConfig)
|
globalImpl := config.NewGlobalImpl(globalConfig)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ func NewSyncCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||||
f.BoolVar(&syncOptions.SyncReleaseLabels, "sync-release-labels", false, "sync release labels to the target release")
|
f.BoolVar(&syncOptions.SyncReleaseLabels, "sync-release-labels", false, "sync release labels to the target release")
|
||||||
f.BoolVar(&syncOptions.Wait, "wait", false, `Override helmDefaults.wait setting "helm upgrade --install --wait"`)
|
f.BoolVar(&syncOptions.Wait, "wait", false, `Override helmDefaults.wait setting "helm upgrade --install --wait"`)
|
||||||
f.BoolVar(&syncOptions.WaitForJobs, "wait-for-jobs", false, `Override helmDefaults.waitForJobs setting "helm upgrade --install --wait-for-jobs"`)
|
f.BoolVar(&syncOptions.WaitForJobs, "wait-for-jobs", false, `Override helmDefaults.waitForJobs setting "helm upgrade --install --wait-for-jobs"`)
|
||||||
|
f.IntVar(&syncOptions.Timeout, "timeout", 0, `Override helmDefaults.timeout setting "helm upgrade --install --timeout" (default 0, which means no timeout)`)
|
||||||
f.BoolVar(&syncOptions.ReuseValues, "reuse-values", false, `Override helmDefaults.reuseValues "helm upgrade --install --reuse-values"`)
|
f.BoolVar(&syncOptions.ReuseValues, "reuse-values", false, `Override helmDefaults.reuseValues "helm upgrade --install --reuse-values"`)
|
||||||
f.BoolVar(&syncOptions.ResetValues, "reset-values", false, `Override helmDefaults.reuseValues "helm upgrade --install --reset-values"`)
|
f.BoolVar(&syncOptions.ResetValues, "reset-values", false, `Override helmDefaults.reuseValues "helm upgrade --install --reset-values"`)
|
||||||
f.StringVar(&syncOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`)
|
f.StringVar(&syncOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`)
|
||||||
|
|
|
||||||
|
|
@ -194,8 +194,9 @@ helmDefaults:
|
||||||
skipSchemaValidation: false
|
skipSchemaValidation: false
|
||||||
# wait for k8s resources via --wait. (default false)
|
# wait for k8s resources via --wait. (default false)
|
||||||
wait: true
|
wait: true
|
||||||
# if set and --wait enabled, will retry any failed check on resource state subject to the specified number of retries (default 0)
|
# DEPRECATED: waitRetries is no longer supported as the --wait-retries flag was removed from Helm.
|
||||||
waitRetries: 3
|
# This configuration is ignored and preserved only for backward compatibility.
|
||||||
|
# waitRetries: 3
|
||||||
# if set and --wait enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as --timeout (default false, Implemented in Helm3.5)
|
# if set and --wait enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as --timeout (default false, Implemented in Helm3.5)
|
||||||
waitForJobs: true
|
waitForJobs: true
|
||||||
# time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks, and waits on pod/pvc/svc/deployment readiness) (default 300)
|
# time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks, and waits on pod/pvc/svc/deployment readiness) (default 300)
|
||||||
|
|
@ -318,7 +319,8 @@ releases:
|
||||||
# --skip-schema-validation flag to helm 'install', 'upgrade' and 'lint', starts with helm 3.16.0 (default false)
|
# --skip-schema-validation flag to helm 'install', 'upgrade' and 'lint', starts with helm 3.16.0 (default false)
|
||||||
skipSchemaValidation: false
|
skipSchemaValidation: false
|
||||||
wait: true
|
wait: true
|
||||||
waitRetries: 3
|
# DEPRECATED: waitRetries is no longer supported - see documentation above
|
||||||
|
# waitRetries: 3
|
||||||
waitForJobs: true
|
waitForJobs: true
|
||||||
timeout: 60
|
timeout: 60
|
||||||
recreatePods: true
|
recreatePods: true
|
||||||
|
|
@ -649,6 +651,8 @@ Flags:
|
||||||
Use "helmfile [command] --help" for more information about a command.
|
Use "helmfile [command] --help" for more information about a command.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Note:** Each command has its own specific flags. Use `helmfile [command] --help` to see command-specific options. For example, `helmfile sync --help` shows operational flags like `--timeout`, `--wait`, and `--wait-for-jobs`.
|
||||||
|
|
||||||
### init
|
### init
|
||||||
|
|
||||||
The `helmfile init` sub-command checks the dependencies required for helmfile operation, such as `helm`, `helm diff plugin`, `helm secrets plugin`, `helm helm-git plugin`, `helm s3 plugin`. When it does not exist or the version is too low, it can be installed automatically.
|
The `helmfile init` sub-command checks the dependencies required for helmfile operation, such as `helm`, `helm diff plugin`, `helm secrets plugin`, `helm helm-git plugin`, `helm s3 plugin`. When it does not exist or the version is too low, it can be installed automatically.
|
||||||
|
|
@ -664,6 +668,25 @@ The `helmfile sync` sub-command sync your cluster state as described in your `he
|
||||||
Under the covers, Helmfile executes `helm upgrade --install` for each `release` declared in the manifest, by optionally decrypting [secrets](#secrets) to be consumed as helm chart values. It also updates specified chart repositories and updates the
|
Under the covers, Helmfile executes `helm upgrade --install` for each `release` declared in the manifest, by optionally decrypting [secrets](#secrets) to be consumed as helm chart values. It also updates specified chart repositories and updates the
|
||||||
dependencies of any referenced local charts.
|
dependencies of any referenced local charts.
|
||||||
|
|
||||||
|
#### Common sync flags
|
||||||
|
|
||||||
|
* `--timeout SECONDS` - Override the default timeout for all releases in this sync operation. This takes precedence over `helmDefaults.timeout` and per-release `timeout` settings.
|
||||||
|
* `--wait` - Override the default wait behavior for all releases
|
||||||
|
* `--wait-for-jobs` - Override the default wait-for-jobs behavior for all releases
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Override timeout for all releases to 10 minutes
|
||||||
|
helmfile sync --timeout 600
|
||||||
|
|
||||||
|
# Combine timeout with wait flags
|
||||||
|
helmfile sync --timeout 900 --wait --wait-for-jobs
|
||||||
|
|
||||||
|
# Target specific releases with custom timeout
|
||||||
|
helmfile sync --selector tier=backend --timeout 1200
|
||||||
|
```
|
||||||
|
|
||||||
For Helm 2.9+ you can use a username and password to authenticate to a remote repository.
|
For Helm 2.9+ you can use a username and password to authenticate to a remote repository.
|
||||||
|
|
||||||
### deps
|
### deps
|
||||||
|
|
|
||||||
225
go.mod
225
go.mod
|
|
@ -1,6 +1,6 @@
|
||||||
module github.com/helmfile/helmfile
|
module github.com/helmfile/helmfile
|
||||||
|
|
||||||
go 1.24.2
|
go 1.24.6
|
||||||
|
|
||||||
require (
|
require (
|
||||||
dario.cat/mergo v1.0.2
|
dario.cat/mergo v1.0.2
|
||||||
|
|
@ -11,32 +11,32 @@ require (
|
||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
github.com/google/go-cmp v0.7.0
|
github.com/google/go-cmp v0.7.0
|
||||||
github.com/gosuri/uitable v0.0.4
|
github.com/gosuri/uitable v0.0.4
|
||||||
github.com/hashicorp/go-getter v1.7.8
|
github.com/hashicorp/go-getter v1.8.1
|
||||||
github.com/hashicorp/hcl/v2 v2.24.0
|
github.com/hashicorp/hcl/v2 v2.24.0
|
||||||
github.com/helmfile/chartify v0.24.6
|
github.com/helmfile/chartify v0.25.0
|
||||||
github.com/helmfile/vals v0.41.3
|
github.com/helmfile/vals v0.42.1
|
||||||
github.com/spf13/cobra v1.9.1
|
github.com/spf13/cobra v1.10.1
|
||||||
github.com/spf13/pflag v1.0.7
|
github.com/spf13/pflag v1.0.10
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/tatsushid/go-prettytable v0.0.0-20141013043238-ed2d14c29939
|
github.com/tatsushid/go-prettytable v0.0.0-20141013043238-ed2d14c29939
|
||||||
github.com/tj/assert v0.0.3
|
github.com/tj/assert v0.0.3
|
||||||
github.com/variantdev/dag v1.1.0
|
github.com/variantdev/dag v1.1.0
|
||||||
github.com/zclconf/go-cty v1.16.3
|
github.com/zclconf/go-cty v1.17.0
|
||||||
github.com/zclconf/go-cty-yaml v1.1.0
|
github.com/zclconf/go-cty-yaml v1.1.0
|
||||||
go.szostok.io/version v1.2.0
|
go.szostok.io/version v1.2.0
|
||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.27.0
|
||||||
go.yaml.in/yaml/v2 v2.4.2
|
go.yaml.in/yaml/v2 v2.4.3
|
||||||
go.yaml.in/yaml/v3 v3.0.4
|
go.yaml.in/yaml/v3 v3.0.4
|
||||||
golang.org/x/sync v0.16.0
|
golang.org/x/sync v0.17.0
|
||||||
golang.org/x/term v0.33.0
|
golang.org/x/term v0.35.0
|
||||||
helm.sh/helm/v3 v3.18.4
|
helm.sh/helm/v3 v3.19.0
|
||||||
k8s.io/apimachinery v0.33.3
|
k8s.io/apimachinery v0.34.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.116.0 // indirect
|
cloud.google.com/go v0.121.6 // indirect
|
||||||
cloud.google.com/go/iam v1.2.2 // indirect
|
cloud.google.com/go/iam v1.5.2 // indirect
|
||||||
cloud.google.com/go/storage v1.50.0 // indirect
|
cloud.google.com/go/storage v1.56.1 // indirect
|
||||||
filippo.io/age v1.2.1 // indirect
|
filippo.io/age v1.2.1 // indirect
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||||
github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect
|
github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect
|
||||||
|
|
@ -51,24 +51,24 @@ require (
|
||||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||||
github.com/fatih/color v1.18.0
|
github.com/fatih/color v1.18.0
|
||||||
github.com/fujiwara/tfstate-lookup v1.6.0 // indirect
|
github.com/fujiwara/tfstate-lookup v1.7.0 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
|
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
|
||||||
github.com/goware/prefixer v0.0.0-20160118172347-395022866408 // indirect
|
github.com/goware/prefixer v0.0.0-20160118172347-395022866408 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||||
github.com/hashicorp/go-slug v0.16.3 // indirect
|
github.com/hashicorp/go-slug v0.16.4 // indirect
|
||||||
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
|
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
|
||||||
github.com/hashicorp/go-tfe v1.56.0 // indirect
|
github.com/hashicorp/go-tfe v1.84.0 // indirect
|
||||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.1-vault-7 // indirect
|
github.com/hashicorp/hcl v1.0.1-vault-7 // indirect
|
||||||
github.com/hashicorp/jsonapi v1.3.1 // indirect
|
github.com/hashicorp/jsonapi v1.4.3-0.20250220162346-81a76b606f3e // indirect
|
||||||
github.com/hashicorp/vault/api v1.20.0 // indirect
|
github.com/hashicorp/vault/api v1.20.0 // indirect
|
||||||
github.com/huandu/xstrings v1.5.0 // indirect
|
github.com/huandu/xstrings v1.5.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
|
@ -76,11 +76,10 @@ require (
|
||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.0 // indirect
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
github.com/lib/pq v1.10.9 // indirect
|
github.com/lib/pq v1.10.9 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
|
||||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||||
|
|
@ -91,114 +90,116 @@ require (
|
||||||
github.com/shopspring/decimal v1.4.0 // indirect
|
github.com/shopspring/decimal v1.4.0 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/spf13/cast v1.7.0 // indirect
|
github.com/spf13/cast v1.7.0 // indirect
|
||||||
github.com/ulikunitz/xz v0.5.10 // indirect
|
github.com/ulikunitz/xz v0.5.15 // indirect
|
||||||
go.opencensus.io v0.24.0 // indirect
|
|
||||||
go.uber.org/atomic v1.9.0 // indirect
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
golang.org/x/net v0.41.0 // indirect
|
golang.org/x/net v0.43.0 // indirect
|
||||||
golang.org/x/oauth2 v0.30.0 // indirect
|
golang.org/x/oauth2 v0.30.0 // indirect
|
||||||
golang.org/x/sys v0.34.0 // indirect
|
golang.org/x/sys v0.36.0 // indirect
|
||||||
golang.org/x/text v0.26.0 // indirect
|
golang.org/x/text v0.28.0 // indirect
|
||||||
golang.org/x/time v0.9.0 // indirect
|
golang.org/x/time v0.12.0 // indirect
|
||||||
google.golang.org/api v0.215.0 // indirect
|
google.golang.org/api v0.248.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
|
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
|
||||||
google.golang.org/grpc v1.68.1 // indirect
|
google.golang.org/grpc v1.74.2 // indirect
|
||||||
google.golang.org/protobuf v1.36.5 // indirect
|
google.golang.org/protobuf v1.36.7 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
|
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
sigs.k8s.io/yaml v1.6.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
al.essio.dev/pkg/shellescape v1.5.1 // indirect
|
al.essio.dev/pkg/shellescape v1.6.0 // indirect
|
||||||
cel.dev/expr v0.19.1 // indirect
|
cel.dev/expr v0.24.0 // indirect
|
||||||
cloud.google.com/go/auth v0.13.0 // indirect
|
cloud.google.com/go/auth v0.16.5 // indirect
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect
|
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
cloud.google.com/go/compute/metadata v0.8.0 // indirect
|
||||||
cloud.google.com/go/kms v1.20.5 // indirect
|
cloud.google.com/go/kms v1.22.0 // indirect
|
||||||
cloud.google.com/go/longrunning v0.6.2 // indirect
|
cloud.google.com/go/longrunning v0.6.7 // indirect
|
||||||
cloud.google.com/go/monitoring v1.21.2 // indirect
|
cloud.google.com/go/monitoring v1.24.2 // indirect
|
||||||
cloud.google.com/go/secretmanager v1.14.3 // indirect
|
cloud.google.com/go/secretmanager v1.15.0 // indirect
|
||||||
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
github.com/1Password/connect-sdk-go v1.5.3 // indirect
|
github.com/1Password/connect-sdk-go v1.5.3 // indirect
|
||||||
github.com/1password/onepassword-sdk-go v0.3.1 // indirect
|
github.com/1password/onepassword-sdk-go v0.3.1 // indirect
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.6 // indirect
|
github.com/AlecAivazis/survey/v2 v2.3.6 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.11.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.3.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.1 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 // indirect
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
|
||||||
github.com/DopplerHQ/cli v0.5.11-0.20230908185655-7aef4713e1a4 // indirect
|
github.com/DopplerHQ/cli v0.5.11-0.20230908185655-7aef4713e1a4 // indirect
|
||||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect
|
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 // indirect
|
||||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect
|
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0 // indirect
|
||||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect
|
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.53.0 // indirect
|
||||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||||
github.com/Masterminds/squirrel v1.5.4 // indirect
|
github.com/Masterminds/squirrel v1.5.4 // indirect
|
||||||
github.com/ProtonMail/go-crypto v1.1.3 // indirect
|
github.com/ProtonMail/go-crypto v1.2.0 // indirect
|
||||||
github.com/agext/levenshtein v1.2.3 // indirect
|
github.com/agext/levenshtein v1.2.3 // indirect
|
||||||
github.com/antchfx/jsonquery v1.3.6 // indirect
|
github.com/antchfx/jsonquery v1.3.6 // indirect
|
||||||
github.com/antchfx/xpath v1.3.4 // indirect
|
github.com/antchfx/xpath v1.3.5 // indirect
|
||||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect
|
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect
|
||||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||||
github.com/atotto/clipboard v0.1.4 // indirect
|
github.com/atotto/clipboard v0.1.4 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect
|
github.com/aws/aws-sdk-go-v2 v1.38.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.29.14 // indirect
|
github.com/aws/aws-sdk-go-v2/config v1.29.15 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67 // indirect
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.68 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.72 // indirect
|
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.72 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.6 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.0 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.2 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/kms v1.37.7 // indirect
|
github.com/aws/aws-sdk-go-v2/service/kms v1.38.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.79.2 // indirect
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.80.1 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.2 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssm v1.64.2 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.20 // indirect
|
||||||
github.com/aws/smithy-go v1.22.2 // indirect
|
github.com/aws/smithy-go v1.23.0 // indirect
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
|
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/chai2010/gettext-go v1.0.2 // indirect
|
github.com/chai2010/gettext-go v1.0.2 // indirect
|
||||||
github.com/cloudflare/circl v1.6.1 // indirect
|
github.com/cloudflare/circl v1.6.1 // indirect
|
||||||
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect
|
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect
|
||||||
github.com/containerd/containerd v1.7.27 // indirect
|
github.com/containerd/containerd v1.7.28 // indirect
|
||||||
github.com/containerd/errdefs v0.3.0 // indirect
|
github.com/containerd/errdefs v0.3.0 // indirect
|
||||||
github.com/containerd/log v0.1.0 // indirect
|
github.com/containerd/log v0.1.0 // indirect
|
||||||
github.com/containerd/platforms v0.2.1 // indirect
|
github.com/containerd/platforms v0.2.1 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||||
github.com/cyberark/conjur-api-go v0.13.1 // indirect
|
github.com/cyberark/conjur-api-go v0.13.3 // indirect
|
||||||
github.com/danieljoos/wincred v1.2.2 // indirect
|
github.com/danieljoos/wincred v1.2.2 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a // indirect
|
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a // indirect
|
||||||
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
|
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
|
||||||
github.com/envoyproxy/go-control-plane v0.13.1 // indirect
|
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
|
||||||
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
|
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
|
||||||
github.com/evanphx/json-patch v5.9.11+incompatible // indirect
|
github.com/evanphx/json-patch v5.9.11+incompatible // indirect
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||||
github.com/extism/go-sdk v1.7.0 // indirect
|
github.com/extism/go-sdk v1.7.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||||
github.com/getsops/gopgagent v0.0.0-20240527072608-0c14999532fe // indirect
|
github.com/getsops/gopgagent v0.0.0-20241224165529-7044f28e491e // indirect
|
||||||
github.com/getsops/sops/v3 v3.9.2 // indirect
|
github.com/getsops/sops/v3 v3.10.2 // indirect
|
||||||
|
github.com/ghodss/yaml v1.0.0 // indirect
|
||||||
github.com/go-errors/errors v1.4.2 // indirect
|
github.com/go-errors/errors v1.4.2 // indirect
|
||||||
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
|
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
|
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
|
||||||
github.com/go-logr/logr v1.4.2 // indirect
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||||
github.com/go-openapi/errors v0.22.1 // indirect
|
github.com/go-openapi/errors v0.22.2 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||||
github.com/go-openapi/loads v0.22.0 // indirect
|
github.com/go-openapi/loads v0.22.0 // indirect
|
||||||
|
|
@ -211,20 +212,21 @@ require (
|
||||||
github.com/goccy/go-yaml v1.17.1 // indirect
|
github.com/goccy/go-yaml v1.17.1 // indirect
|
||||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
|
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
||||||
github.com/google/btree v1.1.3 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/gnostic-models v0.6.9 // indirect
|
github.com/google/gnostic-models v0.7.0 // indirect
|
||||||
github.com/google/go-jsonnet v0.20.0 // indirect
|
github.com/google/go-jsonnet v0.20.0 // indirect
|
||||||
github.com/google/s2a-go v0.1.8 // indirect
|
github.com/google/s2a-go v0.1.9 // indirect
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
|
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
|
||||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||||
|
github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.65 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 // indirect
|
github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect
|
||||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
|
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
|
||||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||||
github.com/hashicorp/hcp-sdk-go v0.151.0 // indirect
|
github.com/hashicorp/hcp-sdk-go v0.155.0 // indirect
|
||||||
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f // indirect
|
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f // indirect
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca // indirect
|
github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca // indirect
|
||||||
github.com/itchyny/timefmt-go v0.1.6 // indirect
|
github.com/itchyny/timefmt-go v0.1.6 // indirect
|
||||||
|
|
@ -244,7 +246,7 @@ require (
|
||||||
github.com/moby/spdystream v0.5.0 // indirect
|
github.com/moby/spdystream v0.5.0 // indirect
|
||||||
github.com/moby/term v0.5.2 // indirect
|
github.com/moby/term v0.5.2 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||||
github.com/muesli/termenv v0.15.1 // indirect
|
github.com/muesli/termenv v0.15.1 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
|
|
@ -261,6 +263,7 @@ require (
|
||||||
github.com/rubenv/sql-migrate v1.8.0 // indirect
|
github.com/rubenv/sql-migrate v1.8.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
|
||||||
|
github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
|
||||||
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 // indirect
|
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 // indirect
|
||||||
github.com/tetratelabs/wazero v1.9.0 // indirect
|
github.com/tetratelabs/wazero v1.9.0 // indirect
|
||||||
github.com/tidwall/gjson v1.18.0 // indirect
|
github.com/tidwall/gjson v1.18.0 // indirect
|
||||||
|
|
@ -272,42 +275,44 @@ require (
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||||
github.com/xlab/treeprint v1.2.0 // indirect
|
github.com/xlab/treeprint v1.2.0 // indirect
|
||||||
|
github.com/yandex-cloud/go-genproto v0.19.0 // indirect
|
||||||
|
github.com/yandex-cloud/go-sdk v0.15.0 // indirect
|
||||||
github.com/zalando/go-keyring v0.2.6 // indirect
|
github.com/zalando/go-keyring v0.2.6 // indirect
|
||||||
|
github.com/zeebo/errs v1.4.0 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
go.opentelemetry.io/contrib/detectors/gcp v1.29.0 // indirect
|
go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.33.0 // indirect
|
go.opentelemetry.io/otel v1.36.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.33.0 // indirect
|
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk v1.33.0 // indirect
|
go.opentelemetry.io/otel/sdk v1.36.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect
|
go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.33.0 // indirect
|
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.4.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/crypto v0.39.0 // indirect
|
golang.org/x/crypto v0.41.0 // indirect
|
||||||
golang.org/x/mod v0.25.0 // indirect
|
golang.org/x/mod v0.26.0 // indirect
|
||||||
golang.org/x/tools v0.33.0 // indirect
|
golang.org/x/tools v0.35.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect
|
||||||
google.golang.org/grpc/stats/opentelemetry v0.0.0-20240907200651-3ffb98b2c93a // indirect
|
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||||
gopkg.in/gookit/color.v1 v1.1.6 // indirect
|
gopkg.in/gookit/color.v1 v1.1.6 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
k8s.io/api v0.33.2 // indirect
|
k8s.io/api v0.34.0 // indirect
|
||||||
k8s.io/apiextensions-apiserver v0.33.2 // indirect
|
k8s.io/apiextensions-apiserver v0.34.0 // indirect
|
||||||
k8s.io/cli-runtime v0.33.2 // indirect
|
k8s.io/cli-runtime v0.34.0 // indirect
|
||||||
k8s.io/client-go v0.33.2 // indirect
|
k8s.io/client-go v0.34.0 // indirect
|
||||||
k8s.io/component-base v0.33.2 // indirect
|
k8s.io/component-base v0.34.0 // indirect
|
||||||
k8s.io/klog/v2 v2.130.1 // indirect
|
k8s.io/klog/v2 v2.130.1 // indirect
|
||||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
|
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
|
||||||
k8s.io/kubectl v0.33.2 // indirect
|
k8s.io/kubectl v0.34.0 // indirect
|
||||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
|
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
|
||||||
oras.land/oras-go/v2 v2.6.0 // indirect
|
oras.land/oras-go/v2 v2.6.0 // indirect
|
||||||
sigs.k8s.io/kustomize/api v0.19.0 // indirect
|
sigs.k8s.io/kustomize/api v0.20.1 // indirect
|
||||||
sigs.k8s.io/kustomize/kyaml v0.19.0 // indirect
|
sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect
|
||||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
|
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -784,7 +784,7 @@ func createHelmKey(bin, kubectx string) helmKey {
|
||||||
//
|
//
|
||||||
// This is currently used for running all the helm commands for reconciling releases. But this may change in the future
|
// This is currently used for running all the helm commands for reconciling releases. But this may change in the future
|
||||||
// once we enable each release to have its own helm binary/version.
|
// once we enable each release to have its own helm binary/version.
|
||||||
func (a *App) getHelm(st *state.HelmState) helmexec.Interface {
|
func (a *App) getHelm(st *state.HelmState) (helmexec.Interface, error) {
|
||||||
a.helmsMutex.Lock()
|
a.helmsMutex.Lock()
|
||||||
defer a.helmsMutex.Unlock()
|
defer a.helmsMutex.Unlock()
|
||||||
|
|
||||||
|
|
@ -799,14 +799,18 @@ func (a *App) getHelm(st *state.HelmState) helmexec.Interface {
|
||||||
key := createHelmKey(bin, kubectx)
|
key := createHelmKey(bin, kubectx)
|
||||||
|
|
||||||
if _, ok := a.helms[key]; !ok {
|
if _, ok := a.helms[key]; !ok {
|
||||||
a.helms[key] = helmexec.New(bin, helmexec.HelmExecOptions{EnableLiveOutput: a.EnableLiveOutput, DisableForceUpdate: a.DisableForceUpdate}, a.Logger, kubeconfig, kubectx, &helmexec.ShellRunner{
|
exec, err := helmexec.New(bin, helmexec.HelmExecOptions{EnableLiveOutput: a.EnableLiveOutput, DisableForceUpdate: a.DisableForceUpdate}, a.Logger, kubeconfig, kubectx, &helmexec.ShellRunner{
|
||||||
Logger: a.Logger,
|
Logger: a.Logger,
|
||||||
Ctx: a.ctx,
|
Ctx: a.ctx,
|
||||||
StripArgsValuesOnExitError: a.StripArgsValuesOnExitError,
|
StripArgsValuesOnExitError: a.StripArgsValuesOnExitError,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
a.helms[key] = exec
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.helms[key]
|
return a.helms[key], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) visitStates(fileOrDir string, defOpts LoadOpts, converge func(*state.HelmState) (bool, []error)) error {
|
func (a *App) visitStates(fileOrDir string, defOpts LoadOpts, converge func(*state.HelmState) (bool, []error)) error {
|
||||||
|
|
@ -958,7 +962,10 @@ var (
|
||||||
func (a *App) ForEachState(do func(*Run) (bool, []error), includeTransitiveNeeds bool, o ...LoadOption) error {
|
func (a *App) ForEachState(do func(*Run) (bool, []error), includeTransitiveNeeds bool, o ...LoadOption) error {
|
||||||
ctx := NewContext()
|
ctx := NewContext()
|
||||||
err := a.visitStatesWithSelectorsAndRemoteSupport(a.FileOrDir, func(st *state.HelmState) (bool, []error) {
|
err := a.visitStatesWithSelectorsAndRemoteSupport(a.FileOrDir, func(st *state.HelmState) (bool, []error) {
|
||||||
helm := a.getHelm(st)
|
helm, err := a.getHelm(st)
|
||||||
|
if err != nil {
|
||||||
|
return false, []error{err}
|
||||||
|
}
|
||||||
|
|
||||||
run, err := NewRun(st, helm, ctx)
|
run, err := NewRun(st, helm, ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -2583,9 +2583,12 @@ func (mock *mockRunner) Execute(cmd string, args []string, env map[string]string
|
||||||
return []byte{}, nil
|
return []byte{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func MockExecer(logger *zap.SugaredLogger, kubeContext string) helmexec.Interface {
|
func MockExecer(logger *zap.SugaredLogger, kubeContext string) (helmexec.Interface, error) {
|
||||||
execer := helmexec.New("helm", helmexec.HelmExecOptions{}, logger, "", kubeContext, &mockRunner{})
|
execer, err := helmexec.New("helm", helmexec.HelmExecOptions{}, logger, "", kubeContext, &mockRunner{})
|
||||||
return execer
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return execer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// mocking helmexec.Interface
|
// mocking helmexec.Interface
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ type desiredStateLoader struct {
|
||||||
chart string
|
chart string
|
||||||
fs *filesystem.FileSystem
|
fs *filesystem.FileSystem
|
||||||
|
|
||||||
getHelm func(*state.HelmState) helmexec.Interface
|
getHelm func(*state.HelmState) (helmexec.Interface, error)
|
||||||
|
|
||||||
remote *remote.Remote
|
remote *remote.Remote
|
||||||
logger *zap.SugaredLogger
|
logger *zap.SugaredLogger
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
HelmRequiredVersion = "v3.17.4"
|
HelmRequiredVersion = "v3.18.6"
|
||||||
HelmDiffRecommendedVersion = "v3.12.3"
|
HelmDiffRecommendedVersion = "v3.13.0"
|
||||||
HelmRecommendedVersion = "v3.18.4"
|
HelmRecommendedVersion = "v3.19.0"
|
||||||
HelmSecretsRecommendedVersion = "v4.6.5"
|
HelmSecretsRecommendedVersion = "v4.6.5"
|
||||||
HelmGitRecommendedVersion = "v1.3.0"
|
HelmGitRecommendedVersion = "v1.3.0"
|
||||||
HelmS3RecommendedVersion = "v0.16.3"
|
HelmS3RecommendedVersion = "v0.16.3"
|
||||||
|
|
@ -163,7 +163,10 @@ func (h *HelmfileInit) WhetherContinue(ask string) error {
|
||||||
|
|
||||||
func (h *HelmfileInit) CheckHelmPlugins() error {
|
func (h *HelmfileInit) CheckHelmPlugins() error {
|
||||||
settings := cli.New()
|
settings := cli.New()
|
||||||
helm := helmexec.New(h.helmBinary, helmexec.HelmExecOptions{}, h.logger, "", "", h.runner)
|
helm, err := helmexec.New(h.helmBinary, helmexec.HelmExecOptions{}, h.logger, "", "", h.runner)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
for _, p := range helmPlugins {
|
for _, p := range helmPlugins {
|
||||||
pluginVersion, err := helmexec.GetPluginVersion(p.name, settings.PluginsDirectory)
|
pluginVersion, err := helmexec.GetPluginVersion(p.name, settings.PluginsDirectory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ type SyncOptions struct {
|
||||||
WaitRetries int
|
WaitRetries int
|
||||||
// WaitForJobs is the wait for jobs flag
|
// WaitForJobs is the wait for jobs flag
|
||||||
WaitForJobs bool
|
WaitForJobs bool
|
||||||
|
// Timeout is the timeout flag in seconds
|
||||||
|
Timeout int
|
||||||
// ReuseValues is true if the helm command should reuse the values
|
// ReuseValues is true if the helm command should reuse the values
|
||||||
ReuseValues bool
|
ReuseValues bool
|
||||||
// ResetValues is true if helm command should reset values to charts' default
|
// ResetValues is true if helm command should reset values to charts' default
|
||||||
|
|
@ -124,6 +126,11 @@ func (t *SyncImpl) WaitForJobs() bool {
|
||||||
return t.SyncOptions.WaitForJobs
|
return t.SyncOptions.WaitForJobs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Timeout returns the timeout
|
||||||
|
func (t *SyncImpl) Timeout() int {
|
||||||
|
return t.SyncOptions.Timeout
|
||||||
|
}
|
||||||
|
|
||||||
// ReuseValues returns the ReuseValues.
|
// ReuseValues returns the ReuseValues.
|
||||||
func (t *SyncImpl) ReuseValues() bool {
|
func (t *SyncImpl) ReuseValues() bool {
|
||||||
if !t.ResetValues() {
|
if !t.ResetValues() {
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,13 @@ func parseHelmVersion(versionStr string) (*semver.Version, error) {
|
||||||
return nil, fmt.Errorf("empty helm version")
|
return nil, fmt.Errorf("empty helm version")
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := chartify.FindSemVerInfo(versionStr)
|
// Check if version string starts with "v", if not add it
|
||||||
|
processedVersion := strings.TrimSpace(versionStr)
|
||||||
|
if !strings.HasPrefix(processedVersion, "v") {
|
||||||
|
processedVersion = "v" + processedVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := chartify.FindSemVerInfo(processedVersion)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error find helm srmver version '%s': %w", versionStr, err)
|
return nil, fmt.Errorf("error find helm srmver version '%s': %w", versionStr, err)
|
||||||
|
|
@ -116,11 +122,10 @@ func redactedURL(chart string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New for running helm commands
|
// New for running helm commands
|
||||||
func New(helmBinary string, options HelmExecOptions, logger *zap.SugaredLogger, kubeconfig string, kubeContext string, runner Runner) *execer {
|
func New(helmBinary string, options HelmExecOptions, logger *zap.SugaredLogger, kubeconfig string, kubeContext string, runner Runner) (*execer, error) {
|
||||||
// TODO: proper error handling
|
|
||||||
version, err := GetHelmVersion(helmBinary, runner)
|
version, err := GetHelmVersion(helmBinary, runner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if version.Prerelease() != "" {
|
if version.Prerelease() != "" {
|
||||||
|
|
@ -137,7 +142,7 @@ func New(helmBinary string, options HelmExecOptions, logger *zap.SugaredLogger,
|
||||||
kubeContext: kubeContext,
|
kubeContext: kubeContext,
|
||||||
runner: runner,
|
runner: runner,
|
||||||
decryptedSecrets: make(map[string]*decryptedSecret),
|
decryptedSecrets: make(map[string]*decryptedSecret),
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (helm *execer) SetExtraArgs(args ...string) {
|
func (helm *execer) SetExtraArgs(args ...string) {
|
||||||
|
|
|
||||||
|
|
@ -36,16 +36,22 @@ func (mock *mockRunner) Execute(cmd string, args []string, env map[string]string
|
||||||
return mock.output, mock.err
|
return mock.output, mock.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func MockExecer(logger *zap.SugaredLogger, kubeconfig, kubeContext string) *execer {
|
func MockExecer(logger *zap.SugaredLogger, kubeconfig, kubeContext string) (*execer, error) {
|
||||||
execer := New("helm", HelmExecOptions{}, logger, kubeconfig, kubeContext, &mockRunner{})
|
execer, err := New("helm", HelmExecOptions{}, logger, kubeconfig, kubeContext, &mockRunner{})
|
||||||
return execer
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return execer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test methods
|
// Test methods
|
||||||
|
|
||||||
func TestNewHelmExec(t *testing.T) {
|
func TestNewHelmExec(t *testing.T) {
|
||||||
buffer := bytes.NewBufferString("something")
|
buffer := bytes.NewBufferString("something")
|
||||||
helm := MockExecer(NewLogger(buffer, "debug"), "config", "dev")
|
helm, err := MockExecer(NewLogger(buffer, "debug"), "config", "dev")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
if helm.kubeContext != "dev" {
|
if helm.kubeContext != "dev" {
|
||||||
t.Error("helmexec.New() - kubeContext")
|
t.Error("helmexec.New() - kubeContext")
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +64,10 @@ func TestNewHelmExec(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_SetExtraArgs(t *testing.T) {
|
func Test_SetExtraArgs(t *testing.T) {
|
||||||
helm := MockExecer(NewLogger(os.Stdout, "info"), "config", "dev")
|
helm, err := MockExecer(NewLogger(os.Stdout, "info"), "config", "dev")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
helm.SetExtraArgs()
|
helm.SetExtraArgs()
|
||||||
if len(helm.extra) != 0 {
|
if len(helm.extra) != 0 {
|
||||||
t.Error("helmexec.SetExtraArgs() - passing no arguments should not change extra field")
|
t.Error("helmexec.SetExtraArgs() - passing no arguments should not change extra field")
|
||||||
|
|
@ -74,7 +83,10 @@ func Test_SetExtraArgs(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_SetHelmBinary(t *testing.T) {
|
func Test_SetHelmBinary(t *testing.T) {
|
||||||
helm := MockExecer(NewLogger(os.Stdout, "info"), "config", "dev")
|
helm, err := MockExecer(NewLogger(os.Stdout, "info"), "config", "dev")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
if helm.helmBinary != "helm" {
|
if helm.helmBinary != "helm" {
|
||||||
t.Error("helmexec.command - default command is not helm")
|
t.Error("helmexec.command - default command is not helm")
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +97,10 @@ func Test_SetHelmBinary(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_SetEnableLiveOutput(t *testing.T) {
|
func Test_SetEnableLiveOutput(t *testing.T) {
|
||||||
helm := MockExecer(NewLogger(os.Stdout, "info"), "config", "dev")
|
helm, err := MockExecer(NewLogger(os.Stdout, "info"), "config", "dev")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
if helm.options.EnableLiveOutput {
|
if helm.options.EnableLiveOutput {
|
||||||
t.Error("helmexec.options.EnableLiveOutput should not be enabled by default")
|
t.Error("helmexec.options.EnableLiveOutput should not be enabled by default")
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +111,10 @@ func Test_SetEnableLiveOutput(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_SetDisableForceUpdate(t *testing.T) {
|
func Test_SetDisableForceUpdate(t *testing.T) {
|
||||||
helm := MockExecer(NewLogger(os.Stdout, "info"), "config", "dev")
|
helm, err := MockExecer(NewLogger(os.Stdout, "info"), "config", "dev")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
if helm.options.DisableForceUpdate {
|
if helm.options.DisableForceUpdate {
|
||||||
t.Error("helmexec.options.ForceUpdate should not be enabled by default")
|
t.Error("helmexec.options.ForceUpdate should not be enabled by default")
|
||||||
}
|
}
|
||||||
|
|
@ -155,11 +173,14 @@ exec: helm --kubeconfig config --kube-context dev repo add myRepo https://repo.e
|
||||||
func Test_AddRepo(t *testing.T) {
|
func Test_AddRepo(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Test case with certfile and keyfile
|
// Test case with certfile and keyfile
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
err := helm.AddRepo("myRepo", "https://repo.example.com/", "", "cert.pem", "key.pem", "", "", "", false, false)
|
err = helm.AddRepo("myRepo", "https://repo.example.com/", "", "cert.pem", "key.pem", "", "", "", false, false)
|
||||||
expected := `Adding repo myRepo https://repo.example.com/
|
expected := `Adding repo myRepo https://repo.example.com/
|
||||||
exec: helm --kubeconfig config --kube-context dev repo add myRepo https://repo.example.com/ --cert-file cert.pem --key-file key.pem
|
exec: helm --kubeconfig config --kube-context dev repo add myRepo https://repo.example.com/ --cert-file cert.pem --key-file key.pem
|
||||||
`
|
`
|
||||||
|
|
@ -292,8 +313,11 @@ exec: helm --kubeconfig config --kube-context dev repo add myRepo https://repo.e
|
||||||
func Test_UpdateRepo(t *testing.T) {
|
func Test_UpdateRepo(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
err := helm.UpdateRepo()
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.UpdateRepo()
|
||||||
expected := `Updating repo
|
expected := `Updating repo
|
||||||
exec: helm --kubeconfig config --kube-context dev repo update
|
exec: helm --kubeconfig config --kube-context dev repo update
|
||||||
`
|
`
|
||||||
|
|
@ -346,8 +370,11 @@ exec: helm --kubeconfig config --kube-context dev registry login repo.example.co
|
||||||
func Test_SyncRelease(t *testing.T) {
|
func Test_SyncRelease(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
err := helm.SyncRelease(HelmContext{}, "release", "chart", "default", "--timeout 10", "--wait", "--wait-for-jobs")
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.SyncRelease(HelmContext{}, "release", "chart", "default", "--timeout 10", "--wait", "--wait-for-jobs")
|
||||||
expected := `Upgrading release=release, chart=chart, namespace=default
|
expected := `Upgrading release=release, chart=chart, namespace=default
|
||||||
exec: helm --kubeconfig config --kube-context dev upgrade --install release chart --timeout 10 --wait --wait-for-jobs --history-max 0
|
exec: helm --kubeconfig config --kube-context dev upgrade --install release chart --timeout 10 --wait --wait-for-jobs --history-max 0
|
||||||
`
|
`
|
||||||
|
|
@ -386,8 +413,11 @@ exec: helm --kubeconfig config --kube-context dev upgrade --install release http
|
||||||
func Test_UpdateDeps(t *testing.T) {
|
func Test_UpdateDeps(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
err := helm.UpdateDeps("./chart/foo")
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.UpdateDeps("./chart/foo")
|
||||||
expected := `Updating dependency ./chart/foo
|
expected := `Updating dependency ./chart/foo
|
||||||
exec: helm --kubeconfig config --kube-context dev dependency update ./chart/foo
|
exec: helm --kubeconfig config --kube-context dev dependency update ./chart/foo
|
||||||
`
|
`
|
||||||
|
|
@ -416,8 +446,11 @@ func Test_BuildDeps(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm3Runner := mockRunner{output: []byte("v3.2.4+ge29ce2a")}
|
helm3Runner := mockRunner{output: []byte("v3.2.4+ge29ce2a")}
|
||||||
helm := New("helm", HelmExecOptions{}, logger, "config", "dev", &helm3Runner)
|
helm, err := New("helm", HelmExecOptions{}, logger, "config", "dev", &helm3Runner)
|
||||||
err := helm.BuildDeps("foo", "./chart/foo", []string{"--skip-refresh"}...)
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.BuildDeps("foo", "./chart/foo", []string{"--skip-refresh"}...)
|
||||||
expected := `Building dependency release=foo, chart=./chart/foo
|
expected := `Building dependency release=foo, chart=./chart/foo
|
||||||
exec: helm --kubeconfig config --kube-context dev dependency build ./chart/foo --skip-refresh
|
exec: helm --kubeconfig config --kube-context dev dependency build ./chart/foo --skip-refresh
|
||||||
v3.2.4+ge29ce2a
|
v3.2.4+ge29ce2a
|
||||||
|
|
@ -458,7 +491,10 @@ v3.2.4+ge29ce2a
|
||||||
|
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
helm2Runner := mockRunner{output: []byte("Client: v2.16.1+ge13bc94")}
|
helm2Runner := mockRunner{output: []byte("Client: v2.16.1+ge13bc94")}
|
||||||
helm = New("helm", HelmExecOptions{}, logger, "config", "dev", &helm2Runner)
|
helm, err = New("helm", HelmExecOptions{}, logger, "config", "dev", &helm2Runner)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
err = helm.BuildDeps("foo", "./chart/foo")
|
err = helm.BuildDeps("foo", "./chart/foo")
|
||||||
expected = `Building dependency release=foo, chart=./chart/foo
|
expected = `Building dependency release=foo, chart=./chart/foo
|
||||||
exec: helm --kubeconfig config --kube-context dev dependency build ./chart/foo
|
exec: helm --kubeconfig config --kube-context dev dependency build ./chart/foo
|
||||||
|
|
@ -484,14 +520,17 @@ func Test_DecryptSecret(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
tmpFilePath := "path/to/temp/file"
|
tmpFilePath := "path/to/temp/file"
|
||||||
helm.writeTempFile = func(content []byte) (string, error) {
|
helm.writeTempFile = func(content []byte) (string, error) {
|
||||||
return tmpFilePath, nil
|
return tmpFilePath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := helm.DecryptSecret(HelmContext{}, "secretName")
|
_, err = helm.DecryptSecret(HelmContext{}, "secretName")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error: %v", err)
|
t.Errorf("Error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -533,7 +572,10 @@ func Test_DecryptSecretWithGotmpl(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
tmpFilePath := "path/to/temp/file"
|
tmpFilePath := "path/to/temp/file"
|
||||||
helm.writeTempFile = func(content []byte) (string, error) {
|
helm.writeTempFile = func(content []byte) (string, error) {
|
||||||
|
|
@ -541,7 +583,7 @@ func Test_DecryptSecretWithGotmpl(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
secretName := "secretName.yaml.gotmpl"
|
secretName := "secretName.yaml.gotmpl"
|
||||||
_, err := helm.DecryptSecret(HelmContext{}, secretName)
|
_, err = helm.DecryptSecret(HelmContext{}, secretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error: %v", err)
|
t.Errorf("Error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -566,8 +608,11 @@ Decrypted %s/secretName.yaml.gotmpl into %s
|
||||||
func Test_DiffRelease(t *testing.T) {
|
func Test_DiffRelease(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
err := helm.DiffRelease(HelmContext{}, "release", "chart", "default", false, "--timeout 10", "--wait", "--wait-for-jobs")
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.DiffRelease(HelmContext{}, "release", "chart", "default", false, "--timeout 10", "--wait", "--wait-for-jobs")
|
||||||
expected := `Comparing release=release, chart=chart, namespace=default
|
expected := `Comparing release=release, chart=chart, namespace=default
|
||||||
|
|
||||||
exec: helm --kubeconfig config --kube-context dev diff upgrade --allow-unreleased release chart --timeout 10 --wait --wait-for-jobs
|
exec: helm --kubeconfig config --kube-context dev diff upgrade --allow-unreleased release chart --timeout 10 --wait --wait-for-jobs
|
||||||
|
|
@ -609,8 +654,11 @@ exec: helm --kubeconfig config --kube-context dev diff upgrade --allow-unrelease
|
||||||
func Test_DeleteRelease(t *testing.T) {
|
func Test_DeleteRelease(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
err := helm.DeleteRelease(HelmContext{}, "release")
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.DeleteRelease(HelmContext{}, "release")
|
||||||
expected := `Deleting release
|
expected := `Deleting release
|
||||||
exec: helm --kubeconfig config --kube-context dev delete release
|
exec: helm --kubeconfig config --kube-context dev delete release
|
||||||
`
|
`
|
||||||
|
|
@ -624,8 +672,11 @@ exec: helm --kubeconfig config --kube-context dev delete release
|
||||||
func Test_DeleteRelease_Flags(t *testing.T) {
|
func Test_DeleteRelease_Flags(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
err := helm.DeleteRelease(HelmContext{}, "release", "--purge")
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.DeleteRelease(HelmContext{}, "release", "--purge")
|
||||||
expected := `Deleting release
|
expected := `Deleting release
|
||||||
exec: helm --kubeconfig config --kube-context dev delete release --purge
|
exec: helm --kubeconfig config --kube-context dev delete release --purge
|
||||||
`
|
`
|
||||||
|
|
@ -640,8 +691,11 @@ exec: helm --kubeconfig config --kube-context dev delete release --purge
|
||||||
func Test_TestRelease(t *testing.T) {
|
func Test_TestRelease(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
err := helm.TestRelease(HelmContext{}, "release")
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.TestRelease(HelmContext{}, "release")
|
||||||
expected := `Testing release
|
expected := `Testing release
|
||||||
exec: helm --kubeconfig config --kube-context dev test release
|
exec: helm --kubeconfig config --kube-context dev test release
|
||||||
`
|
`
|
||||||
|
|
@ -655,8 +709,11 @@ exec: helm --kubeconfig config --kube-context dev test release
|
||||||
func Test_TestRelease_Flags(t *testing.T) {
|
func Test_TestRelease_Flags(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
err := helm.TestRelease(HelmContext{}, "release", "--cleanup", "--timeout", "60")
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.TestRelease(HelmContext{}, "release", "--cleanup", "--timeout", "60")
|
||||||
expected := `Testing release
|
expected := `Testing release
|
||||||
exec: helm --kubeconfig config --kube-context dev test release --cleanup --timeout 60
|
exec: helm --kubeconfig config --kube-context dev test release --cleanup --timeout 60
|
||||||
`
|
`
|
||||||
|
|
@ -671,8 +728,11 @@ exec: helm --kubeconfig config --kube-context dev test release --cleanup --timeo
|
||||||
func Test_ReleaseStatus(t *testing.T) {
|
func Test_ReleaseStatus(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
err := helm.ReleaseStatus(HelmContext{}, "myRelease")
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.ReleaseStatus(HelmContext{}, "myRelease")
|
||||||
expected := `Getting status myRelease
|
expected := `Getting status myRelease
|
||||||
exec: helm --kubeconfig config --kube-context dev status myRelease
|
exec: helm --kubeconfig config --kube-context dev status myRelease
|
||||||
`
|
`
|
||||||
|
|
@ -687,9 +747,12 @@ exec: helm --kubeconfig config --kube-context dev status myRelease
|
||||||
func Test_exec(t *testing.T) {
|
func Test_exec(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "", "")
|
helm, err := MockExecer(logger, "", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
env := map[string]string{}
|
env := map[string]string{}
|
||||||
_, err := helm.exec([]string{"version"}, env, nil)
|
_, err = helm.exec([]string{"version"}, env, nil)
|
||||||
expected := `exec: helm version
|
expected := `exec: helm version
|
||||||
`
|
`
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -699,14 +762,20 @@ func Test_exec(t *testing.T) {
|
||||||
t.Errorf("helmexec.exec()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
t.Errorf("helmexec.exec()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
helm = MockExecer(logger, "config", "dev")
|
helm, err = MockExecer(logger, "config", "dev")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
ret, _ := helm.exec([]string{"diff"}, env, nil)
|
ret, _ := helm.exec([]string{"diff"}, env, nil)
|
||||||
if len(ret) != 0 {
|
if len(ret) != 0 {
|
||||||
t.Error("helmexec.exec() - expected empty return value")
|
t.Error("helmexec.exec() - expected empty return value")
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
helm = MockExecer(logger, "config", "dev")
|
helm, err = MockExecer(logger, "config", "dev")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
_, err = helm.exec([]string{"diff", "release", "chart", "--timeout 10", "--wait", "--wait-for-jobs"}, env, nil)
|
_, err = helm.exec([]string{"diff", "release", "chart", "--timeout 10", "--wait", "--wait-for-jobs"}, env, nil)
|
||||||
expected = `exec: helm --kubeconfig config --kube-context dev diff release chart --timeout 10 --wait --wait-for-jobs
|
expected = `exec: helm --kubeconfig config --kube-context dev diff release chart --timeout 10 --wait --wait-for-jobs
|
||||||
`
|
`
|
||||||
|
|
@ -741,7 +810,10 @@ func Test_exec(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
helm = MockExecer(logger, "", "")
|
helm, err = MockExecer(logger, "", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
helm.SetHelmBinary("overwritten")
|
helm.SetHelmBinary("overwritten")
|
||||||
_, err = helm.exec([]string{"version"}, env, nil)
|
_, err = helm.exec([]string{"version"}, env, nil)
|
||||||
expected = `exec: overwritten version
|
expected = `exec: overwritten version
|
||||||
|
|
@ -757,8 +829,11 @@ func Test_exec(t *testing.T) {
|
||||||
func Test_Lint(t *testing.T) {
|
func Test_Lint(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
err := helm.Lint("release", "path/to/chart", "--values", "file.yml")
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.Lint("release", "path/to/chart", "--values", "file.yml")
|
||||||
expected := `Linting release=release, chart=path/to/chart
|
expected := `Linting release=release, chart=path/to/chart
|
||||||
exec: helm --kubeconfig config --kube-context dev lint path/to/chart --values file.yml
|
exec: helm --kubeconfig config --kube-context dev lint path/to/chart --values file.yml
|
||||||
`
|
`
|
||||||
|
|
@ -773,8 +848,11 @@ exec: helm --kubeconfig config --kube-context dev lint path/to/chart --values fi
|
||||||
func Test_Fetch(t *testing.T) {
|
func Test_Fetch(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
err := helm.Fetch("chart", "--version", "1.2.3", "--untar", "--untardir", "/tmp/dir")
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.Fetch("chart", "--version", "1.2.3", "--untar", "--untardir", "/tmp/dir")
|
||||||
expected := `Fetching chart
|
expected := `Fetching chart
|
||||||
exec: helm --kubeconfig config --kube-context dev fetch chart --version 1.2.3 --untar --untardir /tmp/dir
|
exec: helm --kubeconfig config --kube-context dev fetch chart --version 1.2.3 --untar --untardir /tmp/dir
|
||||||
`
|
`
|
||||||
|
|
@ -848,8 +926,11 @@ exec: helm --kubeconfig config --kube-context dev pull oci://repo/helm-charts --
|
||||||
tt := tests[i]
|
tt := tests[i]
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
helm := New(tt.helmBin, HelmExecOptions{}, logger, "config", "dev", &mockRunner{output: []byte(tt.helmVersion)})
|
helm, err := New(tt.helmBin, HelmExecOptions{}, logger, "config", "dev", &mockRunner{output: []byte(tt.helmVersion)})
|
||||||
err := helm.ChartPull(tt.chartName, tt.chartPath, tt.chartFlags...)
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.ChartPull(tt.chartName, tt.chartPath, tt.chartFlags...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -922,8 +1003,11 @@ func Test_LogLevels(t *testing.T) {
|
||||||
for logLevel, expected := range logLevelTests {
|
for logLevel, expected := range logLevelTests {
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
logger := NewLogger(&buffer, logLevel)
|
logger := NewLogger(&buffer, logLevel)
|
||||||
helm := MockExecer(logger, "", "")
|
helm, err := MockExecer(logger, "", "")
|
||||||
err := helm.AddRepo("myRepo", "https://repo.example.com/", "", "", "", "example_user", "example_password", "", false, false)
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.AddRepo("myRepo", "https://repo.example.com/", "", "", "", "example_user", "example_password", "", false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -951,8 +1035,11 @@ func Test_mergeEnv(t *testing.T) {
|
||||||
func Test_Template(t *testing.T) {
|
func Test_Template(t *testing.T) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
logger := NewLogger(&buffer, "debug")
|
logger := NewLogger(&buffer, "debug")
|
||||||
helm := MockExecer(logger, "config", "dev")
|
helm, err := MockExecer(logger, "config", "dev")
|
||||||
err := helm.TemplateRelease("release", "path/to/chart", "--values", "file.yml")
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
err = helm.TemplateRelease("release", "path/to/chart", "--values", "file.yml")
|
||||||
expected := `Templating release=release, chart=path/to/chart
|
expected := `Templating release=release, chart=path/to/chart
|
||||||
exec: helm --kubeconfig config --kube-context dev template release path/to/chart --values file.yml
|
exec: helm --kubeconfig config --kube-context dev template release path/to/chart --values file.yml
|
||||||
`
|
`
|
||||||
|
|
@ -978,13 +1065,19 @@ exec: helm --kubeconfig config --kube-context dev template release https://examp
|
||||||
|
|
||||||
func Test_IsHelm3(t *testing.T) {
|
func Test_IsHelm3(t *testing.T) {
|
||||||
helm2Runner := mockRunner{output: []byte("Client: v2.16.0+ge13bc94\n")}
|
helm2Runner := mockRunner{output: []byte("Client: v2.16.0+ge13bc94\n")}
|
||||||
helm := New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "", "dev", &helm2Runner)
|
helm, err := New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "", "dev", &helm2Runner)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
if helm.IsHelm3() {
|
if helm.IsHelm3() {
|
||||||
t.Error("helmexec.IsHelm3() - Detected Helm 3 with Helm 2 version")
|
t.Error("helmexec.IsHelm3() - Detected Helm 3 with Helm 2 version")
|
||||||
}
|
}
|
||||||
|
|
||||||
helm3Runner := mockRunner{output: []byte("v3.0.0+ge29ce2a\n")}
|
helm3Runner := mockRunner{output: []byte("v3.0.0+ge29ce2a\n")}
|
||||||
helm = New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "", "dev", &helm3Runner)
|
helm, err = New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "", "dev", &helm3Runner)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
if !helm.IsHelm3() {
|
if !helm.IsHelm3() {
|
||||||
t.Error("helmexec.IsHelm3() - Failed to detect Helm 3")
|
t.Error("helmexec.IsHelm3() - Failed to detect Helm 3")
|
||||||
}
|
}
|
||||||
|
|
@ -1012,14 +1105,20 @@ func Test_GetPluginVersion(t *testing.T) {
|
||||||
|
|
||||||
func Test_GetVersion(t *testing.T) {
|
func Test_GetVersion(t *testing.T) {
|
||||||
helm2Runner := mockRunner{output: []byte("Client: v2.16.1+ge13bc94\n")}
|
helm2Runner := mockRunner{output: []byte("Client: v2.16.1+ge13bc94\n")}
|
||||||
helm := New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "", "dev", &helm2Runner)
|
helm, err := New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "", "dev", &helm2Runner)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
ver := helm.GetVersion()
|
ver := helm.GetVersion()
|
||||||
if ver.Major != 2 || ver.Minor != 16 || ver.Patch != 1 {
|
if ver.Major != 2 || ver.Minor != 16 || ver.Patch != 1 {
|
||||||
t.Errorf("helmexec.GetVersion - did not detect correct Helm2 version; it was: %+v", ver)
|
t.Errorf("helmexec.GetVersion - did not detect correct Helm2 version; it was: %+v", ver)
|
||||||
}
|
}
|
||||||
|
|
||||||
helm3Runner := mockRunner{output: []byte("v3.2.4+ge29ce2a\n")}
|
helm3Runner := mockRunner{output: []byte("v3.2.4+ge29ce2a\n")}
|
||||||
helm = New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "", "dev", &helm3Runner)
|
helm, err = New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "", "dev", &helm3Runner)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
ver = helm.GetVersion()
|
ver = helm.GetVersion()
|
||||||
if ver.Major != 3 || ver.Minor != 2 || ver.Patch != 4 {
|
if ver.Major != 3 || ver.Minor != 2 || ver.Patch != 4 {
|
||||||
t.Errorf("helmexec.GetVersion - did not detect correct Helm3 version; it was: %+v", ver)
|
t.Errorf("helmexec.GetVersion - did not detect correct Helm3 version; it was: %+v", ver)
|
||||||
|
|
@ -1028,7 +1127,10 @@ func Test_GetVersion(t *testing.T) {
|
||||||
|
|
||||||
func Test_IsVersionAtLeast(t *testing.T) {
|
func Test_IsVersionAtLeast(t *testing.T) {
|
||||||
helm2Runner := mockRunner{output: []byte("Client: v2.16.1+ge13bc94\n")}
|
helm2Runner := mockRunner{output: []byte("Client: v2.16.1+ge13bc94\n")}
|
||||||
helm := New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "", "dev", &helm2Runner)
|
helm, err := New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "", "dev", &helm2Runner)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
if !helm.IsVersionAtLeast("2.1.0") {
|
if !helm.IsVersionAtLeast("2.1.0") {
|
||||||
t.Error("helmexec.IsVersionAtLeast - 2.16.1 not atleast 2.1")
|
t.Error("helmexec.IsVersionAtLeast - 2.16.1 not atleast 2.1")
|
||||||
}
|
}
|
||||||
|
|
@ -1140,6 +1242,24 @@ func TestParseHelmVersion(t *testing.T) {
|
||||||
want: nil,
|
want: nil,
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "version without v prefix",
|
||||||
|
version: "3.2.4",
|
||||||
|
want: semver.MustParse("v3.2.4"),
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "version without v prefix with build info",
|
||||||
|
version: "3.2.4+ge29ce2a",
|
||||||
|
want: semver.MustParse("v3.2.4+ge29ce2a"),
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "version without v prefix with spaces",
|
||||||
|
version: " 3.2.4 ",
|
||||||
|
want: semver.MustParse("v3.2.4"),
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ func Output(ctx context.Context, c *exec.Cmd, stripArgsValuesOnExitError bool, l
|
||||||
exitStatus := waitStatus.ExitStatus()
|
exitStatus := waitStatus.ExitStatus()
|
||||||
err = newExitError(c.Path, c.Args, exitStatus, ee, stderr.String(), combined.String(), stripArgsValuesOnExitError)
|
err = newExitError(c.Path, c.Args, exitStatus, ee, stderr.String(), combined.String(), stripArgsValuesOnExitError)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unexpected error: %v", err))
|
err = fmt.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ type StateCreator struct {
|
||||||
|
|
||||||
LoadFile func(inheritedEnv, overrodeEnv *environment.Environment, baseDir, file string, evaluateBases bool) (*HelmState, error)
|
LoadFile func(inheritedEnv, overrodeEnv *environment.Environment, baseDir, file string, evaluateBases bool) (*HelmState, error)
|
||||||
|
|
||||||
getHelm func(*HelmState) helmexec.Interface
|
getHelm func(*HelmState) (helmexec.Interface, error)
|
||||||
|
|
||||||
overrideHelmBinary string
|
overrideHelmBinary string
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ type StateCreator struct {
|
||||||
lockFile string
|
lockFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCreator(logger *zap.SugaredLogger, fs *filesystem.FileSystem, valsRuntime vals.Evaluator, getHelm func(*HelmState) helmexec.Interface, overrideHelmBinary string, overrideKustomizeBinary string, remote *remote.Remote, enableLiveOutput bool, lockFile string) *StateCreator {
|
func NewCreator(logger *zap.SugaredLogger, fs *filesystem.FileSystem, valsRuntime vals.Evaluator, getHelm func(*HelmState) (helmexec.Interface, error), overrideHelmBinary string, overrideKustomizeBinary string, remote *remote.Remote, enableLiveOutput bool, lockFile string) *StateCreator {
|
||||||
return &StateCreator{
|
return &StateCreator{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
|
||||||
|
|
@ -352,7 +352,10 @@ func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEn
|
||||||
func (c *StateCreator) scatterGatherEnvSecretFiles(st *HelmState, envSecretFiles []string, envVals map[string]any, keepFileExtensions []string) ([]string, error) {
|
func (c *StateCreator) scatterGatherEnvSecretFiles(st *HelmState, envSecretFiles []string, envVals map[string]any, keepFileExtensions []string) ([]string, error) {
|
||||||
var errs []error
|
var errs []error
|
||||||
var decryptedFilesKeeper []string
|
var decryptedFilesKeeper []string
|
||||||
helm := c.getHelm(st)
|
helm, err := c.getHelm(st)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
inputs := envSecretFiles
|
inputs := envSecretFiles
|
||||||
inputsSize := len(inputs)
|
inputsSize := len(inputs)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
package state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
"github.com/helmfile/helmfile/pkg/exectest"
|
||||||
|
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIsReleaseInstalled_HandlesConnectionError(t *testing.T) {
|
||||||
|
logger := zap.NewNop().Sugar()
|
||||||
|
|
||||||
|
state := &HelmState{
|
||||||
|
logger: logger,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a custom helm mock that fails on List operations
|
||||||
|
helm := &CustomFailingHelm{
|
||||||
|
Helm: &exectest.Helm{
|
||||||
|
DiffMutex: &sync.Mutex{},
|
||||||
|
ChartsMutex: &sync.Mutex{},
|
||||||
|
ReleasesMutex: &sync.Mutex{},
|
||||||
|
Helm3: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
release := ReleaseSpec{
|
||||||
|
Name: "test-release",
|
||||||
|
Chart: "test/chart",
|
||||||
|
Namespace: "default",
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should return an error due to connection failure
|
||||||
|
_, err := state.isReleaseInstalled(helmexec.HelmContext{}, helm, release)
|
||||||
|
|
||||||
|
// Verify that error was propagated
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected isReleaseInstalled to return error when Kubernetes is unreachable, but got no error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err.Error() == "" {
|
||||||
|
t.Fatalf("expected isReleaseInstalled to return meaningful error when Kubernetes is unreachable, but got empty error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the error contains the expected message
|
||||||
|
expectedMsg := "Kubernetes cluster unreachable"
|
||||||
|
if err.Error() != expectedMsg && !strings.Contains(err.Error(), "Kubernetes cluster unreachable") {
|
||||||
|
t.Fatalf("expected error to contain 'Kubernetes cluster unreachable', but got: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomFailingHelm wraps exectest.Helm and overrides List to simulate failures
|
||||||
|
type CustomFailingHelm struct {
|
||||||
|
*exectest.Helm
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *CustomFailingHelm) List(context helmexec.HelmContext, filter string, flags ...string) (string, error) {
|
||||||
|
return "", errors.New("Kubernetes cluster unreachable: Get \"http://localhost:8080/version\": dial tcp [::1]:8080: connect: connection refused")
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/helmfile/chartify"
|
"github.com/helmfile/chartify"
|
||||||
|
|
@ -158,31 +157,17 @@ func (st *HelmState) appendWaitForJobsFlags(flags []string, release *ReleaseSpec
|
||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) appendWaitFlags(flags []string, helm helmexec.Interface, release *ReleaseSpec, ops *SyncOpts) []string {
|
func (st *HelmState) appendWaitFlags(flags []string, release *ReleaseSpec, ops *SyncOpts) []string {
|
||||||
var hasWait bool
|
|
||||||
switch {
|
switch {
|
||||||
case release.Wait != nil && *release.Wait:
|
case release.Wait != nil && *release.Wait:
|
||||||
hasWait = true
|
|
||||||
flags = append(flags, "--wait")
|
flags = append(flags, "--wait")
|
||||||
case ops != nil && ops.Wait:
|
case ops != nil && ops.Wait:
|
||||||
hasWait = true
|
|
||||||
flags = append(flags, "--wait")
|
flags = append(flags, "--wait")
|
||||||
case release.Wait == nil && st.HelmDefaults.Wait:
|
case release.Wait == nil && st.HelmDefaults.Wait:
|
||||||
hasWait = true
|
|
||||||
flags = append(flags, "--wait")
|
flags = append(flags, "--wait")
|
||||||
}
|
}
|
||||||
// see https://github.com/helm/helm/releases/tag/v3.15.0
|
// Note: --wait-retries flag has been removed from Helm and is no longer supported
|
||||||
// https://github.com/helm/helm/commit/fc74964
|
// WaitRetries configuration is preserved for backward compatibility but ignored
|
||||||
if hasWait && helm.IsVersionAtLeast("3.15.0") {
|
|
||||||
switch {
|
|
||||||
case release.WaitRetries != nil && *release.WaitRetries > 0:
|
|
||||||
flags = append(flags, "--wait-retries", strconv.Itoa(*release.WaitRetries))
|
|
||||||
case ops != nil && ops.WaitRetries > 0:
|
|
||||||
flags = append(flags, "--wait-retries", strconv.Itoa(ops.WaitRetries))
|
|
||||||
case release.WaitRetries == nil && st.HelmDefaults.WaitRetries > 0:
|
|
||||||
flags = append(flags, "--wait-retries", strconv.Itoa(st.HelmDefaults.WaitRetries))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,6 @@ func TestAppendWaitFlags(t *testing.T) {
|
||||||
name string
|
name string
|
||||||
release *ReleaseSpec
|
release *ReleaseSpec
|
||||||
syncOpts *SyncOpts
|
syncOpts *SyncOpts
|
||||||
helm helmexec.Interface
|
|
||||||
helmSpec HelmSpec
|
helmSpec HelmSpec
|
||||||
expected []string
|
expected []string
|
||||||
}{
|
}{
|
||||||
|
|
@ -85,7 +84,6 @@ func TestAppendWaitFlags(t *testing.T) {
|
||||||
name: "release wait",
|
name: "release wait",
|
||||||
release: &ReleaseSpec{Wait: &[]bool{true}[0]},
|
release: &ReleaseSpec{Wait: &[]bool{true}[0]},
|
||||||
syncOpts: nil,
|
syncOpts: nil,
|
||||||
helm: testutil.NewVersionHelmExec("3.11.0"),
|
|
||||||
helmSpec: HelmSpec{},
|
helmSpec: HelmSpec{},
|
||||||
expected: []string{"--wait"},
|
expected: []string{"--wait"},
|
||||||
},
|
},
|
||||||
|
|
@ -93,7 +91,6 @@ func TestAppendWaitFlags(t *testing.T) {
|
||||||
name: "cli flags wait",
|
name: "cli flags wait",
|
||||||
release: &ReleaseSpec{},
|
release: &ReleaseSpec{},
|
||||||
syncOpts: &SyncOpts{Wait: true},
|
syncOpts: &SyncOpts{Wait: true},
|
||||||
helm: testutil.NewVersionHelmExec("3.11.0"),
|
|
||||||
helmSpec: HelmSpec{},
|
helmSpec: HelmSpec{},
|
||||||
expected: []string{"--wait"},
|
expected: []string{"--wait"},
|
||||||
},
|
},
|
||||||
|
|
@ -101,7 +98,6 @@ func TestAppendWaitFlags(t *testing.T) {
|
||||||
name: "helm defaults wait",
|
name: "helm defaults wait",
|
||||||
release: &ReleaseSpec{},
|
release: &ReleaseSpec{},
|
||||||
syncOpts: nil,
|
syncOpts: nil,
|
||||||
helm: testutil.NewVersionHelmExec("3.11.0"),
|
|
||||||
helmSpec: HelmSpec{Wait: true},
|
helmSpec: HelmSpec{Wait: true},
|
||||||
expected: []string{"--wait"},
|
expected: []string{"--wait"},
|
||||||
},
|
},
|
||||||
|
|
@ -109,7 +105,6 @@ func TestAppendWaitFlags(t *testing.T) {
|
||||||
name: "release wait false",
|
name: "release wait false",
|
||||||
release: &ReleaseSpec{Wait: &[]bool{false}[0]},
|
release: &ReleaseSpec{Wait: &[]bool{false}[0]},
|
||||||
syncOpts: nil,
|
syncOpts: nil,
|
||||||
helm: testutil.NewVersionHelmExec("3.11.0"),
|
|
||||||
helmSpec: HelmSpec{Wait: true},
|
helmSpec: HelmSpec{Wait: true},
|
||||||
expected: []string{},
|
expected: []string{},
|
||||||
},
|
},
|
||||||
|
|
@ -117,7 +112,6 @@ func TestAppendWaitFlags(t *testing.T) {
|
||||||
name: "cli flags wait false",
|
name: "cli flags wait false",
|
||||||
release: &ReleaseSpec{},
|
release: &ReleaseSpec{},
|
||||||
syncOpts: &SyncOpts{},
|
syncOpts: &SyncOpts{},
|
||||||
helm: testutil.NewVersionHelmExec("3.11.0"),
|
|
||||||
helmSpec: HelmSpec{Wait: true},
|
helmSpec: HelmSpec{Wait: true},
|
||||||
expected: []string{"--wait"},
|
expected: []string{"--wait"},
|
||||||
},
|
},
|
||||||
|
|
@ -125,66 +119,58 @@ func TestAppendWaitFlags(t *testing.T) {
|
||||||
name: "helm defaults wait false",
|
name: "helm defaults wait false",
|
||||||
release: &ReleaseSpec{},
|
release: &ReleaseSpec{},
|
||||||
syncOpts: nil,
|
syncOpts: nil,
|
||||||
helm: testutil.NewVersionHelmExec("3.11.0"),
|
|
||||||
helmSpec: HelmSpec{Wait: false},
|
helmSpec: HelmSpec{Wait: false},
|
||||||
expected: []string{},
|
expected: []string{},
|
||||||
},
|
},
|
||||||
// --wait-retries
|
// --wait-retries flag has been removed from Helm
|
||||||
{
|
{
|
||||||
name: "release wait and retry unsupported",
|
name: "release wait and retry unsupported",
|
||||||
release: &ReleaseSpec{Wait: &[]bool{true}[0], WaitRetries: &[]int{1}[0]},
|
release: &ReleaseSpec{Wait: &[]bool{true}[0], WaitRetries: &[]int{1}[0]},
|
||||||
syncOpts: nil,
|
syncOpts: nil,
|
||||||
helm: testutil.NewVersionHelmExec("3.11.0"),
|
|
||||||
helmSpec: HelmSpec{},
|
helmSpec: HelmSpec{},
|
||||||
expected: []string{"--wait"},
|
expected: []string{"--wait"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "release wait and retry supported",
|
name: "release wait and retry - retries ignored",
|
||||||
release: &ReleaseSpec{Wait: &[]bool{true}[0], WaitRetries: &[]int{1}[0]},
|
release: &ReleaseSpec{Wait: &[]bool{true}[0], WaitRetries: &[]int{1}[0]},
|
||||||
syncOpts: nil,
|
syncOpts: nil,
|
||||||
helm: testutil.NewVersionHelmExec("3.15.0"),
|
|
||||||
helmSpec: HelmSpec{},
|
helmSpec: HelmSpec{},
|
||||||
expected: []string{"--wait", "--wait-retries", "1"},
|
expected: []string{"--wait"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no wait retry",
|
name: "no wait retry",
|
||||||
release: &ReleaseSpec{WaitRetries: &[]int{1}[0]},
|
release: &ReleaseSpec{WaitRetries: &[]int{1}[0]},
|
||||||
syncOpts: nil,
|
syncOpts: nil,
|
||||||
helm: testutil.NewVersionHelmExec("3.15.0"),
|
|
||||||
helmSpec: HelmSpec{},
|
helmSpec: HelmSpec{},
|
||||||
expected: []string{},
|
expected: []string{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "cli flags wait and retry",
|
name: "cli flags wait and retry - retries ignored",
|
||||||
release: &ReleaseSpec{},
|
release: &ReleaseSpec{},
|
||||||
syncOpts: &SyncOpts{Wait: true, WaitRetries: 2},
|
syncOpts: &SyncOpts{Wait: true, WaitRetries: 2},
|
||||||
helm: testutil.NewVersionHelmExec("3.15.0"),
|
|
||||||
helmSpec: HelmSpec{},
|
helmSpec: HelmSpec{},
|
||||||
expected: []string{"--wait", "--wait-retries", "2"},
|
expected: []string{"--wait"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "helm defaults wait retry",
|
name: "helm defaults wait retry - retries ignored",
|
||||||
release: &ReleaseSpec{},
|
release: &ReleaseSpec{},
|
||||||
syncOpts: nil,
|
syncOpts: nil,
|
||||||
helm: testutil.NewVersionHelmExec("3.15.0"),
|
|
||||||
helmSpec: HelmSpec{Wait: true, WaitRetries: 3},
|
helmSpec: HelmSpec{Wait: true, WaitRetries: 3},
|
||||||
expected: []string{"--wait", "--wait-retries", "3"},
|
expected: []string{"--wait"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "release wait default retries",
|
name: "release wait default retries - retries ignored",
|
||||||
release: &ReleaseSpec{Wait: &[]bool{true}[0]},
|
release: &ReleaseSpec{Wait: &[]bool{true}[0]},
|
||||||
syncOpts: nil,
|
syncOpts: nil,
|
||||||
helm: testutil.NewVersionHelmExec("3.15.0"),
|
|
||||||
helmSpec: HelmSpec{WaitRetries: 4},
|
helmSpec: HelmSpec{WaitRetries: 4},
|
||||||
expected: []string{"--wait", "--wait-retries", "4"},
|
expected: []string{"--wait"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "release retries default wait",
|
name: "release retries default wait - retries ignored",
|
||||||
release: &ReleaseSpec{WaitRetries: &[]int{5}[0]},
|
release: &ReleaseSpec{WaitRetries: &[]int{5}[0]},
|
||||||
syncOpts: nil,
|
syncOpts: nil,
|
||||||
helm: testutil.NewVersionHelmExec("3.15.0"),
|
|
||||||
helmSpec: HelmSpec{Wait: true},
|
helmSpec: HelmSpec{Wait: true},
|
||||||
expected: []string{"--wait", "--wait-retries", "5"},
|
expected: []string{"--wait"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,7 +178,7 @@ func TestAppendWaitFlags(t *testing.T) {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
st := &HelmState{}
|
st := &HelmState{}
|
||||||
st.HelmDefaults = tt.helmSpec
|
st.HelmDefaults = tt.helmSpec
|
||||||
got := st.appendWaitFlags([]string{}, tt.helm, tt.release, tt.syncOpts)
|
got := st.appendWaitFlags([]string{}, tt.release, tt.syncOpts)
|
||||||
require.Equalf(t, tt.expected, got, "appendWaitFlags() = %v, want %v", got, tt.expected)
|
require.Equalf(t, tt.expected, got, "appendWaitFlags() = %v, want %v", got, tt.expected)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,7 @@ type HelmSpec struct {
|
||||||
// Wait, if set to true, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful
|
// Wait, if set to true, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful
|
||||||
Wait bool `yaml:"wait"`
|
Wait bool `yaml:"wait"`
|
||||||
// WaitRetries, if set and --wait enabled, will retry any failed check on resource state, except if HTTP status code < 500 is received, subject to the specified number of retries
|
// WaitRetries, if set and --wait enabled, will retry any failed check on resource state, except if HTTP status code < 500 is received, subject to the specified number of retries
|
||||||
|
// DEPRECATED: This field is ignored as the --wait-retries flag was removed from Helm. Preserved for backward compatibility.
|
||||||
WaitRetries int `yaml:"waitRetries"`
|
WaitRetries int `yaml:"waitRetries"`
|
||||||
// WaitForJobs, if set and --wait enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as --timeout
|
// WaitForJobs, if set and --wait enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as --timeout
|
||||||
WaitForJobs bool `yaml:"waitForJobs"`
|
WaitForJobs bool `yaml:"waitForJobs"`
|
||||||
|
|
@ -267,6 +268,7 @@ type ReleaseSpec struct {
|
||||||
// Wait, if set to true, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful
|
// Wait, if set to true, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful
|
||||||
Wait *bool `yaml:"wait,omitempty"`
|
Wait *bool `yaml:"wait,omitempty"`
|
||||||
// WaitRetries, if set and --wait enabled, will retry any failed check on resource state, except if HTTP status code < 500 is received, subject to the specified number of retries
|
// WaitRetries, if set and --wait enabled, will retry any failed check on resource state, except if HTTP status code < 500 is received, subject to the specified number of retries
|
||||||
|
// DEPRECATED: This field is ignored as the --wait-retries flag was removed from Helm. Preserved for backward compatibility.
|
||||||
WaitRetries *int `yaml:"waitRetries,omitempty"`
|
WaitRetries *int `yaml:"waitRetries,omitempty"`
|
||||||
// WaitForJobs, if set and --wait enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as --timeout
|
// WaitForJobs, if set and --wait enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as --timeout
|
||||||
WaitForJobs *bool `yaml:"waitForJobs,omitempty"`
|
WaitForJobs *bool `yaml:"waitForJobs,omitempty"`
|
||||||
|
|
@ -813,6 +815,7 @@ type SyncOpts struct {
|
||||||
Wait bool
|
Wait bool
|
||||||
WaitRetries int
|
WaitRetries int
|
||||||
WaitForJobs bool
|
WaitForJobs bool
|
||||||
|
Timeout int
|
||||||
SyncReleaseLabels bool
|
SyncReleaseLabels bool
|
||||||
ReuseValues bool
|
ReuseValues bool
|
||||||
ResetValues bool
|
ResetValues bool
|
||||||
|
|
@ -1269,6 +1272,19 @@ func (st *HelmState) GetRepositoryAndNameFromChartName(chartName string) (*Repos
|
||||||
return nil, chartName
|
return nil, chartName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var mutexMap sync.Map
|
||||||
|
|
||||||
|
// retrieves or creates a sync.Mutex for a given name
|
||||||
|
func (st *HelmState) getNamedMutex(name string) *sync.Mutex {
|
||||||
|
mu, ok := mutexMap.Load(name)
|
||||||
|
if ok {
|
||||||
|
return mu.(*sync.Mutex)
|
||||||
|
}
|
||||||
|
newMu := &sync.Mutex{}
|
||||||
|
actualMu, _ := mutexMap.LoadOrStore(name, newMu)
|
||||||
|
return actualMu.(*sync.Mutex)
|
||||||
|
}
|
||||||
|
|
||||||
type PrepareChartKey struct {
|
type PrepareChartKey struct {
|
||||||
Namespace, Name, KubeContext string
|
Namespace, Name, KubeContext string
|
||||||
}
|
}
|
||||||
|
|
@ -1347,7 +1363,7 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
chartFetchedByGoGetter := chartPath != chartName
|
chartFetchedByGoGetter := chartPath != chartName
|
||||||
|
|
||||||
if !chartFetchedByGoGetter {
|
if !chartFetchedByGoGetter {
|
||||||
ociChartPath, err := st.getOCIChart(release, dir, helm, opts.OutputDirTemplate)
|
ociChartPath, err := st.getOCIChart(release, dir, helm, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
results <- &chartPrepareResult{err: fmt.Errorf("release %q: %w", release.Name, err)}
|
results <- &chartPrepareResult{err: fmt.Errorf("release %q: %w", release.Name, err)}
|
||||||
|
|
||||||
|
|
@ -1967,7 +1983,7 @@ func (st *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValu
|
||||||
mu := &sync.RWMutex{}
|
mu := &sync.RWMutex{}
|
||||||
installedReleases := map[string]bool{}
|
installedReleases := map[string]bool{}
|
||||||
|
|
||||||
isInstalled := func(r *ReleaseSpec) bool {
|
isInstalled := func(r *ReleaseSpec) (bool, error) {
|
||||||
id := ReleaseToID(r)
|
id := ReleaseToID(r)
|
||||||
|
|
||||||
mu.RLock()
|
mu.RLock()
|
||||||
|
|
@ -1975,19 +1991,19 @@ func (st *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValu
|
||||||
mu.RUnlock()
|
mu.RUnlock()
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
return v
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := st.isReleaseInstalled(st.createHelmContext(r, 0), helm, *r)
|
v, err := st.isReleaseInstalled(st.createHelmContext(r, 0), helm, *r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
st.logger.Warnf("confirming if the release is already installed or not: %v", err)
|
return false, err
|
||||||
} else {
|
|
||||||
mu.Lock()
|
|
||||||
installedReleases[id] = v
|
|
||||||
mu.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return v
|
mu.Lock()
|
||||||
|
installedReleases[id] = v
|
||||||
|
mu.Unlock()
|
||||||
|
|
||||||
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
releases := []*ReleaseSpec{}
|
releases := []*ReleaseSpec{}
|
||||||
|
|
@ -2032,12 +2048,25 @@ func (st *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValu
|
||||||
suppressDiff = true
|
suppressDiff = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if opt.SkipDiffOnInstall && !isInstalled(release) {
|
if opt.SkipDiffOnInstall {
|
||||||
results <- diffPrepareResult{release: release, upgradeDueToSkippedDiff: true, suppressDiff: suppressDiff}
|
installed, err := isInstalled(release)
|
||||||
continue
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
} else if !installed {
|
||||||
|
results <- diffPrepareResult{release: release, upgradeDueToSkippedDiff: true, suppressDiff: suppressDiff}
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
disableValidation := release.DisableValidationOnInstall != nil && *release.DisableValidationOnInstall && !isInstalled(release)
|
var disableValidation bool
|
||||||
|
if release.DisableValidationOnInstall != nil && *release.DisableValidationOnInstall {
|
||||||
|
installed, err := isInstalled(release)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
} else {
|
||||||
|
disableValidation = !installed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO We need a long-term fix for this :)
|
// TODO We need a long-term fix for this :)
|
||||||
// See https://github.com/roboll/helmfile/issues/737
|
// See https://github.com/roboll/helmfile/issues/737
|
||||||
|
|
@ -2352,7 +2381,7 @@ func (st *HelmState) TestReleases(helm helmexec.Interface, cleanup bool, timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
if timeout == EmptyTimeout {
|
if timeout == EmptyTimeout {
|
||||||
flags = append(flags, st.timeoutFlags(&release)...)
|
flags = append(flags, st.timeoutFlags(&release, nil)...)
|
||||||
} else {
|
} else {
|
||||||
duration := strconv.Itoa(timeout)
|
duration := strconv.Itoa(timeout)
|
||||||
duration += "s"
|
duration += "s"
|
||||||
|
|
@ -2779,6 +2808,14 @@ func (st *HelmState) appendKeyringFlags(flags []string, release *ReleaseSpec) []
|
||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// appendEnableDNSFlags append the helm command-line flag for DNS resolution
|
||||||
|
func (st *HelmState) appendEnableDNSFlags(flags []string, release *ReleaseSpec) []string {
|
||||||
|
if release.EnableDNS != nil && *release.EnableDNS || release.EnableDNS == nil && st.HelmDefaults.EnableDNS {
|
||||||
|
flags = append(flags, "--enable-dns")
|
||||||
|
}
|
||||||
|
return flags
|
||||||
|
}
|
||||||
|
|
||||||
func (st *HelmState) kubeConnectionFlags(release *ReleaseSpec) []string {
|
func (st *HelmState) kubeConnectionFlags(release *ReleaseSpec) []string {
|
||||||
flags := []string{}
|
flags := []string{}
|
||||||
if release.KubeContext != "" {
|
if release.KubeContext != "" {
|
||||||
|
|
@ -2832,13 +2869,16 @@ func (st *HelmState) needsInsecureSkipTLSVerify(release *ReleaseSpec, repo *Repo
|
||||||
return relSkipTLSVerify || st.HelmDefaults.InsecureSkipTLSVerify || repoSkipTLSVerify
|
return relSkipTLSVerify || st.HelmDefaults.InsecureSkipTLSVerify || repoSkipTLSVerify
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) timeoutFlags(release *ReleaseSpec) []string {
|
func (st *HelmState) timeoutFlags(release *ReleaseSpec, ops *SyncOpts) []string {
|
||||||
var flags []string
|
var flags []string
|
||||||
|
|
||||||
timeout := st.HelmDefaults.Timeout
|
timeout := st.HelmDefaults.Timeout
|
||||||
if release.Timeout != nil {
|
if release.Timeout != nil {
|
||||||
timeout = *release.Timeout
|
timeout = *release.Timeout
|
||||||
}
|
}
|
||||||
|
if ops != nil && ops.Timeout > 0 {
|
||||||
|
timeout = ops.Timeout
|
||||||
|
}
|
||||||
if timeout != 0 {
|
if timeout != 0 {
|
||||||
duration := strconv.Itoa(timeout)
|
duration := strconv.Itoa(timeout)
|
||||||
duration += "s"
|
duration += "s"
|
||||||
|
|
@ -2851,11 +2891,9 @@ func (st *HelmState) timeoutFlags(release *ReleaseSpec) []string {
|
||||||
func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSpec, workerIndex int, opt *SyncOpts) ([]string, []string, error) {
|
func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSpec, workerIndex int, opt *SyncOpts) ([]string, []string, error) {
|
||||||
var flags []string
|
var flags []string
|
||||||
flags = st.appendChartVersionFlags(flags, release)
|
flags = st.appendChartVersionFlags(flags, release)
|
||||||
if release.EnableDNS != nil && *release.EnableDNS || release.EnableDNS == nil && st.HelmDefaults.EnableDNS {
|
flags = st.appendEnableDNSFlags(flags, release)
|
||||||
flags = append(flags, "--enable-dns")
|
|
||||||
}
|
|
||||||
|
|
||||||
flags = st.appendWaitFlags(flags, helm, release, opt)
|
flags = st.appendWaitFlags(flags, release, opt)
|
||||||
flags = st.appendWaitForJobsFlags(flags, release, opt)
|
flags = st.appendWaitForJobsFlags(flags, release, opt)
|
||||||
|
|
||||||
// non-OCI chart should be verified here
|
// non-OCI chart should be verified here
|
||||||
|
|
@ -2864,7 +2902,7 @@ func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSp
|
||||||
flags = st.appendKeyringFlags(flags, release)
|
flags = st.appendKeyringFlags(flags, release)
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = append(flags, st.timeoutFlags(release)...)
|
flags = append(flags, st.timeoutFlags(release, opt)...)
|
||||||
|
|
||||||
if release.Force != nil && *release.Force || release.Force == nil && st.HelmDefaults.Force {
|
if release.Force != nil && *release.Force || release.Force == nil && st.HelmDefaults.Force {
|
||||||
flags = append(flags, "--force")
|
flags = append(flags, "--force")
|
||||||
|
|
@ -2978,6 +3016,7 @@ func (st *HelmState) flagsForDiff(helm helmexec.Interface, release *ReleaseSpec,
|
||||||
settings := cli.New()
|
settings := cli.New()
|
||||||
var flags []string
|
var flags []string
|
||||||
flags = st.appendChartVersionFlags(flags, release)
|
flags = st.appendChartVersionFlags(flags, release)
|
||||||
|
flags = st.appendEnableDNSFlags(flags, release)
|
||||||
|
|
||||||
disableOpenAPIValidation := false
|
disableOpenAPIValidation := false
|
||||||
if release.DisableOpenAPIValidation != nil {
|
if release.DisableOpenAPIValidation != nil {
|
||||||
|
|
@ -3291,7 +3330,7 @@ func (st *HelmState) ExpandedHelmfiles() ([]SubHelmfileSpec, error) {
|
||||||
}
|
}
|
||||||
if len(matches) == 0 {
|
if len(matches) == 0 {
|
||||||
err := fmt.Errorf("no matches for path: %s", hf.Path)
|
err := fmt.Errorf("no matches for path: %s", hf.Path)
|
||||||
if *st.MissingFileHandler == "Error" {
|
if *st.getMissingFileHandler() == "Error" {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
st.logger.Warnf("no matches for path: %s", hf.Path)
|
st.logger.Warnf("no matches for path: %s", hf.Path)
|
||||||
|
|
@ -3379,6 +3418,19 @@ func (st *HelmState) getReleaseMissingFileHandler(release *ReleaseSpec) *string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getMissingFileHandler returns the first non-nil MissingFileHandler in the following order:
|
||||||
|
// - st.MissingFileHandler
|
||||||
|
// - "Error"
|
||||||
|
func (st *HelmState) getMissingFileHandler() *string {
|
||||||
|
defaultMissingFileHandler := "Error"
|
||||||
|
switch {
|
||||||
|
case st.MissingFileHandler != nil:
|
||||||
|
return st.MissingFileHandler
|
||||||
|
default:
|
||||||
|
return &defaultMissingFileHandler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (st *HelmState) generateTemporaryReleaseValuesFiles(release *ReleaseSpec, values []any) ([]string, error) {
|
func (st *HelmState) generateTemporaryReleaseValuesFiles(release *ReleaseSpec, values []any) ([]string, error) {
|
||||||
generatedFiles := []string{}
|
generatedFiles := []string{}
|
||||||
|
|
||||||
|
|
@ -4091,7 +4143,10 @@ func (st *HelmState) Reverse() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *HelmState) getOCIChart(release *ReleaseSpec, tempDir string, helm helmexec.Interface, outputDirTemplate string) (*string, error) {
|
var downloadedOCICharts = make(map[string]bool)
|
||||||
|
var downloadedOCIMutex sync.RWMutex
|
||||||
|
|
||||||
|
func (st *HelmState) getOCIChart(release *ReleaseSpec, tempDir string, helm helmexec.Interface, opts ChartPrepareOptions) (*string, error) {
|
||||||
qualifiedChartName, chartName, chartVersion, err := st.getOCIQualifiedChartName(release, helm)
|
qualifiedChartName, chartName, chartVersion, err := st.getOCIQualifiedChartName(release, helm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -4101,7 +4156,34 @@ func (st *HelmState) getOCIChart(release *ReleaseSpec, tempDir string, helm helm
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
chartPath, _ := st.getOCIChartPath(tempDir, release, chartName, chartVersion, outputDirTemplate)
|
if opts.OutputDirTemplate == "" {
|
||||||
|
tempDir = remote.CacheDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
chartPath, _ := st.getOCIChartPath(tempDir, release, chartName, chartVersion, opts.OutputDirTemplate)
|
||||||
|
|
||||||
|
mu := st.getNamedMutex(chartPath)
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
|
||||||
|
_, err = os.Stat(tempDir)
|
||||||
|
if err != nil {
|
||||||
|
err = os.MkdirAll(tempDir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadedOCIMutex.RLock()
|
||||||
|
alreadyDownloadedFlag := downloadedOCICharts[chartPath]
|
||||||
|
downloadedOCIMutex.RUnlock()
|
||||||
|
|
||||||
|
if !opts.SkipDeps && !opts.SkipRefresh && !alreadyDownloadedFlag {
|
||||||
|
err = os.RemoveAll(chartPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if st.fs.DirectoryExistsAt(chartPath) {
|
if st.fs.DirectoryExistsAt(chartPath) {
|
||||||
st.logger.Debugf("chart already exists at %s", chartPath)
|
st.logger.Debugf("chart already exists at %s", chartPath)
|
||||||
|
|
@ -4128,6 +4210,10 @@ func (st *HelmState) getOCIChart(release *ReleaseSpec, tempDir string, helm helm
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
downloadedOCIMutex.Lock()
|
||||||
|
downloadedOCICharts[chartPath] = true
|
||||||
|
downloadedOCIMutex.Unlock()
|
||||||
|
|
||||||
chartPath = filepath.Dir(fullChartPath)
|
chartPath = filepath.Dir(fullChartPath)
|
||||||
|
|
||||||
return &chartPath, nil
|
return &chartPath, nil
|
||||||
|
|
@ -4194,15 +4280,15 @@ func (st *HelmState) getOCIChartPath(tempDir string, release *ReleaseSpec, chart
|
||||||
|
|
||||||
pathElems := []string{tempDir}
|
pathElems := []string{tempDir}
|
||||||
|
|
||||||
if release.Namespace != "" {
|
replacer := strings.NewReplacer(
|
||||||
pathElems = append(pathElems, release.Namespace)
|
":", "_",
|
||||||
}
|
"//", "_",
|
||||||
|
".", "_",
|
||||||
if release.KubeContext != "" {
|
"&", "_",
|
||||||
pathElems = append(pathElems, release.KubeContext)
|
)
|
||||||
}
|
qName := strings.Split(replacer.Replace(release.Chart), "/")
|
||||||
|
|
||||||
pathElems = append(pathElems, release.Name, chartName, safeVersionPath(chartVersion))
|
|
||||||
|
|
||||||
|
pathElems = append(pathElems, qName...)
|
||||||
|
pathElems = append(pathElems, safeVersionPath(chartVersion))
|
||||||
return filepath.Join(pathElems...), nil
|
return filepath.Join(pathElems...), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,7 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
|
||||||
version *semver.Version
|
version *semver.Version
|
||||||
defaults HelmSpec
|
defaults HelmSpec
|
||||||
release *ReleaseSpec
|
release *ReleaseSpec
|
||||||
|
syncOpts *SyncOpts
|
||||||
want []string
|
want []string
|
||||||
wantErr string
|
wantErr string
|
||||||
}{
|
}{
|
||||||
|
|
@ -455,6 +456,27 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
|
||||||
"--namespace", "test-namespace",
|
"--namespace", "test-namespace",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "timeout-from-cli-flag",
|
||||||
|
defaults: HelmSpec{
|
||||||
|
Timeout: 123,
|
||||||
|
},
|
||||||
|
release: &ReleaseSpec{
|
||||||
|
Chart: "test/chart",
|
||||||
|
Version: "0.1",
|
||||||
|
Timeout: some(456),
|
||||||
|
Name: "test-charts",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
syncOpts: &SyncOpts{
|
||||||
|
Timeout: 789,
|
||||||
|
},
|
||||||
|
want: []string{
|
||||||
|
"--version", "0.1",
|
||||||
|
"--timeout", "789s",
|
||||||
|
"--namespace", "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "atomic",
|
name: "atomic",
|
||||||
defaults: HelmSpec{
|
defaults: HelmSpec{
|
||||||
|
|
@ -737,7 +759,7 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
|
||||||
Version: tt.version,
|
Version: tt.version,
|
||||||
}
|
}
|
||||||
|
|
||||||
args, _, err := state.flagsForUpgrade(helm, tt.release, 0, nil)
|
args, _, err := state.flagsForUpgrade(helm, tt.release, 0, tt.syncOpts)
|
||||||
if err != nil && tt.wantErr == "" {
|
if err != nil && tt.wantErr == "" {
|
||||||
t.Errorf("unexpected error flagsForUpgrade: %v", err)
|
t.Errorf("unexpected error flagsForUpgrade: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1942,14 +1964,19 @@ func TestHelmState_DiffReleases(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHelmState_DiffFlags(t *testing.T) {
|
func TestHelmState_DiffFlags(t *testing.T) {
|
||||||
|
enable := true
|
||||||
|
disable := false
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
defaults HelmSpec
|
||||||
releases []ReleaseSpec
|
releases []ReleaseSpec
|
||||||
helm *exectest.Helm
|
helm *exectest.Helm
|
||||||
wantDiffFlags []string
|
wantDiffFlags []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "release with api version and kubeversion",
|
name: "release with api version and kubeversion",
|
||||||
|
defaults: HelmSpec{},
|
||||||
releases: []ReleaseSpec{
|
releases: []ReleaseSpec{
|
||||||
{
|
{
|
||||||
Name: "releaseName",
|
Name: "releaseName",
|
||||||
|
|
@ -1962,7 +1989,8 @@ func TestHelmState_DiffFlags(t *testing.T) {
|
||||||
wantDiffFlags: []string{"--api-versions", "helmfile.test/v1", "--api-versions", "helmfile.test/v2", "--kube-version", "1.21"},
|
wantDiffFlags: []string{"--api-versions", "helmfile.test/v1", "--api-versions", "helmfile.test/v2", "--kube-version", "1.21"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "release with kubeversion and plain http which is ignored",
|
name: "release with kubeversion and plain http which is ignored",
|
||||||
|
defaults: HelmSpec{},
|
||||||
releases: []ReleaseSpec{
|
releases: []ReleaseSpec{
|
||||||
{
|
{
|
||||||
Name: "releaseName",
|
Name: "releaseName",
|
||||||
|
|
@ -1974,13 +2002,52 @@ func TestHelmState_DiffFlags(t *testing.T) {
|
||||||
helm: &exectest.Helm{},
|
helm: &exectest.Helm{},
|
||||||
wantDiffFlags: []string{"--kube-version", "1.21"},
|
wantDiffFlags: []string{"--kube-version", "1.21"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "release with enable-dns",
|
||||||
|
defaults: HelmSpec{EnableDNS: false},
|
||||||
|
releases: []ReleaseSpec{
|
||||||
|
{
|
||||||
|
Name: "releaseName",
|
||||||
|
Chart: "foo",
|
||||||
|
EnableDNS: &enable,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
helm: &exectest.Helm{},
|
||||||
|
wantDiffFlags: []string{"--enable-dns"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "release with disable-dns override",
|
||||||
|
defaults: HelmSpec{EnableDNS: true},
|
||||||
|
releases: []ReleaseSpec{
|
||||||
|
{
|
||||||
|
Name: "releaseName",
|
||||||
|
Chart: "foo",
|
||||||
|
EnableDNS: &disable,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
helm: &exectest.Helm{},
|
||||||
|
wantDiffFlags: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "release with enable-dns from default",
|
||||||
|
defaults: HelmSpec{EnableDNS: true},
|
||||||
|
releases: []ReleaseSpec{
|
||||||
|
{
|
||||||
|
Name: "releaseName",
|
||||||
|
Chart: "foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
helm: &exectest.Helm{},
|
||||||
|
wantDiffFlags: []string{"--enable-dns"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for i := range tests {
|
for i := range tests {
|
||||||
tt := tests[i]
|
tt := tests[i]
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
state := &HelmState{
|
state := &HelmState{
|
||||||
ReleaseSetSpec: ReleaseSetSpec{
|
ReleaseSetSpec: ReleaseSetSpec{
|
||||||
Releases: tt.releases,
|
Releases: tt.releases,
|
||||||
|
HelmDefaults: tt.defaults,
|
||||||
},
|
},
|
||||||
logger: logger,
|
logger: logger,
|
||||||
valsRuntime: valsRuntime,
|
valsRuntime: valsRuntime,
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,6 @@ var (
|
||||||
helmShortVersionRegex = regexp.MustCompile(`v\d+\.\d+\.\d+\+[a-z0-9]+`)
|
helmShortVersionRegex = regexp.MustCompile(`v\d+\.\d+\.\d+\+[a-z0-9]+`)
|
||||||
)
|
)
|
||||||
|
|
||||||
type ociChart struct {
|
|
||||||
name string
|
|
||||||
version string
|
|
||||||
digest string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
LocalDockerRegistry struct {
|
LocalDockerRegistry struct {
|
||||||
Enabled bool `yaml:"enabled"`
|
Enabled bool `yaml:"enabled"`
|
||||||
|
|
@ -166,8 +160,6 @@ func testHelmfileTemplateWithBuildCommand(t *testing.T, GoYamlV3 bool) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// ociCharts holds a list of chart name, version and digest distributed by local oci registry.
|
|
||||||
ociCharts := []ociChart{}
|
|
||||||
// If localDockerRegistry.enabled is set to `true`,
|
// If localDockerRegistry.enabled is set to `true`,
|
||||||
// run the docker registry v2 and push the test charts to the registry
|
// run the docker registry v2 and push the test charts to the registry
|
||||||
// so that it can be accessed by helm and helmfile as a oci registry based chart repository.
|
// so that it can be accessed by helm and helmfile as a oci registry based chart repository.
|
||||||
|
|
@ -201,16 +193,9 @@ func testHelmfileTemplateWithBuildCommand(t *testing.T, GoYamlV3 bool) {
|
||||||
if !c.IsDir() {
|
if !c.IsDir() {
|
||||||
t.Fatalf("%s is not a directory", c)
|
t.Fatalf("%s is not a directory", c)
|
||||||
}
|
}
|
||||||
chartName, chartVersion := execHelmShowChart(t, chartPath)
|
|
||||||
tgzFile := execHelmPackage(t, chartPath)
|
tgzFile := execHelmPackage(t, chartPath)
|
||||||
chartDigest, err := execHelmPush(t, tgzFile, fmt.Sprintf("oci://localhost:%d/myrepo", hostPort))
|
_, err := execHelmPush(t, tgzFile, fmt.Sprintf("oci://localhost:%d/myrepo", hostPort))
|
||||||
require.NoError(t, err, "Unable to run helm push to local registry: %v", err)
|
require.NoError(t, err, "Unable to run helm push to local registry: %v", err)
|
||||||
|
|
||||||
ociCharts = append(ociCharts, ociChart{
|
|
||||||
name: chartName,
|
|
||||||
version: chartVersion,
|
|
||||||
digest: chartDigest,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,7 +206,7 @@ func testHelmfileTemplateWithBuildCommand(t *testing.T, GoYamlV3 bool) {
|
||||||
helmfileCacheHome := filepath.Join(tmpDir, "helmfile_cache")
|
helmfileCacheHome := filepath.Join(tmpDir, "helmfile_cache")
|
||||||
// HELM_CONFIG_HOME contains the registry auth file (registry.json) and the index of all the repos added via helm-repo-add (repositories.yaml).
|
// HELM_CONFIG_HOME contains the registry auth file (registry.json) and the index of all the repos added via helm-repo-add (repositories.yaml).
|
||||||
helmConfigHome := filepath.Join(tmpDir, "helm_config")
|
helmConfigHome := filepath.Join(tmpDir, "helm_config")
|
||||||
t.Logf("Using HELM_CACHE_HOME=%s, HELMFILE_CACHE_HOME=%s, HELM_CONFIG_HOME=%s", helmCacheHome, helmfileCacheHome, helmConfigHome)
|
t.Logf("Using HELM_CACHE_HOME=%s, HELMFILE_CACHE_HOME=%s, HELM_CONFIG_HOME=%s, WD=%s", helmCacheHome, helmfileCacheHome, helmConfigHome, wd)
|
||||||
|
|
||||||
inputFile := filepath.Join(testdataDir, name, "input.yaml.gotmpl")
|
inputFile := filepath.Join(testdataDir, name, "input.yaml.gotmpl")
|
||||||
outputFile := ""
|
outputFile := ""
|
||||||
|
|
@ -230,6 +215,7 @@ func testHelmfileTemplateWithBuildCommand(t *testing.T, GoYamlV3 bool) {
|
||||||
} else {
|
} else {
|
||||||
outputFile = filepath.Join(testdataDir, name, "gopkg.in-yaml.v2-output.yaml")
|
outputFile = filepath.Join(testdataDir, name, "gopkg.in-yaml.v2-output.yaml")
|
||||||
}
|
}
|
||||||
|
expectedOutputFile := filepath.Join(testdataDir, name, "output.yaml")
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
@ -262,15 +248,8 @@ func testHelmfileTemplateWithBuildCommand(t *testing.T, GoYamlV3 bool) {
|
||||||
gotStr = chartGitFullPathRegex.ReplaceAllString(gotStr, `chart=$$GoGetterPath`)
|
gotStr = chartGitFullPathRegex.ReplaceAllString(gotStr, `chart=$$GoGetterPath`)
|
||||||
// Replace helm version with $HelmVersion
|
// Replace helm version with $HelmVersion
|
||||||
gotStr = helmShortVersionRegex.ReplaceAllString(gotStr, `$$HelmVersion`)
|
gotStr = helmShortVersionRegex.ReplaceAllString(gotStr, `$$HelmVersion`)
|
||||||
// Replace all occurrences of HELMFILE_CACHE_HOME with /home/runner/.cache/helmfile
|
|
||||||
// for stable test result
|
|
||||||
gotStr = strings.ReplaceAll(gotStr, helmfileCacheHome, "/home/runner/.cache/helmfile")
|
|
||||||
|
|
||||||
// OCI based helm charts are pulled and exported under temporary directory.
|
|
||||||
// We are not sure the exact name of the temporary directory generated by helmfile,
|
|
||||||
// so redact its base directory name with $TMP.
|
|
||||||
if config.LocalDockerRegistry.Enabled {
|
if config.LocalDockerRegistry.Enabled {
|
||||||
var releaseName, chartPath string
|
|
||||||
sc := bufio.NewScanner(strings.NewReader(gotStr))
|
sc := bufio.NewScanner(strings.NewReader(gotStr))
|
||||||
for sc.Scan() {
|
for sc.Scan() {
|
||||||
if !strings.HasPrefix(sc.Text(), "Templating ") {
|
if !strings.HasPrefix(sc.Text(), "Templating ") {
|
||||||
|
|
@ -281,28 +260,20 @@ func testHelmfileTemplateWithBuildCommand(t *testing.T, GoYamlV3 bool) {
|
||||||
if len(releaseChartParts) != 2 {
|
if len(releaseChartParts) != 2 {
|
||||||
t.Fatal("Found unexpected log output of templating oci based helm chart, want=\"Templating release=<release_name>, chart=<chart_name>\"")
|
t.Fatal("Found unexpected log output of templating oci based helm chart, want=\"Templating release=<release_name>, chart=<chart_name>\"")
|
||||||
}
|
}
|
||||||
releaseNamePart, chartPathPart := releaseChartParts[0], releaseChartParts[1]
|
|
||||||
releaseName = strings.TrimPrefix(releaseNamePart, "release=")
|
|
||||||
chartPath = chartPathPart
|
|
||||||
}
|
|
||||||
for _, ociChart := range ociCharts {
|
|
||||||
chartPathWithoutTempDirBase := fmt.Sprintf("/%s/%s/%s/%s", releaseName, ociChart.name, ociChart.version, ociChart.name)
|
|
||||||
var chartPathBase string
|
|
||||||
if strings.HasSuffix(chartPath, chartPathWithoutTempDirBase) {
|
|
||||||
chartPathBase = strings.TrimSuffix(chartPath, chartPathWithoutTempDirBase)
|
|
||||||
}
|
|
||||||
if len(chartPathBase) != 0 {
|
|
||||||
gotStr = strings.ReplaceAll(gotStr, chartPathBase, "chart=$TMP")
|
|
||||||
}
|
|
||||||
gotStr = strings.ReplaceAll(gotStr, fmt.Sprintf("Digest: %s", ociChart.digest), "Digest: $DIGEST")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gotStr = strings.ReplaceAll(gotStr, helmfileCacheHome, "$HELMFILE_CACHE_HOME")
|
||||||
|
gotStr = strings.ReplaceAll(gotStr, wd, "__workingdir__")
|
||||||
|
|
||||||
if stat, _ := os.Stat(outputFile); stat != nil {
|
if stat, _ := os.Stat(outputFile); stat != nil {
|
||||||
want, err := os.ReadFile(outputFile)
|
want, err := os.ReadFile(outputFile)
|
||||||
wantStr := strings.ReplaceAll(string(want), "__workingdir__", wd)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, wantStr, gotStr)
|
require.Equal(t, string(want), gotStr)
|
||||||
|
} else if stat, _ := os.Stat(expectedOutputFile); stat != nil {
|
||||||
|
want, err := os.ReadFile(expectedOutputFile)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, string(want), gotStr)
|
||||||
} else {
|
} else {
|
||||||
// To update the test golden image(output.yaml), just remove it and rerun this test.
|
// To update the test golden image(output.yaml), just remove it and rerun this test.
|
||||||
// We automatically capture the output to `output.yaml` in the test case directory
|
// We automatically capture the output to `output.yaml` in the test case directory
|
||||||
|
|
@ -325,23 +296,6 @@ func execDocker(t *testing.T, args ...string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func execHelmShowChart(t *testing.T, localChart string) (string, string) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
name, version := "", ""
|
|
||||||
out := execHelm(t, "show", "chart", localChart)
|
|
||||||
sc := bufio.NewScanner(strings.NewReader(out))
|
|
||||||
for sc.Scan() {
|
|
||||||
if strings.HasPrefix(sc.Text(), "name:") {
|
|
||||||
name = strings.TrimPrefix(sc.Text(), "name: ")
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(sc.Text(), "version:") {
|
|
||||||
version = strings.TrimPrefix(sc.Text(), "version: ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return name, version
|
|
||||||
}
|
|
||||||
|
|
||||||
func execHelmPackage(t *testing.T, localChart string) string {
|
func execHelmPackage(t *testing.T, localChart string) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Pulling localhost:5001/myrepo/raw:0.1.0
|
Pulling localhost:5001/myrepo/raw:0.1.0
|
||||||
Templating release=foo, chart=$TMP/foo/raw/0.1.0/raw
|
Templating release=foo, chart=$HELMFILE_CACHE_HOME/myrepo/raw/0.1.0/raw
|
||||||
---
|
---
|
||||||
# Source: raw/templates/resources.yaml
|
# Source: raw/templates/resources.yaml
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
|
||||||
6
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_direct/config.yaml
vendored
Normal file
6
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_direct/config.yaml
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
localDockerRegistry:
|
||||||
|
enabled: true
|
||||||
|
port: 5001
|
||||||
|
chartifyTempDir: temp2
|
||||||
|
helmfileArgs:
|
||||||
|
- template
|
||||||
22
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_direct/input.yaml.gotmpl
vendored
Normal file
22
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_direct/input.yaml.gotmpl
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
releases:
|
||||||
|
- name: foo
|
||||||
|
chart: oci://localhost:5001/myrepo/raw
|
||||||
|
version: 0.1.0
|
||||||
|
values: &oci_chart_pull_direct
|
||||||
|
- templates:
|
||||||
|
- |
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{`{{ .Release.Name }}`}}
|
||||||
|
namespace: {{`{{ .Release.Namespace }}`}}
|
||||||
|
annotations:
|
||||||
|
chart-version: {{`{{ .Chart.Version }}`}}
|
||||||
|
data:
|
||||||
|
values: {{`{{ .Release.Name }}`}}
|
||||||
|
|
||||||
|
- name: bar
|
||||||
|
chart: oci://localhost:5001/myrepo/raw
|
||||||
|
version: 0.1.0
|
||||||
|
namespace: ns2
|
||||||
|
values: *oci_chart_pull_direct
|
||||||
27
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_direct/output.yaml
vendored
Normal file
27
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_direct/output.yaml
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
Pulling localhost:5001/myrepo/raw:0.1.0
|
||||||
|
Templating release=foo, chart=$HELMFILE_CACHE_HOME/oci__localhost_5001/myrepo/raw/0.1.0/raw
|
||||||
|
---
|
||||||
|
# Source: raw/templates/resources.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
chart-version: 0.1.0
|
||||||
|
data:
|
||||||
|
values: foo
|
||||||
|
|
||||||
|
Templating release=bar, chart=$HELMFILE_CACHE_HOME/oci__localhost_5001/myrepo/raw/0.1.0/raw
|
||||||
|
---
|
||||||
|
# Source: raw/templates/resources.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: bar
|
||||||
|
namespace: ns2
|
||||||
|
annotations:
|
||||||
|
chart-version: 0.1.0
|
||||||
|
data:
|
||||||
|
values: bar
|
||||||
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Templating two versions of the same chart with only one pulling of each version
|
||||||
|
localDockerRegistry:
|
||||||
|
enabled: true
|
||||||
|
port: 5001
|
||||||
|
chartifyTempDir: temp3
|
||||||
|
helmfileArgs:
|
||||||
|
# Prevent releases from racing and randomizing the log
|
||||||
|
- --concurrency=1
|
||||||
|
- template
|
||||||
43
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_once/input.yaml.gotmpl
vendored
Normal file
43
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_once/input.yaml.gotmpl
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
repositories:
|
||||||
|
- name: myrepo
|
||||||
|
url: localhost:5001/myrepo
|
||||||
|
oci: true
|
||||||
|
|
||||||
|
releases:
|
||||||
|
- name: foo
|
||||||
|
chart: myrepo/raw
|
||||||
|
version: 0.1.0
|
||||||
|
values: &oci_chart_pull_once_values
|
||||||
|
- templates:
|
||||||
|
- |
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{`{{ .Release.Name }}`}}
|
||||||
|
namespace: {{`{{ .Release.Namespace }}`}}
|
||||||
|
annotations:
|
||||||
|
chart-version: {{`{{ .Chart.Version }}`}}
|
||||||
|
data:
|
||||||
|
values: {{`{{ .Release.Name }}`}}
|
||||||
|
|
||||||
|
- name: bar
|
||||||
|
chart: myrepo/raw
|
||||||
|
version: 0.1.0
|
||||||
|
values: *oci_chart_pull_once_values
|
||||||
|
|
||||||
|
- name: release-no-default-ns
|
||||||
|
chart: myrepo/raw
|
||||||
|
version: 0.1.0
|
||||||
|
namespace: no-default
|
||||||
|
values: *oci_chart_pull_once_values
|
||||||
|
|
||||||
|
- name: second-version-of-chart
|
||||||
|
chart: myrepo/raw
|
||||||
|
version: 0.0.1
|
||||||
|
namespace: foobar
|
||||||
|
values: *oci_chart_pull_once_values
|
||||||
|
|
||||||
|
- name: first-release-version-of-chart
|
||||||
|
chart: myrepo/raw
|
||||||
|
version: 0.1.0
|
||||||
|
values: *oci_chart_pull_once_values
|
||||||
67
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_once/output.yaml
vendored
Normal file
67
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_once/output.yaml
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
Pulling localhost:5001/myrepo/raw:0.1.0
|
||||||
|
Pulling localhost:5001/myrepo/raw:0.0.1
|
||||||
|
Templating release=foo, chart=$HELMFILE_CACHE_HOME/myrepo/raw/0.1.0/raw
|
||||||
|
---
|
||||||
|
# Source: raw/templates/resources.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
chart-version: 0.1.0
|
||||||
|
data:
|
||||||
|
values: foo
|
||||||
|
|
||||||
|
Templating release=bar, chart=$HELMFILE_CACHE_HOME/myrepo/raw/0.1.0/raw
|
||||||
|
---
|
||||||
|
# Source: raw/templates/resources.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: bar
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
chart-version: 0.1.0
|
||||||
|
data:
|
||||||
|
values: bar
|
||||||
|
|
||||||
|
Templating release=release-no-default-ns, chart=$HELMFILE_CACHE_HOME/myrepo/raw/0.1.0/raw
|
||||||
|
---
|
||||||
|
# Source: raw/templates/resources.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: release-no-default-ns
|
||||||
|
namespace: no-default
|
||||||
|
annotations:
|
||||||
|
chart-version: 0.1.0
|
||||||
|
data:
|
||||||
|
values: release-no-default-ns
|
||||||
|
|
||||||
|
Templating release=second-version-of-chart, chart=$HELMFILE_CACHE_HOME/myrepo/raw/0.0.1/raw
|
||||||
|
---
|
||||||
|
# Source: raw/templates/resources.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: second-version-of-chart
|
||||||
|
namespace: foobar
|
||||||
|
annotations:
|
||||||
|
chart-version: 0.0.1
|
||||||
|
data:
|
||||||
|
values: second-version-of-chart
|
||||||
|
|
||||||
|
Templating release=first-release-version-of-chart, chart=$HELMFILE_CACHE_HOME/myrepo/raw/0.1.0/raw
|
||||||
|
---
|
||||||
|
# Source: raw/templates/resources.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: first-release-version-of-chart
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
chart-version: 0.1.0
|
||||||
|
data:
|
||||||
|
values: first-release-version-of-chart
|
||||||
|
|
||||||
7
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_once2/config.yaml
vendored
Normal file
7
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_once2/config.yaml
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Templating few releases with the same chart\version and only one pulling
|
||||||
|
localDockerRegistry:
|
||||||
|
enabled: true
|
||||||
|
port: 5001
|
||||||
|
chartifyTempDir: temp3
|
||||||
|
helmfileArgs:
|
||||||
|
- template
|
||||||
23
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_once2/input.yaml.gotmpl
vendored
Normal file
23
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_once2/input.yaml.gotmpl
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
repositories:
|
||||||
|
- name: myrepo
|
||||||
|
url: localhost:5001/myrepo
|
||||||
|
oci: true
|
||||||
|
|
||||||
|
releases:
|
||||||
|
{{- range $i := until 5 }}
|
||||||
|
- name: release-{{ $i }}
|
||||||
|
chart: myrepo/raw
|
||||||
|
version: 0.1.0
|
||||||
|
values:
|
||||||
|
- templates:
|
||||||
|
- |
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{`{{ .Release.Name }}`}}
|
||||||
|
namespace: {{`{{ .Release.Namespace }}`}}
|
||||||
|
annotations:
|
||||||
|
chart-version: {{`{{ .Chart.Version }}`}}
|
||||||
|
data:
|
||||||
|
values: {{`{{ .Release.Name }}`}}
|
||||||
|
{{- end }}
|
||||||
66
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_once2/output.yaml
vendored
Normal file
66
test/e2e/template/helmfile/testdata/snapshot/oci_chart_pull_once2/output.yaml
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
Pulling localhost:5001/myrepo/raw:0.1.0
|
||||||
|
Templating release=release-0, chart=$HELMFILE_CACHE_HOME/myrepo/raw/0.1.0/raw
|
||||||
|
---
|
||||||
|
# Source: raw/templates/resources.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: release-0
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
chart-version: 0.1.0
|
||||||
|
data:
|
||||||
|
values: release-0
|
||||||
|
|
||||||
|
Templating release=release-1, chart=$HELMFILE_CACHE_HOME/myrepo/raw/0.1.0/raw
|
||||||
|
---
|
||||||
|
# Source: raw/templates/resources.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: release-1
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
chart-version: 0.1.0
|
||||||
|
data:
|
||||||
|
values: release-1
|
||||||
|
|
||||||
|
Templating release=release-2, chart=$HELMFILE_CACHE_HOME/myrepo/raw/0.1.0/raw
|
||||||
|
---
|
||||||
|
# Source: raw/templates/resources.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: release-2
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
chart-version: 0.1.0
|
||||||
|
data:
|
||||||
|
values: release-2
|
||||||
|
|
||||||
|
Templating release=release-3, chart=$HELMFILE_CACHE_HOME/myrepo/raw/0.1.0/raw
|
||||||
|
---
|
||||||
|
# Source: raw/templates/resources.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: release-3
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
chart-version: 0.1.0
|
||||||
|
data:
|
||||||
|
values: release-3
|
||||||
|
|
||||||
|
Templating release=release-4, chart=$HELMFILE_CACHE_HOME/myrepo/raw/0.1.0/raw
|
||||||
|
---
|
||||||
|
# Source: raw/templates/resources.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: release-4
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
chart-version: 0.1.0
|
||||||
|
data:
|
||||||
|
values: release-4
|
||||||
|
|
||||||
|
|
@ -27,7 +27,7 @@ export HELM_DATA_HOME="${helm_dir}/data"
|
||||||
export HELM_HOME="${HELM_DATA_HOME}"
|
export HELM_HOME="${HELM_DATA_HOME}"
|
||||||
export HELM_PLUGINS="${HELM_DATA_HOME}/plugins"
|
export HELM_PLUGINS="${HELM_DATA_HOME}/plugins"
|
||||||
export HELM_CONFIG_HOME="${helm_dir}/config"
|
export HELM_CONFIG_HOME="${helm_dir}/config"
|
||||||
HELM_DIFF_VERSION="${HELM_DIFF_VERSION:-3.12.3}"
|
HELM_DIFF_VERSION="${HELM_DIFF_VERSION:-3.12.5}"
|
||||||
HELM_GIT_VERSION="${HELM_GIT_VERSION:-1.3.0}"
|
HELM_GIT_VERSION="${HELM_GIT_VERSION:-1.3.0}"
|
||||||
HELM_SECRETS_VERSION="${HELM_SECRETS_VERSION:-3.15.0}"
|
HELM_SECRETS_VERSION="${HELM_SECRETS_VERSION:-3.15.0}"
|
||||||
export GNUPGHOME="${PWD}/${dir}/.gnupg"
|
export GNUPGHOME="${PWD}/${dir}/.gnupg"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue