Compare commits
No commits in common. "main" and "v0.155.0" have entirely different histories.
|
|
@ -1,234 +0,0 @@
|
|||
# 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.
|
||||
|
|
@ -9,7 +9,3 @@ updates:
|
|||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ exemptLabels:
|
|||
- in progress
|
||||
- pinned
|
||||
- security
|
||||
- bug
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: wontfix
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
HELM_VERSION ?= v3.7.2
|
||||
KUSTOMIZE_VERSION ?= v5.4.3
|
||||
K8S_VERSION ?= v1.32.1
|
||||
MINIKUBE_VERSION ?= v1.31.1
|
||||
SOPS_VERSION ?= v3.9.3
|
||||
KUSTOMIZE_VERSION ?= v4.5.7
|
||||
K8S_VERSION ?= v1.13.12
|
||||
MINIKUBE_VERSION ?= v0.30.0
|
||||
SOPS_VERSION ?= v3.6.1
|
||||
|
||||
# ---
|
||||
CHANGE_MINIKUBE_NONE_USER ?= true
|
||||
|
|
@ -57,12 +57,12 @@ minikube:
|
|||
vault:
|
||||
docker kill $$(docker ps -a --filter "name=vault" -q) || true
|
||||
docker run -d -p8200:8200 --rm --name vault vault:1.2.0 server -dev -dev-root-token-id=toor
|
||||
docker run --rm --network="host" --cap-add IPC_LOCK -e VAULT_ADDR=$$VAULT_ADDR -e VAULT_TOKEN=$$VAULT_TOKEN vault:1.2.0 secrets enable -path=sops transit
|
||||
docker run --rm --network="host" --cap-add IPC_LOCK -e VAULT_ADDR=$$VAULT_ADDR -e VAULT_TOKEN=$$VAULT_TOKEN vault:1.2.0 write sops/keys/key type=rsa-4096
|
||||
docker run --rm --network="host" -e VAULT_ADDR=$$VAULT_ADDR -e VAULT_TOKEN=$$VAULT_TOKEN vault:1.2.0 secrets enable -path=sops transit
|
||||
docker run --rm --network="host" -e VAULT_ADDR=$$VAULT_ADDR -e VAULT_TOKEN=$$VAULT_TOKEN vault:1.2.0 write sops/keys/key type=rsa-4096
|
||||
.PHONY: vault
|
||||
|
||||
sops:
|
||||
curl -sSLo $(tmp)/sops "https://github.com/getsops/sops/releases/download/${SOPS_VERSION}/sops-${SOPS_VERSION}.linux.amd64"
|
||||
curl -sSLo $(tmp)/sops "https://github.com/mozilla/sops/releases/download/${SOPS_VERSION}/sops-${SOPS_VERSION}.linux"
|
||||
chmod +x $(tmp)/sops
|
||||
sudo mv ${tmp}/sops /usr/local/bin/
|
||||
.PHONY: sops
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
name: Cleanup cache
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
|
||||
jobs:
|
||||
cleanup-cache:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
|
||||
echo "Fetching list of cache keys"
|
||||
cacheKeys=$(gh actions-cache list -R $GITHUB_REPOSITORY -B $BRANCH | cut -f 1 )
|
||||
|
||||
echo "Deleting caches..."
|
||||
for cacheKey in $cacheKeys; do
|
||||
gh actions-cache delete $cacheKey -R $GITHUB_REPOSITORY -B $BRANCH --confirm
|
||||
done
|
||||
shell: bash
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
|
|
@ -9,134 +9,163 @@ on:
|
|||
paths-ignore: [ '**.md', '**/docs/**' ]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache: false
|
||||
- uses: golangci/golangci-lint-action@v8
|
||||
with:
|
||||
version: v2.1.6
|
||||
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
- name: Build
|
||||
run: make build build-test-tools
|
||||
- name: Test
|
||||
run: make check test
|
||||
- name: Archive built binaries
|
||||
run: tar -cvf built-binaries.tar helmfile diff-yamls dyff
|
||||
- uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: built-binaries-${{ github.run_id }}
|
||||
path: built-binaries.tar
|
||||
retention-days: 1
|
||||
- name: Display built binaries
|
||||
run: ls -l helmfile diff-yamls dyff
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Cache libraries
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-go
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.20'
|
||||
- name: Env
|
||||
run: go env
|
||||
- name: Build
|
||||
run: make build build-test-tools
|
||||
- name: Test
|
||||
run: make check test
|
||||
|
||||
- name: Prepare tar to upload built binaries
|
||||
run: tar -cvf built-binaries.tar helmfile diff-yamls dyff
|
||||
- name: Upload built binaries
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: built-binaries-${{ github.run_id }}
|
||||
path: built-binaries.tar
|
||||
retention-days: 1
|
||||
- name: Display built binaries
|
||||
run: ls -l helmfile diff-yamls dyff
|
||||
|
||||
integration_tests:
|
||||
needs: tests
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
# 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.
|
||||
# See https://github.com/helmfile/helmfile/pull/286#issuecomment-1250161182 for more context.
|
||||
- helm-version: v3.18.6
|
||||
kustomize-version: v5.2.1
|
||||
plugin-secrets-version: 4.6.5
|
||||
plugin-diff-version: 3.11.0
|
||||
extra-helmfile-flags: ''
|
||||
- helm-version: v3.18.6
|
||||
kustomize-version: v5.4.3
|
||||
# We assume that the helm-secrets plugin is supposed to
|
||||
# work with the two most recent helm minor versions.
|
||||
# Once it turned out to be not practically true,
|
||||
# we will mark this combination as failable,
|
||||
# and instruct users to upgrade helm and helm-secrets at once.
|
||||
plugin-secrets-version: 4.6.5
|
||||
plugin-diff-version: 3.12.5
|
||||
extra-helmfile-flags: ''
|
||||
- helm-version: v3.19.0
|
||||
kustomize-version: v5.2.1
|
||||
plugin-secrets-version: 4.6.5
|
||||
plugin-diff-version: 3.11.0
|
||||
extra-helmfile-flags: ''
|
||||
- helm-version: v3.19.0
|
||||
kustomize-version: v5.4.3
|
||||
plugin-secrets-version: 4.6.5
|
||||
plugin-diff-version: 3.12.5
|
||||
extra-helmfile-flags: ''
|
||||
# In case you need to test some optional helmfile features,
|
||||
# enable it via extra-helmfile-flags below.
|
||||
- helm-version: v3.19.0
|
||||
kustomize-version: v5.4.3
|
||||
plugin-secrets-version: 4.6.5
|
||||
plugin-diff-version: 3.12.5
|
||||
extra-helmfile-flags: '--enable-live-output'
|
||||
include:
|
||||
# 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.
|
||||
# See https://github.com/helmfile/helmfile/pull/286#issuecomment-1250161182 for more context.
|
||||
- helm-version: v3.11.3
|
||||
kustomize-version: v4.4.1
|
||||
plugin-secrets-version: 3.15.0
|
||||
plugin-diff-version: 3.7.0
|
||||
extra-helmfile-flags:
|
||||
v1mode:
|
||||
- helm-version: v3.11.3
|
||||
kustomize-version: v4.5.7
|
||||
# We assume that the helm-secrets plugin is supposed to
|
||||
# work with the two most recent helm minor versions.
|
||||
# Once it turned out to be not practically true,
|
||||
# we will mark this combination as failable,
|
||||
# and instruct users to upgrade helm and helm-secrets at once.
|
||||
plugin-secrets-version: 4.0.0
|
||||
plugin-diff-version: 3.8.1
|
||||
extra-helmfile-flags:
|
||||
v1mode:
|
||||
- helm-version: v3.12.1
|
||||
kustomize-version: v4.4.1
|
||||
plugin-secrets-version: 3.15.0
|
||||
plugin-diff-version: 3.7.0
|
||||
extra-helmfile-flags:
|
||||
v1mode:
|
||||
- helm-version: v3.12.1
|
||||
kustomize-version: v4.5.7
|
||||
plugin-secrets-version: 4.0.0
|
||||
plugin-diff-version: 3.8.1
|
||||
extra-helmfile-flags:
|
||||
v1mode:
|
||||
# Helmfile v1
|
||||
- helm-version: v3.12.1
|
||||
kustomize-version: v4.5.7
|
||||
plugin-secrets-version: 4.0.0
|
||||
plugin-diff-version: 3.8.1
|
||||
extra-helmfile-flags:
|
||||
v1mode: "true"
|
||||
# In case you need to test some optional helmfile features,
|
||||
# enable it via extra-helmfile-flags below.
|
||||
- helm-version: v3.12.1
|
||||
kustomize-version: v4.5.7
|
||||
plugin-secrets-version: 4.0.0
|
||||
plugin-diff-version: 3.8.1
|
||||
extra-helmfile-flags: "--enable-live-output"
|
||||
v1mode:
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
- uses: actions/checkout@v2
|
||||
- name: Cache libraries
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-go
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.20'
|
||||
- name: Env
|
||||
run: go env
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: built-binaries-${{ github.run_id }}
|
||||
- name: install semver
|
||||
run: go install github.com/ffurrer2/semver/v2/cmd/semver@latest
|
||||
- name: Extract tar to get built binaries
|
||||
run: tar -xvf built-binaries.tar
|
||||
- name: Display built binaries
|
||||
run: ls -l helmfile diff-yamls dyff
|
||||
|
||||
- name: Install test dependencies
|
||||
env:
|
||||
HELM_VERSION: ${{ matrix.helm-version }}
|
||||
KUSTOMIZE_VERSION: ${{ matrix.kustomize-version }}
|
||||
run: make -C .github/workflows helm vault sops kustomize
|
||||
- name: Start minikube
|
||||
uses: medyagh/setup-minikube@latest
|
||||
with:
|
||||
kubernetes-version: v1.33.1
|
||||
- name: Execute integration tests
|
||||
run: make integration
|
||||
env:
|
||||
HELM_SECRETS_VERSION: ${{ matrix.plugin-secrets-version }}
|
||||
HELM_DIFF_VERSION: ${{ matrix.plugin-diff-version }}
|
||||
HELMFILE_HELM3: 1
|
||||
TERM: xterm
|
||||
EXTRA_HELMFILE_FLAGS: ${{ matrix.extra-helmfile-flags }}
|
||||
- name: Download built binaries
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: built-binaries-${{ github.run_id }}
|
||||
- name: Extract tar to get built binaries
|
||||
run: tar -xvf built-binaries.tar
|
||||
- name: Display built binaries
|
||||
run: ls -l helmfile diff-yamls dyff
|
||||
|
||||
- name: Install test dependencies
|
||||
env:
|
||||
HELM_VERSION: ${{ matrix.helm-version }}
|
||||
KUSTOMIZE_VERSION: ${{ matrix.kustomize-version }}
|
||||
run: make -C .github/workflows helm vault sops kustomize
|
||||
- name: Start minikube
|
||||
uses: medyagh/setup-minikube@master
|
||||
- name: Execute integration tests
|
||||
env:
|
||||
HELM_SECRETS_VERSION: ${{ matrix.plugin-secrets-version }}
|
||||
HELM_DIFF_VERSION: ${{ matrix.plugin-diff-version }}
|
||||
HELMFILE_HELM3: 1
|
||||
TERM: xterm
|
||||
EXTRA_HELMFILE_FLAGS: ${{ matrix.extra-helmfile-flags }}
|
||||
HELMFILE_V1MODE: ${{ matrix.v1mode }}
|
||||
run: make integration
|
||||
e2e_tests:
|
||||
needs: tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/download-artifact@v6
|
||||
- name: Install package
|
||||
run: |
|
||||
sudo apt-get -y install expect
|
||||
- name: Download built binaries
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: built-binaries-${{ github.run_id }}
|
||||
- name: Extract tar to get built binaries
|
||||
run: tar -xvf built-binaries.tar
|
||||
- name: Display built binaries
|
||||
run: ls -l helmfile diff-yamls dyff
|
||||
- name: Install package
|
||||
run: sudo apt-get -y install expect
|
||||
- name: Run helmfile init
|
||||
run: bash test/e2e/helmfile-init/init_linux.sh
|
||||
env:
|
||||
TERM: xterm
|
||||
run: bash test/e2e/helmfile-init/init_linux.sh
|
||||
|
|
|
|||
|
|
@ -39,21 +39,21 @@ jobs:
|
|||
suffix: "-ubuntu"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository }}${{ matrix.image.suffix }}
|
||||
flavor: latest=false
|
||||
|
|
@ -64,14 +64,14 @@ jobs:
|
|||
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build / Push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.image.dockerfile }}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
name: Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths-ignore: [ '**.md', '**/docs/**' ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
paths-ignore: [ '**.md', '**/docs/**' ]
|
||||
|
||||
env:
|
||||
GO_VERSION: 1.20
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.20'
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Golangci lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: v1.51.0
|
||||
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
lock:
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- uses: 'dessant/lock-threads@v5'
|
||||
- uses: 'dessant/lock-threads@v2'
|
||||
with:
|
||||
github-token: '${{ github.token }}'
|
||||
issue-lock-inactive-days: 1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
name: Publish v0.x Binaries
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "!*"
|
||||
tags:
|
||||
- "v0*"
|
||||
|
||||
jobs:
|
||||
goreleaser:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
-
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.20'
|
||||
-
|
||||
name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v1
|
||||
with:
|
||||
version: latest
|
||||
args: release --rm-dist
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
name: Publish v1.x Binaries
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "!*"
|
||||
tags:
|
||||
- "v1*"
|
||||
|
||||
env:
|
||||
# This is referenced from .goreleaser.yml
|
||||
HELMFILE_V1MODE: "true"
|
||||
|
||||
jobs:
|
||||
goreleaser:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
-
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.20'
|
||||
-
|
||||
name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v1
|
||||
with:
|
||||
version: latest
|
||||
args: release --rm-dist
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
name: GoReleaser
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v0*'
|
||||
- 'v1*'
|
||||
branches:
|
||||
- 'main'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SNAPSHOT: ${{ !startsWith(github.ref, 'refs/tags/v') && '--snapshot' || '' }}
|
||||
|
||||
jobs:
|
||||
goreleaser:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
- name: check disk usage
|
||||
run: df -h
|
||||
- name: cleanup disk
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf /usr/local/share/boost
|
||||
sudo rm -fr /usr/local/lib/android
|
||||
sudo rm -fr /opt/hostedtoolcache/CodeQL
|
||||
sudo docker image prune --all --force
|
||||
sudo docker builder prune -a
|
||||
- name: check disk usage
|
||||
run: df -h
|
||||
- uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
version: latest
|
||||
args: release --clean ${{ env.SNAPSHOT }}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
name: Test Binary Builds
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
goreleaser:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
-
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.20'
|
||||
-
|
||||
name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v1
|
||||
with:
|
||||
version: latest
|
||||
args: release --rm-dist --snapshot
|
||||
|
|
@ -11,4 +11,3 @@ vendor/
|
|||
*.lock
|
||||
test/integration/.gnupg/
|
||||
.vscode/launch.json
|
||||
cover.out
|
||||
|
|
|
|||
464
.golangci.yaml
464
.golangci.yaml
|
|
@ -1,146 +1,360 @@
|
|||
version: "2"
|
||||
# This file contains all available configuration options
|
||||
# with their default values.
|
||||
|
||||
# options for analysis running
|
||||
run:
|
||||
# default concurrency is a available CPU number
|
||||
# concurrency: 4
|
||||
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
timeout: 30m
|
||||
|
||||
# exit code when at least one issue was found, default is 1
|
||||
issues-exit-code: 1
|
||||
|
||||
# include test files or not, default is true
|
||||
tests: true
|
||||
|
||||
# list of build tags, all linters use it. Default is empty list.
|
||||
# build-tags:
|
||||
# - mytag
|
||||
|
||||
# which dirs to skip: issues from them won't be reported;
|
||||
# can use regexp here: generated.*, regexp is applied on full path;
|
||||
# default value is empty list, but default dirs are skipped independently
|
||||
# from this option's value (see skip-dirs-use-default).
|
||||
# skip-dirs:
|
||||
# - src/external_libs
|
||||
# - autogenerated_by_my_lib
|
||||
|
||||
# default is true. Enables skipping of directories:
|
||||
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
|
||||
skip-dirs-use-default: true
|
||||
|
||||
# which files to skip: they will be analyzed, but issues from them
|
||||
# won't be reported. Default value is empty list, but there is
|
||||
# no need to include all autogenerated files, we confidently recognize
|
||||
# autogenerated files. If it's not please let us know.
|
||||
# skip-files:
|
||||
# - ".*\\.my\\.go$"
|
||||
# - lib/bad.go
|
||||
|
||||
# by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
|
||||
# If invoked with -mod=readonly, the go command is disallowed from the implicit
|
||||
# automatic updating of go.mod described above. Instead, it fails when any changes
|
||||
# to go.mod are needed. This setting is most useful to check that go.mod does
|
||||
# not need updates, such as in a continuous integration and testing system.
|
||||
# If invoked with -mod=vendor, the go command assumes that the vendor
|
||||
# directory holds the correct copies of dependencies and ignores
|
||||
# the dependency descriptions in go.mod.
|
||||
# modules-download-mode: readonly|release|vendor
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
formats:
|
||||
text:
|
||||
path: stdout
|
||||
print-linter-name: true
|
||||
print-issued-lines: true
|
||||
colors: false
|
||||
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
|
||||
format: line-number
|
||||
|
||||
# print lines of code with issue, default is true
|
||||
print-issued-lines: true
|
||||
|
||||
# print linter name in the end of issue text, default is true
|
||||
print-linter-name: true
|
||||
|
||||
# all available settings of specific linters
|
||||
linters-settings:
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
- default
|
||||
- prefix(github.com/helmfile/helmfile)
|
||||
|
||||
errcheck:
|
||||
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-type-assertions: false
|
||||
|
||||
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-blank: false
|
||||
|
||||
# [deprecated] comma-separated list of pairs of the form pkg:regex
|
||||
# the regex is used to ignore names within pkg. (default "fmt:.*").
|
||||
# see https://github.com/kisielk/errcheck#the-deprecated-method for details
|
||||
# ignore: fmt:.*
|
||||
|
||||
# path to a file containing a list of functions to exclude from checking
|
||||
# see https://github.com/kisielk/errcheck#excluding-functions for details
|
||||
# exclude: /path/to/file.txt
|
||||
|
||||
# Disable error checking, as errorcheck detects more errors and is more configurable.
|
||||
gosec:
|
||||
exclude:
|
||||
- "G104"
|
||||
|
||||
govet:
|
||||
# report about shadowed variables
|
||||
check-shadowing: false
|
||||
|
||||
# settings per analyzer
|
||||
settings:
|
||||
printf: # analyzer name, run `go tool vet help` to see all analyzers
|
||||
funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||
|
||||
# enable or disable analyzers by name
|
||||
# enable:
|
||||
# - atomicalign
|
||||
# enable-all: false
|
||||
# disable:
|
||||
# - shadow
|
||||
# disable-all: false
|
||||
golint:
|
||||
# minimal confidence for issues, default is 0.8
|
||||
min-confidence: 0.8
|
||||
gofmt:
|
||||
# simplify code: gofmt with `-s` option, true by default
|
||||
simplify: true
|
||||
goimports:
|
||||
# put imports beginning with prefix after 3rd-party packages;
|
||||
# it's a comma-separated list of prefixes
|
||||
# local-prefixes: github.com/org/project
|
||||
gocyclo:
|
||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||
min-complexity: 30
|
||||
gocognit:
|
||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||
min-complexity: 100
|
||||
maligned:
|
||||
# print struct with more effective memory layout or not, false by default
|
||||
suggest-new: true
|
||||
dupl:
|
||||
# tokens count to trigger issue, 150 by default
|
||||
threshold: 100
|
||||
goconst:
|
||||
# minimal length of string constant, 3 by default
|
||||
min-len: 3
|
||||
# minimal occurrences count to trigger, 3 by default
|
||||
min-occurrences: 8
|
||||
# depguard:
|
||||
# list-type: blacklist
|
||||
# include-go-root: false
|
||||
# packages:
|
||||
# - github.com/sirupsen/logrus
|
||||
# packages-with-error-messages:
|
||||
# # specify an error message to output when a blacklisted package is used
|
||||
# github.com/sirupsen/logrus: "logging is allowed only by logutils.Log"
|
||||
misspell:
|
||||
# Correct spellings using locale preferences for US or UK.
|
||||
# Default is to use a neutral variety of English.
|
||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||
locale: US
|
||||
ignore-words:
|
||||
- GitLab
|
||||
lll:
|
||||
# max line length, lines longer will be reported. Default is 120.
|
||||
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
|
||||
line-length: 120
|
||||
# tab width in spaces. Default to 1.
|
||||
tab-width: 1
|
||||
unused:
|
||||
# treat code as a program (not a library) and report unused exported identifiers; default is false.
|
||||
# XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
|
||||
# if it's called for subdir of a project it can't find funcs usages. All text editor integrations
|
||||
# with golangci-lint call it on a directory with the changed file.
|
||||
check-exported: false
|
||||
unparam:
|
||||
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
|
||||
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
|
||||
# if it's called for subdir of a project it can't find external interfaces. All text editor integrations
|
||||
# with golangci-lint call it on a directory with the changed file.
|
||||
check-exported: false
|
||||
nakedret:
|
||||
# make an issue if func has more lines of code than this setting and it has naked returns; default is 30
|
||||
max-func-lines: 30
|
||||
prealloc:
|
||||
# XXX: we don't recommend using this linter before doing performance profiling.
|
||||
# For most programs usage of prealloc will be a premature optimization.
|
||||
|
||||
# Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.
|
||||
# True by default.
|
||||
simple: true
|
||||
range-loops: true # Report preallocation suggestions on range loops, true by default
|
||||
for-loops: false # Report preallocation suggestions on for loops, false by default
|
||||
gocritic:
|
||||
# Which checks should be enabled; can't be combined with 'disabled-checks';
|
||||
# See https://go-critic.github.io/overview#checks-overview
|
||||
# To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run`
|
||||
# By default list of stable checks is used.
|
||||
# enabled-checks:
|
||||
# - rangeValCopy
|
||||
|
||||
# Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty
|
||||
# disabled-checks:
|
||||
# - regexpMust
|
||||
|
||||
# Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.
|
||||
# Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags".
|
||||
# enabled-tags:
|
||||
# - performance
|
||||
|
||||
settings: # settings passed to gocritic
|
||||
captLocal: # must be valid enabled check name
|
||||
paramsOnly: true
|
||||
# rangeValCopy:
|
||||
# sizeThreshold: 32
|
||||
godox:
|
||||
# report any comments starting with keywords, this is useful for TODO or FIXME comments that
|
||||
# might be left in the code accidentally and should be resolved before merging
|
||||
keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting
|
||||
- TODO
|
||||
- BUG
|
||||
- FIXME
|
||||
- NOTE
|
||||
- OPTIMIZE # marks code that should be optimized before merging
|
||||
- HACK # marks hack-arounds that should be removed before merging
|
||||
dogsled:
|
||||
# checks assignments with too many blank identifiers; default is 2
|
||||
max-blank-identifiers: 2
|
||||
|
||||
whitespace:
|
||||
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
|
||||
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
|
||||
wsl:
|
||||
# If true append is only allowed to be cuddled if appending value is
|
||||
# matching variables, fields or types on line above. Default is true.
|
||||
strict-append: true
|
||||
# Allow calls and assignments to be cuddled as long as the lines have any
|
||||
# matching variables, fields or types. Default is true.
|
||||
allow-assign-and-call: true
|
||||
# Allow multiline assignments to be cuddled. Default is true.
|
||||
allow-multiline-assign: true
|
||||
# Allow declarations (var) to be cuddled.
|
||||
allow-cuddle-declarations: false
|
||||
# Allow trailing comments in ending of blocks
|
||||
allow-trailing-comment: false
|
||||
# Force newlines in end of case at this limit (0 = never).
|
||||
force-case-trailing-whitespace: 0
|
||||
revive:
|
||||
ignore-generated-header: true
|
||||
severity: warning
|
||||
funlen:
|
||||
# Checks the number of lines in a function.
|
||||
# If lower than 0, disable the check.
|
||||
# Default: 60
|
||||
lines: 280
|
||||
# Checks the number of statements in a function.
|
||||
# If lower than 0, disable the check.
|
||||
# Default: 40
|
||||
statements: 140
|
||||
|
||||
linters:
|
||||
default: none
|
||||
# please, do not use `enable-all`: it's deprecated and will be removed soon.
|
||||
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||
disable-all: true
|
||||
enable:
|
||||
- bodyclose
|
||||
- copyloopvar
|
||||
- depguard
|
||||
- usestdlibvars
|
||||
- reassign
|
||||
- errcheck
|
||||
- funlen
|
||||
- gocognit
|
||||
- goconst
|
||||
- gofmt
|
||||
- goimports
|
||||
- revive
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
- nakedret
|
||||
- reassign
|
||||
- revive
|
||||
- exportloopref
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- usestdlibvars
|
||||
- whitespace
|
||||
settings:
|
||||
staticcheck:
|
||||
checks: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-ST1005", "-QF1001", "-QF1008"]
|
||||
|
||||
dogsled:
|
||||
max-blank-identifiers: 2
|
||||
dupl:
|
||||
threshold: 100
|
||||
errcheck:
|
||||
check-type-assertions: false
|
||||
check-blank: false
|
||||
funlen:
|
||||
lines: 280
|
||||
statements: 140
|
||||
gocognit:
|
||||
min-complexity: 110
|
||||
goconst:
|
||||
min-len: 3
|
||||
min-occurrences: 8
|
||||
gocritic:
|
||||
settings:
|
||||
captLocal:
|
||||
paramsOnly: true
|
||||
gocyclo:
|
||||
min-complexity: 30
|
||||
godox:
|
||||
keywords:
|
||||
- TODO
|
||||
- BUG
|
||||
- FIXME
|
||||
- NOTE
|
||||
- OPTIMIZE
|
||||
- HACK
|
||||
gosec:
|
||||
excludes:
|
||||
- G104
|
||||
govet:
|
||||
disable:
|
||||
- shadow
|
||||
settings:
|
||||
printf:
|
||||
funcs:
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||
lll:
|
||||
line-length: 120
|
||||
tab-width: 1
|
||||
misspell:
|
||||
locale: US
|
||||
ignore-rules:
|
||||
- GitLab
|
||||
nakedret:
|
||||
max-func-lines: 50
|
||||
prealloc:
|
||||
simple: true
|
||||
range-loops: true
|
||||
for-loops: false
|
||||
revive:
|
||||
confidence: 0.8
|
||||
severity: warning
|
||||
unparam:
|
||||
check-exported: false
|
||||
whitespace:
|
||||
multi-if: false
|
||||
multi-func: false
|
||||
wsl:
|
||||
strict-append: true
|
||||
allow-assign-and-call: true
|
||||
allow-multiline-assign: true
|
||||
force-case-trailing-whitespace: 0
|
||||
allow-trailing-comment: false
|
||||
allow-cuddle-declarations: false
|
||||
exclusions:
|
||||
generated: lax
|
||||
rules:
|
||||
- linters:
|
||||
- dupl
|
||||
- errcheck
|
||||
- funlen
|
||||
- gocyclo
|
||||
- gosec
|
||||
path: _test\.go
|
||||
- linters:
|
||||
- lll
|
||||
source: '^//go:generate '
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
new: false
|
||||
formatters:
|
||||
enable:
|
||||
- gci
|
||||
- gofmt
|
||||
- goimports
|
||||
settings:
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
- default
|
||||
- prefix(github.com/helmfile/helmfile)
|
||||
gofmt:
|
||||
simplify: true
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
# - gocritic
|
||||
# - godox
|
||||
# - gosec
|
||||
# - interfacer
|
||||
# - stylecheck
|
||||
# - dogsled
|
||||
# - dupl
|
||||
# don't enable:
|
||||
# - deadcode
|
||||
# - gochecknoglobals
|
||||
# - gochecknoinits
|
||||
# - gocyclo
|
||||
# - lll
|
||||
# - maligned
|
||||
# - prealloc
|
||||
# - varcheck
|
||||
|
||||
issues:
|
||||
# List of regexps of issue texts to exclude, empty list by default.
|
||||
# But independently from this option we use default exclude patterns,
|
||||
# it can be disabled by `exclude-use-default: false`. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`
|
||||
# exclude:
|
||||
# - abcdef
|
||||
|
||||
# Excluding configuration per-path, per-linter, per-text and per-source
|
||||
exclude-rules:
|
||||
# Exclude some linters from running on tests files.
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gocyclo
|
||||
- errcheck
|
||||
- dupl
|
||||
- gosec
|
||||
- funlen
|
||||
|
||||
# Exclude known linters from partially hard-vendored code,
|
||||
# which is impossible to exclude via "nolint" comments.
|
||||
# - path: internal/hmac/
|
||||
# text: "weak cryptographic primitive"
|
||||
# linters:
|
||||
# - gosec
|
||||
|
||||
# Exclude some staticcheck messages
|
||||
# - linters:
|
||||
# - staticcheck
|
||||
# text: "SA9003:"
|
||||
|
||||
# Exclude lll issues for long lines with go:generate
|
||||
- linters:
|
||||
- lll
|
||||
source: "^//go:generate "
|
||||
|
||||
# Independently from option `exclude` we use default exclude patterns,
|
||||
# it can be disabled by this option. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`.
|
||||
# Default value for this option is true.
|
||||
exclude-use-default: false
|
||||
|
||||
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
||||
max-issues-per-linter: 0
|
||||
|
||||
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
|
||||
max-same-issues: 0
|
||||
|
||||
# Show only new issues: if there are unstaged changes or untracked files,
|
||||
# only those changes are analyzed, else only changes in HEAD~ are analyzed.
|
||||
# It's a super-useful option for integration of golangci-lint into existing
|
||||
# large codebase. It's not practical to fix all existing issues at the moment
|
||||
# of integration: much better don't allow issues in new code.
|
||||
# Default is false.
|
||||
new: false
|
||||
|
||||
# Show only new issues created after git revision `REV`
|
||||
# This should be passed as flag during individual CI jobs.
|
||||
# new-from-rev: REV
|
||||
|
||||
# Show only new issues created in git patch with set file path.
|
||||
# new-from-patch: path/to/patch/file
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
version: 2
|
||||
project_name: helmfile
|
||||
env:
|
||||
# We default to non-v1 mode (=helmfile v0.x behavior) when HELMFILE_V1MODE is not set
|
||||
- HELMFILE_V1MODE={{ if index .Env "HELMFILE_V1MODE" }}{{ .Env.HELMFILE_V1MODE }}{{ else }}false{{ end }}
|
||||
builds:
|
||||
- id: helmfile
|
||||
main: .
|
||||
|
|
@ -12,6 +14,7 @@ builds:
|
|||
- -X go.szostok.io/version.commit={{.FullCommit}}
|
||||
- -X go.szostok.io/version.commitDate={{.CommitDate}}
|
||||
- -X go.szostok.io/version.dirtyBuild=false
|
||||
- -X github.com/helmfile/helmfile/pkg/runtime.v1Mode={{.Env.HELMFILE_V1MODE}}
|
||||
goos:
|
||||
- darwin
|
||||
- linux
|
||||
|
|
@ -20,26 +23,5 @@ builds:
|
|||
- amd64
|
||||
- arm64
|
||||
- "386"
|
||||
archives:
|
||||
- id: helmfile
|
||||
ids:
|
||||
- helmfile
|
||||
builds_info:
|
||||
group: root
|
||||
owner: root
|
||||
mode: 0644
|
||||
changelog:
|
||||
use: github
|
||||
sort: asc
|
||||
groups:
|
||||
- title: Features
|
||||
regexp: '^.*[Ff]eat[(\\w)]*:+.*$'
|
||||
order: 0
|
||||
- title: "Fixes"
|
||||
regexp: '^.*fix[(\\w)]*.*$'
|
||||
order: 1
|
||||
- title: "Dependencies"
|
||||
regexp: '^.*(deps|bump)[(\\w)]*.*$'
|
||||
order: 2
|
||||
- title: Others
|
||||
order: 999
|
||||
use: github-native
|
||||
|
|
|
|||
|
|
@ -4,11 +4,6 @@ mkdocs:
|
|||
configuration: mkdocs.yml
|
||||
fail_on_warning: false
|
||||
|
||||
build:
|
||||
os: ubuntu-24.04
|
||||
tools:
|
||||
python: "3.12"
|
||||
|
||||
python:
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
# Helmfile Maintainers
|
||||
* @mumoshu @itscaro @yxxhero @xiaomudk @zhaque44
|
||||
* @mumoshu @itscaro @yxxhero @xiaomudk
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ By contributing to `helmfile`, you accept and agree to the following DCO and lic
|
|||
conditions for your present and future Contributions submitted to the `helmfile` project.
|
||||
|
||||
[DCO](https://developercertificate.org/)
|
||||
[License](https://github.com/helmfile/helmfile/blob/main/LICENSE)
|
||||
[License](https://github.com/helmfile/helmfile/blob/master/LICENSE)
|
||||
|
||||
# Developing helmfile
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ $ go get github.com/helmfile/helmfile
|
|||
|
||||
$ cd $GOPATH/src/github.com/helmfile/helmfile
|
||||
|
||||
$ git checkout -b your-shiny-new-feature origin/main
|
||||
$ git checkout -b your-shiny-new-feature origin/master
|
||||
|
||||
...
|
||||
|
||||
|
|
|
|||
45
Dockerfile
45
Dockerfile
|
|
@ -1,4 +1,4 @@
|
|||
FROM --platform=$BUILDPLATFORM golang:1.24-alpine AS builder
|
||||
FROM --platform=$BUILDPLATFORM golang:1.20-alpine as builder
|
||||
|
||||
RUN apk add --no-cache make git
|
||||
WORKDIR /workspace/helmfile
|
||||
|
|
@ -12,11 +12,11 @@ RUN make static-${TARGETOS}-${TARGETARCH}
|
|||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
FROM alpine:3.22
|
||||
FROM alpine:3.16
|
||||
|
||||
LABEL org.opencontainers.image.source=https://github.com/helmfile/helmfile
|
||||
LABEL org.opencontainers.image.source https://github.com/helmfile/helmfile
|
||||
|
||||
RUN apk add --no-cache ca-certificates git bash curl jq yq openssh-client gnupg
|
||||
RUN apk add --no-cache ca-certificates git bash curl jq openssh-client gnupg
|
||||
|
||||
ARG TARGETARCH TARGETOS TARGETPLATFORM
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ ENV HELM_CONFIG_HOME="${HELM_CONFIG_HOME}"
|
|||
ARG HELM_DATA_HOME="${HOME}/.local/share/helm"
|
||||
ENV HELM_DATA_HOME="${HELM_DATA_HOME}"
|
||||
|
||||
ARG HELM_VERSION="v3.19.0"
|
||||
ARG HELM_VERSION="v3.12.1"
|
||||
ENV HELM_VERSION="${HELM_VERSION}"
|
||||
ARG HELM_LOCATION="https://get.helm.sh"
|
||||
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}" && \
|
||||
echo Verifying ${HELM_FILENAME}... && \
|
||||
case ${TARGETPLATFORM} in \
|
||||
"linux/amd64") HELM_SHA256="a7f81ce08007091b86d8bd696eb4d86b8d0f2e1b9f6c714be62f82f96a594496" ;; \
|
||||
"linux/arm64") HELM_SHA256="440cf7add0aee27ebc93fada965523c1dc2e0ab340d4348da2215737fc0d76ad" ;; \
|
||||
"linux/amd64") HELM_SHA256="1a7074f58ef7190f74ce6db5db0b70e355a655e2013c4d5db2317e63fa9e3dea" ;; \
|
||||
"linux/arm64") HELM_SHA256="50548d4fedef9d8d01d1ed5a2dd5c849271d1017127417dc4c7ef6777ae68f7e" ;; \
|
||||
esac && \
|
||||
echo "${HELM_SHA256} ${HELM_FILENAME}" | sha256sum -c && \
|
||||
echo Extracting ${HELM_FILENAME}... && \
|
||||
|
|
@ -50,41 +50,40 @@ RUN set -x && \
|
|||
# using the install documentation found at https://kubernetes.io/docs/tasks/tools/install-kubectl/
|
||||
# for now but in a future version of alpine (in the testing version at the time of writing)
|
||||
# we should be able to install using apk add.
|
||||
ENV KUBECTL_VERSION="v1.32.1"
|
||||
ENV KUBECTL_VERSION="v1.25.2"
|
||||
RUN set -x && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/${TARGETOS}/${TARGETARCH}/kubectl" && \
|
||||
case ${TARGETPLATFORM} in \
|
||||
"linux/amd64") KUBECTL_SHA256="e16c80f1a9f94db31063477eb9e61a2e24c1a4eee09ba776b029048f5369db0c" ;; \
|
||||
"linux/arm64") KUBECTL_SHA256="98206fd83a4fd17f013f8c61c33d0ae8ec3a7c53ec59ef3d6a0a9400862dc5b2" ;; \
|
||||
"linux/amd64") KUBECTL_SHA256="8639f2b9c33d38910d706171ce3d25be9b19fc139d0e3d4627f38ce84f9040eb" ;; \
|
||||
"linux/arm64") KUBECTL_SHA256="b26aa656194545699471278ad899a90b1ea9408d35f6c65e3a46831b9c063fd5" ;; \
|
||||
esac && \
|
||||
echo "${KUBECTL_SHA256} kubectl" | sha256sum -c && \
|
||||
chmod +x kubectl && \
|
||||
mv kubectl /usr/local/bin/kubectl && \
|
||||
[ "$(kubectl version -o json | jq -r '.clientVersion.gitVersion')" = "${KUBECTL_VERSION}" ]
|
||||
|
||||
ENV KUSTOMIZE_VERSION="v5.4.3"
|
||||
ENV KUSTOMIZE_VERSION="v4.5.7"
|
||||
ARG KUSTOMIZE_FILENAME="kustomize_${KUSTOMIZE_VERSION}_${TARGETOS}_${TARGETARCH}.tar.gz"
|
||||
RUN set -x && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/${KUSTOMIZE_VERSION}/${KUSTOMIZE_FILENAME}" && \
|
||||
case ${TARGETPLATFORM} in \
|
||||
# Checksums are available at https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/${KUSTOMIZE_VERSION}/checksums.txt
|
||||
"linux/amd64") KUSTOMIZE_SHA256="3669470b454d865c8184d6bce78df05e977c9aea31c30df3c669317d43bcc7a7" ;; \
|
||||
"linux/arm64") KUSTOMIZE_SHA256="1b515578b0af12c15d9856720066ce2fe66756d63785b2cbccaf2885beb2381c" ;; \
|
||||
"linux/amd64") KUSTOMIZE_SHA256="701e3c4bfa14e4c520d481fdf7131f902531bfc002cb5062dcf31263a09c70c9" ;; \
|
||||
"linux/arm64") KUSTOMIZE_SHA256="65665b39297cc73c13918f05bbe8450d17556f0acd16242a339271e14861df67" ;; \
|
||||
esac && \
|
||||
echo "${KUSTOMIZE_SHA256} ${KUSTOMIZE_FILENAME}" | sha256sum -c && \
|
||||
tar xvf "${KUSTOMIZE_FILENAME}" -C /usr/local/bin && \
|
||||
rm "${KUSTOMIZE_FILENAME}" && \
|
||||
[ "$(kustomize version)" = "${KUSTOMIZE_VERSION}" ]
|
||||
kustomize version --short | grep "kustomize/${KUSTOMIZE_VERSION}"
|
||||
|
||||
ENV SOPS_VERSION="v3.10.2"
|
||||
ENV SOPS_VERSION="v3.7.3"
|
||||
ARG SOPS_FILENAME="sops-${SOPS_VERSION}.${TARGETOS}.${TARGETARCH}"
|
||||
RUN set -x && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://github.com/getsops/sops/releases/download/${SOPS_VERSION}/${SOPS_FILENAME}" && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://github.com/mozilla/sops/releases/download/${SOPS_VERSION}/${SOPS_FILENAME}" && \
|
||||
chmod +x "${SOPS_FILENAME}" && \
|
||||
mv "${SOPS_FILENAME}" /usr/local/bin/sops && \
|
||||
sops --version --disable-version-check | grep -E "^sops ${SOPS_VERSION#v}"
|
||||
sops --version | grep -E "^sops ${SOPS_VERSION#v}"
|
||||
|
||||
ENV AGE_VERSION="v1.2.1"
|
||||
ENV AGE_VERSION="v1.0.0"
|
||||
ARG AGE_FILENAME="age-${AGE_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz"
|
||||
RUN set -x && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://github.com/FiloSottile/age/releases/download/${AGE_VERSION}/${AGE_FILENAME}" && \
|
||||
|
|
@ -93,10 +92,10 @@ RUN set -x && \
|
|||
[ "$(age --version)" = "${AGE_VERSION}" ] && \
|
||||
[ "$(age-keygen --version)" = "${AGE_VERSION}" ]
|
||||
|
||||
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.13.1 && \
|
||||
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/aslafy-z/helm-git.git --version v1.3.0 && \
|
||||
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.8.1 && \
|
||||
helm plugin install https://github.com/jkroepke/helm-secrets --version v4.1.1 && \
|
||||
helm plugin install https://github.com/hypnoglow/helm-s3.git --version v0.14.0 && \
|
||||
helm plugin install https://github.com/aslafy-z/helm-git.git --version v0.12.0 && \
|
||||
rm -rf ${HELM_CACHE_HOME}/plugins
|
||||
|
||||
# Allow users other than root to use helm plugins located in root home
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM --platform=$BUILDPLATFORM golang:1.24-alpine AS builder
|
||||
FROM --platform=$BUILDPLATFORM golang:1.20-alpine as builder
|
||||
|
||||
RUN apk add --no-cache make git
|
||||
WORKDIR /workspace/helmfile
|
||||
|
|
@ -14,20 +14,17 @@ RUN make static-${TARGETOS}-${TARGETARCH}
|
|||
|
||||
FROM debian:stable-slim
|
||||
|
||||
LABEL org.opencontainers.image.source=https://github.com/helmfile/helmfile
|
||||
LABEL org.opencontainers.image.source https://github.com/helmfile/helmfile
|
||||
|
||||
RUN apt update -qq && \
|
||||
apt install --no-install-recommends -y \
|
||||
ca-certificates \
|
||||
gnupg \
|
||||
git bash curl jq wget openssh-client && \
|
||||
ca-certificates \
|
||||
gnupg \
|
||||
git bash curl jq wget openssh-client && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG TARGETARCH TARGETOS TARGETPLATFORM
|
||||
|
||||
RUN wget https://github.com/mikefarah/yq/releases/latest/download/yq_${TARGETOS}_${TARGETARCH} -O /usr/local/bin/yq &&\
|
||||
chmod +x /usr/local/bin/yq
|
||||
|
||||
# Set Helm home variables so that also non-root users can use plugins etc.
|
||||
ARG HOME="/helm"
|
||||
ENV HOME="${HOME}"
|
||||
|
|
@ -38,7 +35,7 @@ ENV HELM_CONFIG_HOME="${HELM_CONFIG_HOME}"
|
|||
ARG HELM_DATA_HOME="${HOME}/.local/share/helm"
|
||||
ENV HELM_DATA_HOME="${HELM_DATA_HOME}"
|
||||
|
||||
ARG HELM_VERSION="v3.19.0"
|
||||
ARG HELM_VERSION="v3.12.1"
|
||||
ENV HELM_VERSION="${HELM_VERSION}"
|
||||
ARG HELM_LOCATION="https://get.helm.sh"
|
||||
ARG HELM_FILENAME="helm-${HELM_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz"
|
||||
|
|
@ -46,8 +43,8 @@ RUN set -x && \
|
|||
curl --retry 5 --retry-connrefused -LO "${HELM_LOCATION}/${HELM_FILENAME}" && \
|
||||
echo Verifying ${HELM_FILENAME}... && \
|
||||
case ${TARGETPLATFORM} in \
|
||||
"linux/amd64") HELM_SHA256="a7f81ce08007091b86d8bd696eb4d86b8d0f2e1b9f6c714be62f82f96a594496" ;; \
|
||||
"linux/arm64") HELM_SHA256="440cf7add0aee27ebc93fada965523c1dc2e0ab340d4348da2215737fc0d76ad" ;; \
|
||||
"linux/amd64") HELM_SHA256="1a7074f58ef7190f74ce6db5db0b70e355a655e2013c4d5db2317e63fa9e3dea" ;; \
|
||||
"linux/arm64") HELM_SHA256="50548d4fedef9d8d01d1ed5a2dd5c849271d1017127417dc4c7ef6777ae68f7e" ;; \
|
||||
esac && \
|
||||
echo "${HELM_SHA256} ${HELM_FILENAME}" | sha256sum -c && \
|
||||
echo Extracting ${HELM_FILENAME}... && \
|
||||
|
|
@ -58,42 +55,40 @@ RUN set -x && \
|
|||
# using the install documentation found at https://kubernetes.io/docs/tasks/tools/install-kubectl/
|
||||
# for now but in a future version of alpine (in the testing version at the time of writing)
|
||||
# we should be able to install using apk add.
|
||||
ENV KUBECTL_VERSION="v1.32.1"
|
||||
ENV KUBECTL_VERSION="v1.25.2"
|
||||
RUN set -x && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/${TARGETOS}/${TARGETARCH}/kubectl" && \
|
||||
case ${TARGETPLATFORM} in \
|
||||
# checksums are available at https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/${TARGETOS}/${TARGETARCH}/kubectl.sha256
|
||||
"linux/amd64") KUBECTL_SHA256="e16c80f1a9f94db31063477eb9e61a2e24c1a4eee09ba776b029048f5369db0c" ;; \
|
||||
"linux/arm64") KUBECTL_SHA256="98206fd83a4fd17f013f8c61c33d0ae8ec3a7c53ec59ef3d6a0a9400862dc5b2" ;; \
|
||||
"linux/amd64") KUBECTL_SHA256="8639f2b9c33d38910d706171ce3d25be9b19fc139d0e3d4627f38ce84f9040eb" ;; \
|
||||
"linux/arm64") KUBECTL_SHA256="b26aa656194545699471278ad899a90b1ea9408d35f6c65e3a46831b9c063fd5" ;; \
|
||||
esac && \
|
||||
echo "${KUBECTL_SHA256} kubectl" | sha256sum -c && \
|
||||
chmod +x kubectl && \
|
||||
mv kubectl /usr/local/bin/kubectl && \
|
||||
[ "$(kubectl version -o json | jq -r '.clientVersion.gitVersion')" = "${KUBECTL_VERSION}" ]
|
||||
|
||||
ENV KUSTOMIZE_VERSION="v5.4.3"
|
||||
ENV KUSTOMIZE_VERSION="v4.5.7"
|
||||
ARG KUSTOMIZE_FILENAME="kustomize_${KUSTOMIZE_VERSION}_${TARGETOS}_${TARGETARCH}.tar.gz"
|
||||
RUN set -x && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/${KUSTOMIZE_VERSION}/${KUSTOMIZE_FILENAME}" && \
|
||||
case ${TARGETPLATFORM} in \
|
||||
# Checksums are available at https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/${KUSTOMIZE_VERSION}/checksums.txt
|
||||
"linux/amd64") KUSTOMIZE_SHA256="3669470b454d865c8184d6bce78df05e977c9aea31c30df3c669317d43bcc7a7" ;; \
|
||||
"linux/arm64") KUSTOMIZE_SHA256="1b515578b0af12c15d9856720066ce2fe66756d63785b2cbccaf2885beb2381c" ;; \
|
||||
"linux/amd64") KUSTOMIZE_SHA256="701e3c4bfa14e4c520d481fdf7131f902531bfc002cb5062dcf31263a09c70c9" ;; \
|
||||
"linux/arm64") KUSTOMIZE_SHA256="65665b39297cc73c13918f05bbe8450d17556f0acd16242a339271e14861df67" ;; \
|
||||
esac && \
|
||||
echo "${KUSTOMIZE_SHA256} ${KUSTOMIZE_FILENAME}" | sha256sum -c && \
|
||||
tar xvf "${KUSTOMIZE_FILENAME}" -C /usr/local/bin && \
|
||||
rm "${KUSTOMIZE_FILENAME}" && \
|
||||
[ "$(kustomize version)" = "${KUSTOMIZE_VERSION}" ]
|
||||
kustomize version --short | grep "kustomize/${KUSTOMIZE_VERSION}"
|
||||
|
||||
ENV SOPS_VERSION="v3.10.2"
|
||||
ENV SOPS_VERSION="v3.7.3"
|
||||
ARG SOPS_FILENAME="sops-${SOPS_VERSION}.${TARGETOS}.${TARGETARCH}"
|
||||
RUN set -x && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://github.com/getsops/sops/releases/download/${SOPS_VERSION}/${SOPS_FILENAME}" && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://github.com/mozilla/sops/releases/download/${SOPS_VERSION}/${SOPS_FILENAME}" && \
|
||||
chmod +x "${SOPS_FILENAME}" && \
|
||||
mv "${SOPS_FILENAME}" /usr/local/bin/sops && \
|
||||
sops --version --disable-version-check | grep -E "^sops ${SOPS_VERSION#v}"
|
||||
sops --version | grep -E "^sops ${SOPS_VERSION#v}"
|
||||
|
||||
ENV AGE_VERSION="v1.2.1"
|
||||
ENV AGE_VERSION="v1.0.0"
|
||||
ARG AGE_FILENAME="age-${AGE_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz"
|
||||
RUN set -x && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://github.com/FiloSottile/age/releases/download/${AGE_VERSION}/${AGE_FILENAME}" && \
|
||||
|
|
@ -102,10 +97,10 @@ RUN set -x && \
|
|||
[ "$(age --version)" = "${AGE_VERSION}" ] && \
|
||||
[ "$(age-keygen --version)" = "${AGE_VERSION}" ]
|
||||
|
||||
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.13.1 && \
|
||||
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/aslafy-z/helm-git.git --version v1.3.0 && \
|
||||
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.8.1 && \
|
||||
helm plugin install https://github.com/jkroepke/helm-secrets --version v4.1.1 && \
|
||||
helm plugin install https://github.com/hypnoglow/helm-s3.git --version v0.14.0 && \
|
||||
helm plugin install https://github.com/aslafy-z/helm-git.git --version v0.12.0 && \
|
||||
rm -rf ${HELM_CACHE_HOME}/plugins
|
||||
|
||||
# Allow users other than root to use helm plugins located in root home
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM --platform=$BUILDPLATFORM golang:1.24-alpine AS builder
|
||||
FROM --platform=$BUILDPLATFORM golang:1.20-alpine as builder
|
||||
|
||||
RUN apk add --no-cache make git
|
||||
WORKDIR /workspace/helmfile
|
||||
|
|
@ -12,22 +12,19 @@ RUN make static-${TARGETOS}-${TARGETARCH}
|
|||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
FROM ubuntu:24.04
|
||||
FROM ubuntu:20.04
|
||||
|
||||
LABEL org.opencontainers.image.source=https://github.com/helmfile/helmfile
|
||||
LABEL org.opencontainers.image.source https://github.com/helmfile/helmfile
|
||||
|
||||
RUN apt update -qq && \
|
||||
apt install --no-install-recommends -y \
|
||||
ca-certificates \
|
||||
gnupg \
|
||||
git bash curl jq wget openssh-client && \
|
||||
ca-certificates \
|
||||
gnupg \
|
||||
git bash curl jq wget openssh-client && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG TARGETARCH TARGETOS TARGETPLATFORM
|
||||
|
||||
RUN wget https://github.com/mikefarah/yq/releases/latest/download/yq_${TARGETOS}_${TARGETARCH} -O /usr/local/bin/yq &&\
|
||||
chmod +x /usr/local/bin/yq
|
||||
|
||||
# Set Helm home variables so that also non-root users can use plugins etc.
|
||||
ARG HOME="/helm"
|
||||
ENV HOME="${HOME}"
|
||||
|
|
@ -38,7 +35,7 @@ ENV HELM_CONFIG_HOME="${HELM_CONFIG_HOME}"
|
|||
ARG HELM_DATA_HOME="${HOME}/.local/share/helm"
|
||||
ENV HELM_DATA_HOME="${HELM_DATA_HOME}"
|
||||
|
||||
ARG HELM_VERSION="v3.19.0"
|
||||
ARG HELM_VERSION="v3.12.1"
|
||||
ENV HELM_VERSION="${HELM_VERSION}"
|
||||
ARG HELM_LOCATION="https://get.helm.sh"
|
||||
ARG HELM_FILENAME="helm-${HELM_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz"
|
||||
|
|
@ -46,8 +43,8 @@ RUN set -x && \
|
|||
curl --retry 5 --retry-connrefused -LO "${HELM_LOCATION}/${HELM_FILENAME}" && \
|
||||
echo Verifying ${HELM_FILENAME}... && \
|
||||
case ${TARGETPLATFORM} in \
|
||||
"linux/amd64") HELM_SHA256="a7f81ce08007091b86d8bd696eb4d86b8d0f2e1b9f6c714be62f82f96a594496" ;; \
|
||||
"linux/arm64") HELM_SHA256="440cf7add0aee27ebc93fada965523c1dc2e0ab340d4348da2215737fc0d76ad" ;; \
|
||||
"linux/amd64") HELM_SHA256="1a7074f58ef7190f74ce6db5db0b70e355a655e2013c4d5db2317e63fa9e3dea" ;; \
|
||||
"linux/arm64") HELM_SHA256="50548d4fedef9d8d01d1ed5a2dd5c849271d1017127417dc4c7ef6777ae68f7e" ;; \
|
||||
esac && \
|
||||
echo "${HELM_SHA256} ${HELM_FILENAME}" | sha256sum -c && \
|
||||
echo Extracting ${HELM_FILENAME}... && \
|
||||
|
|
@ -58,42 +55,40 @@ RUN set -x && \
|
|||
# using the install documentation found at https://kubernetes.io/docs/tasks/tools/install-kubectl/
|
||||
# for now but in a future version of alpine (in the testing version at the time of writing)
|
||||
# we should be able to install using apk add.
|
||||
ENV KUBECTL_VERSION="v1.32.1"
|
||||
ENV KUBECTL_VERSION="v1.25.2"
|
||||
RUN set -x && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/${TARGETOS}/${TARGETARCH}/kubectl" && \
|
||||
case ${TARGETPLATFORM} in \
|
||||
# checksums are available at https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/${TARGETOS}/${TARGETARCH}/kubectl.sha256
|
||||
"linux/amd64") KUBECTL_SHA256="e16c80f1a9f94db31063477eb9e61a2e24c1a4eee09ba776b029048f5369db0c" ;; \
|
||||
"linux/arm64") KUBECTL_SHA256="98206fd83a4fd17f013f8c61c33d0ae8ec3a7c53ec59ef3d6a0a9400862dc5b2" ;; \
|
||||
"linux/amd64") KUBECTL_SHA256="8639f2b9c33d38910d706171ce3d25be9b19fc139d0e3d4627f38ce84f9040eb" ;; \
|
||||
"linux/arm64") KUBECTL_SHA256="b26aa656194545699471278ad899a90b1ea9408d35f6c65e3a46831b9c063fd5" ;; \
|
||||
esac && \
|
||||
echo "${KUBECTL_SHA256} kubectl" | sha256sum -c && \
|
||||
chmod +x kubectl && \
|
||||
mv kubectl /usr/local/bin/kubectl && \
|
||||
[ "$(kubectl version -o json | jq -r '.clientVersion.gitVersion')" = "${KUBECTL_VERSION}" ]
|
||||
|
||||
ENV KUSTOMIZE_VERSION="v5.4.3"
|
||||
ENV KUSTOMIZE_VERSION="v4.5.7"
|
||||
ARG KUSTOMIZE_FILENAME="kustomize_${KUSTOMIZE_VERSION}_${TARGETOS}_${TARGETARCH}.tar.gz"
|
||||
RUN set -x && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/${KUSTOMIZE_VERSION}/${KUSTOMIZE_FILENAME}" && \
|
||||
case ${TARGETPLATFORM} in \
|
||||
# Checksums are available at https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/${KUSTOMIZE_VERSION}/checksums.txt
|
||||
"linux/amd64") KUSTOMIZE_SHA256="3669470b454d865c8184d6bce78df05e977c9aea31c30df3c669317d43bcc7a7" ;; \
|
||||
"linux/arm64") KUSTOMIZE_SHA256="1b515578b0af12c15d9856720066ce2fe66756d63785b2cbccaf2885beb2381c" ;; \
|
||||
"linux/amd64") KUSTOMIZE_SHA256="701e3c4bfa14e4c520d481fdf7131f902531bfc002cb5062dcf31263a09c70c9" ;; \
|
||||
"linux/arm64") KUSTOMIZE_SHA256="65665b39297cc73c13918f05bbe8450d17556f0acd16242a339271e14861df67" ;; \
|
||||
esac && \
|
||||
echo "${KUSTOMIZE_SHA256} ${KUSTOMIZE_FILENAME}" | sha256sum -c && \
|
||||
tar xvf "${KUSTOMIZE_FILENAME}" -C /usr/local/bin && \
|
||||
rm "${KUSTOMIZE_FILENAME}" && \
|
||||
[ "$(kustomize version)" = "${KUSTOMIZE_VERSION}" ]
|
||||
kustomize version --short | grep "kustomize/${KUSTOMIZE_VERSION}"
|
||||
|
||||
ENV SOPS_VERSION="v3.10.2"
|
||||
ENV SOPS_VERSION="v3.7.3"
|
||||
ARG SOPS_FILENAME="sops-${SOPS_VERSION}.${TARGETOS}.${TARGETARCH}"
|
||||
RUN set -x && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://github.com/getsops/sops/releases/download/${SOPS_VERSION}/${SOPS_FILENAME}" && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://github.com/mozilla/sops/releases/download/${SOPS_VERSION}/${SOPS_FILENAME}" && \
|
||||
chmod +x "${SOPS_FILENAME}" && \
|
||||
mv "${SOPS_FILENAME}" /usr/local/bin/sops && \
|
||||
sops --version --disable-version-check | grep -E "^sops ${SOPS_VERSION#v}"
|
||||
sops --version | grep -E "^sops ${SOPS_VERSION#v}"
|
||||
|
||||
ENV AGE_VERSION="v1.2.1"
|
||||
ENV AGE_VERSION="v1.0.0"
|
||||
ARG AGE_FILENAME="age-${AGE_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz"
|
||||
RUN set -x && \
|
||||
curl --retry 5 --retry-connrefused -LO "https://github.com/FiloSottile/age/releases/download/${AGE_VERSION}/${AGE_FILENAME}" && \
|
||||
|
|
@ -102,10 +97,10 @@ RUN set -x && \
|
|||
[ "$(age --version)" = "${AGE_VERSION}" ] && \
|
||||
[ "$(age-keygen --version)" = "${AGE_VERSION}" ]
|
||||
|
||||
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.13.1 && \
|
||||
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/aslafy-z/helm-git.git --version v1.3.0 && \
|
||||
RUN helm plugin install https://github.com/databus23/helm-diff --version v3.8.1 && \
|
||||
helm plugin install https://github.com/jkroepke/helm-secrets --version v4.1.1 && \
|
||||
helm plugin install https://github.com/hypnoglow/helm-s3.git --version v0.14.0 && \
|
||||
helm plugin install https://github.com/aslafy-z/helm-git.git --version v0.12.0 && \
|
||||
rm -rf ${HELM_CACHE_HOME}/plugins
|
||||
|
||||
# Allow users other than root to use helm plugins located in root home
|
||||
|
|
|
|||
4
Makefile
4
Makefile
|
|
@ -25,6 +25,10 @@ build:
|
|||
go build -ldflags="$(GO_BUILD_VERSION_LDFLAGS)" ${TARGETS}
|
||||
.PHONY: build
|
||||
|
||||
build-v1:
|
||||
go build -ldflags="$(GO_BUILD_VERSION_LDFLAGS) -X github.com/helmfile/helmfile/pkg/runtime.v1Mode=true" ${TARGETS}
|
||||
.PHONY: build-v1
|
||||
|
||||
generate:
|
||||
go generate ${PKGS}
|
||||
.PHONY: generate
|
||||
|
|
|
|||
|
|
@ -12,12 +12,10 @@
|
|||
# Helmfile
|
||||
|
||||
[](https://github.com/helmfile/helmfile/actions/workflows/ci.yaml?query=branch%3Amain)
|
||||
[](https://github.com/helmfile/helmfile/pkgs/container/helmfile)
|
||||
[](https://github.com/helmfile/helmfile/pkgs/container/helmfile)
|
||||
[](https://goreportcard.com/report/github.com/helmfile/helmfile)
|
||||
[](https://slack.sweetops.com)
|
||||
[](https://helmfile.readthedocs.io/en/latest/)
|
||||
[](https://gurubase.io/g/helmfile)
|
||||
[](https://zread.ai/helmfile/helmfile)
|
||||
|
||||
声明式Helm Chart管理工具
|
||||
<br />
|
||||
|
|
|
|||
22
README.md
22
README.md
|
|
@ -12,12 +12,10 @@
|
|||
# Helmfile
|
||||
|
||||
[](https://github.com/helmfile/helmfile/actions/workflows/ci.yaml?query=branch%3Amain)
|
||||
[](https://github.com/helmfile/helmfile/pkgs/container/helmfile)
|
||||
[](https://github.com/helmfile/helmfile/pkgs/container/helmfile)
|
||||
[](https://goreportcard.com/report/github.com/helmfile/helmfile)
|
||||
[](https://slack.sweetops.com)
|
||||
[](https://helmfile.readthedocs.io/en/latest/)
|
||||
[](https://gurubase.io/g/helmfile)
|
||||
[](https://zread.ai/helmfile/helmfile)
|
||||
|
||||
Deploy Kubernetes Helm Charts
|
||||
<br />
|
||||
|
|
@ -34,9 +32,7 @@ Helmfile is a declarative spec for deploying helm charts. It lets you...
|
|||
* Apply CI/CD to configuration changes.
|
||||
* Periodically sync to avoid skew in environments.
|
||||
|
||||
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)
|
||||
To avoid upgrades for each iteration of `helm`, the `helmfile` executable delegates to `helm` - as a result, `helm` must be installed.
|
||||
|
||||
## Highlights
|
||||
|
||||
|
|
@ -50,10 +46,14 @@ To avoid upgrades for each iteration of `helm`, the `helmfile` executable delega
|
|||
|
||||
## Status
|
||||
|
||||
May 2025 Update
|
||||
March 2022 Update - The helmfile project has been moved to [helmfile/helmfile](https://github.com/helmfile/helmfile) from the former home `roboll/helmfile`. Please see roboll/helmfile#1824 for more information.
|
||||
|
||||
Even though Helmfile is used in production environments [across multiple organizations](USERS.md), it is still in its early stage of development, hence versioned 0.x.
|
||||
|
||||
Helmfile complies to Semantic Versioning 2.0.0 in which v0.x means that there could be backward-incompatible changes for every release.
|
||||
|
||||
Note that we will try our best to document any backward incompatibility. And in reality, helmfile had no breaking change for a year or so.
|
||||
|
||||
* Helmfile v1.0 and v1.1 has been released. We recommend upgrading directly to v1.1 if you are still using v0.x.
|
||||
* If you haven't already upgraded, please go over this v1 proposal [here](docs/proposals/towards-1.0.md) to see a small list of breaking changes.
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
@ -109,10 +109,6 @@ Iterate on the `helmfile.yaml` by referencing:
|
|||
* [CLI reference](https://helmfile.readthedocs.io/en/latest/#cli-reference)
|
||||
* [Helmfile Best Practices Guide](https://helmfile.readthedocs.io/en/latest/writing-helmfile/)
|
||||
|
||||
## More complex examples
|
||||
|
||||
See: [multi-env-helmfile](https://github.com/helmfile/multi-env-helmfile)
|
||||
|
||||
## Docs
|
||||
|
||||
Please read [complete documentation](https://helmfile.readthedocs.io/)
|
||||
|
|
|
|||
5
USERS.md
5
USERS.md
|
|
@ -36,9 +36,4 @@ information to this file.
|
|||
| [subshell](https://subshell.com) | production | We're using helmfile since 2021 to deploy all our Kubernetes workloads into our clusters. We love helmfile for its simplicity and power. Thank you! | Hamburg, Germany | August 2022 |
|
||||
| [Norddeutscher Rundfunk](https://www.ndr.de) | production | Using Helmfile since 2020 to deploy workloads to several similar clusters (dev, qa, prod, test, etc.) for sites tagesschau.de and sportschau.de. Thank you so much for your awesome work! | Hamburg, Germany | August 2022 |
|
||||
| [Dealhub](https://dealhub.io/) | production | Helmfile was an essential part of our k8s migration. Keep up the good work! | Holon, Israel | January 2023 |
|
||||
| [BlueLabs](https://bluelabs.eu/) | production | Helmfile is the cornerstone of our lightweight, auditable and centralized GKE deployments. | Europe | February 2021 |
|
||||
| [Zhihu](https://www.zhihu.com/) | production | helmfile is an important tool for the deployment of our basic components, which can achieve standardization and auditability. |China, Beijing | December 2023 |
|
||||
| [Tudock](https://tudock.de) | production | We have no public post about it, but we recently started using Helmfile to deploy developer applications and have been very happy with the results! | Hamburg, Germany | March 2024 |
|
||||
| [Incentive.me](https://incentive.me/) | production | We use helmfile as the main tool for deploying our Kubernetes workloads. | Rio de Janeiro, Brazil | November 2021 |
|
||||
| [RightCapital](https://www.rightcapital.com/) | production | We use helmfile as the main tool for deploying our Kubernetes workloads. | Shelton, CT, USA | May 2019 |
|
||||
<!-- TABLE_END -->
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
Vagrant.configure("2") do |config|
|
||||
config.vm.box = "ubuntu/focal64"
|
||||
config.vm.hostname = "minikube.box"
|
||||
config.vm.provision :shell, privileged: false,
|
||||
inline: <<-EOS
|
||||
set -e
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y make docker.io
|
||||
sudo systemctl start docker
|
||||
sudo usermod -G docker $USER
|
||||
cd /vagrant/.circleci
|
||||
make all
|
||||
EOS
|
||||
|
||||
config.vm.provider "virtualbox" do |v|
|
||||
v.memory = 2048
|
||||
v.cpus = 2
|
||||
end
|
||||
end
|
||||
15
cmd/apply.go
15
cmd/apply.go
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/helmfile/helmfile/pkg/app"
|
||||
"github.com/helmfile/helmfile/pkg/config"
|
||||
"github.com/helmfile/helmfile/pkg/runtime"
|
||||
)
|
||||
|
||||
// NewApplyCmd returns apply subcmd
|
||||
|
|
@ -40,9 +41,13 @@ func NewApplyCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
|||
f.StringVar(&applyOptions.Output, "output", "", "output format for diff plugin")
|
||||
f.BoolVar(&applyOptions.DetailedExitcode, "detailed-exitcode", false, "return a non-zero exit code 2 instead of 0 when there were changes detected AND the changes are synced successfully")
|
||||
f.BoolVar(&applyOptions.StripTrailingCR, "strip-trailing-cr", false, "strip trailing carriage return on input")
|
||||
f.StringVar(&applyOptions.DiffArgs, "diff-args", "", `pass args to helm helm-diff`)
|
||||
f.StringVar(&applyOptions.SyncArgs, "sync-args", "", `pass args to helm upgrade`)
|
||||
f.StringVar(&globalCfg.GlobalOptions.Args, "args", "", "pass args to helm exec")
|
||||
if !runtime.V1Mode {
|
||||
// TODO: Remove this function once Helmfile v0.x
|
||||
f.BoolVar(&applyOptions.RetainValuesFiles, "retain-values-files", false, "DEPRECATED: Use skip-cleanup instead")
|
||||
_ = f.MarkDeprecated("retain-values-files", "Use skip-cleanup instead")
|
||||
}
|
||||
|
||||
f.BoolVar(&applyOptions.SkipCleanup, "skip-cleanup", false, "Stop cleaning up temporary values generated by helmfile and helm-secrets. Useful for debugging. Don't use in production for security")
|
||||
f.BoolVar(&applyOptions.SkipCRDs, "skip-crds", false, "if set, no CRDs will be installed on sync. By default, CRDs are installed if not already present")
|
||||
f.BoolVar(&applyOptions.SkipNeeds, "skip-needs", true, `do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`)
|
||||
|
|
@ -54,19 +59,13 @@ func NewApplyCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
|||
f.BoolVar(&applyOptions.SuppressSecrets, "suppress-secrets", false, "suppress secrets in the diff output. highly recommended to specify on CI/CD use-cases")
|
||||
f.BoolVar(&applyOptions.ShowSecrets, "show-secrets", false, "do not redact secret values in the diff output. should be used for debug purpose only")
|
||||
f.BoolVar(&applyOptions.NoHooks, "no-hooks", false, "do not diff changes made by hooks.")
|
||||
f.BoolVar(&applyOptions.HideNotes, "hide-notes", false, "add --hide-notes flag to helm")
|
||||
f.BoolVar(&applyOptions.TakeOwnership, "take-ownership", false, "add --take-ownership flag to helm")
|
||||
f.BoolVar(&applyOptions.SyncReleaseLabels, "sync-release-labels", false, "sync release labels to the target release")
|
||||
f.BoolVar(&applyOptions.SuppressDiff, "suppress-diff", false, "suppress diff in the output. Usable in new installs")
|
||||
f.BoolVar(&applyOptions.Wait, "wait", false, `Override helmDefaults.wait setting "helm upgrade --install --wait"`)
|
||||
f.BoolVar(&applyOptions.WaitForJobs, "wait-for-jobs", false, `Override helmDefaults.waitForJobs setting "helm upgrade --install --wait-for-jobs"`)
|
||||
f.BoolVar(&applyOptions.ReuseValues, "reuse-values", false, `Override helmDefaults.reuseValues "helm upgrade --install --reuse-values"`)
|
||||
f.BoolVar(&applyOptions.ResetValues, "reset-values", false, `Override helmDefaults.reuseValues "helm upgrade --install --reset-values"`)
|
||||
f.StringVar(&applyOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`)
|
||||
f.StringArrayVar(&applyOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`)
|
||||
f.BoolVar(&applyOptions.SkipSchemaValidation, "skip-schema-validation", false, `pass --skip-schema-validation to "helm template" or "helm upgrade --install"`)
|
||||
f.StringVar(&applyOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background")
|
||||
f.StringArrayVar(&applyOptions.SuppressOutputLineRegex, "suppress-output-line-regex", nil, "a list of regex patterns to suppress output lines from the diff output")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
// TODO: Remove this function once Helmfile v0.x
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/app"
|
||||
"github.com/helmfile/helmfile/pkg/config"
|
||||
)
|
||||
|
||||
// NewChartsCmd returns charts subcmd
|
||||
func NewChartsCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||
chartsOptions := config.NewChartsOptions()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "charts",
|
||||
Short: "DEPRECATED: sync releases from state file (helm upgrade --install)",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
chartsImpl := config.NewChartsImpl(globalCfg, chartsOptions)
|
||||
err := config.NewCLIConfigImpl(chartsImpl.GlobalImpl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := chartsImpl.ValidateConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a := app.New(chartsImpl)
|
||||
return toCLIError(chartsImpl.GlobalImpl, a.DeprecatedSyncCharts(chartsImpl))
|
||||
},
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.StringVar(&globalCfg.GlobalOptions.Args, "args", "", "pass args to helm exec")
|
||||
f.StringArrayVar(&chartsOptions.Set, "set", nil, "additional values to be merged into the helm command --set flag")
|
||||
f.StringArrayVar(&chartsOptions.Values, "values", nil, "additional value files to be merged into the helm command --values flag")
|
||||
f.IntVar(&chartsOptions.Concurrency, "concurrency", 0, "maximum number of concurrent helm processes to run, 0 is unlimited")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// TODO: Remove this function once Helmfile v0.x
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/app"
|
||||
"github.com/helmfile/helmfile/pkg/config"
|
||||
)
|
||||
|
||||
// NewDeleteCmd returns delete subcmd
|
||||
func NewDeleteCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||
deleteOptions := config.NewDeleteOptions()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "DEPRECATED: delete releases from state file (helm delete)",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
deleteImpl := config.NewDeleteImpl(globalCfg, deleteOptions)
|
||||
err := config.NewCLIConfigImpl(deleteImpl.GlobalImpl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := deleteImpl.ValidateConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a := app.New(deleteImpl)
|
||||
return toCLIError(deleteImpl.GlobalImpl, a.Delete(deleteImpl))
|
||||
},
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.StringVar(&globalCfg.GlobalOptions.Args, "args", "", "pass args to helm exec")
|
||||
f.StringVar(&deleteOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background")
|
||||
f.IntVar(&deleteOptions.Concurrency, "concurrency", 0, "maximum number of concurrent helm processes to run, 0 is unlimited")
|
||||
f.BoolVar(&deleteOptions.Purge, "purge", false, "purge releases i.e. free release names and histories")
|
||||
f.BoolVar(&deleteOptions.SkipCharts, "skip-charts", false, "don't prepare charts when deleting releases")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
@ -35,8 +35,6 @@ func NewDestroyCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
|||
f.StringVar(&destroyOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background")
|
||||
f.IntVar(&destroyOptions.Concurrency, "concurrency", 0, "maximum number of concurrent helm processes to run, 0 is unlimited")
|
||||
f.BoolVar(&destroyOptions.SkipCharts, "skip-charts", false, "don't prepare charts when destroying releases")
|
||||
f.BoolVar(&destroyOptions.DeleteWait, "deleteWait", false, `override helmDefaults.wait setting "helm uninstall --wait"`)
|
||||
f.IntVar(&destroyOptions.DeleteTimeout, "deleteTimeout", 300, `time in seconds to wait for helm uninstall, default: 300`)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ func NewDiffCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
|||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.StringVar(&diffOptions.DiffArgs, "diff-args", "", `pass args to helm helm-diff`)
|
||||
f.StringVar(&globalCfg.GlobalOptions.Args, "args", "", "pass args to helm diff")
|
||||
f.StringArrayVar(&diffOptions.Set, "set", nil, "additional values to be merged into the helm command --set flag")
|
||||
f.StringArrayVar(&diffOptions.Values, "values", nil, "additional value files to be merged into the helm command --values flag")
|
||||
|
|
@ -52,10 +51,7 @@ func NewDiffCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
|||
f.StringArrayVar(&diffOptions.Suppress, "suppress", nil, "suppress specified Kubernetes objects in the output. Can be provided multiple times. For example: --suppress KeycloakClient --suppress VaultSecret")
|
||||
f.BoolVar(&diffOptions.ReuseValues, "reuse-values", false, `Override helmDefaults.reuseValues "helm diff upgrade --install --reuse-values"`)
|
||||
f.BoolVar(&diffOptions.ResetValues, "reset-values", false, `Override helmDefaults.reuseValues "helm diff upgrade --install --reset-values"`)
|
||||
f.BoolVar(&diffOptions.TakeOwnership, "take-ownership", false, "add --take-ownership flag to helm")
|
||||
f.StringVar(&diffOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`)
|
||||
f.StringArrayVar(&diffOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`)
|
||||
f.StringArrayVar(&diffOptions.SuppressOutputLineRegex, "suppress-output-line-regex", nil, "a list of regex patterns to suppress output lines from the diff output")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
|
|||
23
cmd/root.go
23
cmd/root.go
|
|
@ -60,13 +60,7 @@ func NewRootCmd(globalConfig *config.GlobalOptions) (*cobra.Command, error) {
|
|||
case globalConfig.Quiet:
|
||||
logLevel = "warn"
|
||||
}
|
||||
|
||||
// If the log output is not set, default to stderr.
|
||||
logOut := globalConfig.LogOutput
|
||||
if logOut == nil {
|
||||
logOut = os.Stderr
|
||||
}
|
||||
logger = helmexec.NewLogger(logOut, logLevel)
|
||||
logger = helmexec.NewLogger(os.Stderr, logLevel)
|
||||
globalConfig.SetLogger(logger)
|
||||
return nil
|
||||
},
|
||||
|
|
@ -76,7 +70,7 @@ func NewRootCmd(globalConfig *config.GlobalOptions) (*cobra.Command, error) {
|
|||
// Set the global options for the root command.
|
||||
setGlobalOptionsForRootCmd(flags, globalConfig)
|
||||
|
||||
flags.ParseErrorsAllowlist.UnknownFlags = true
|
||||
flags.ParseErrorsWhitelist.UnknownFlags = true
|
||||
|
||||
globalImpl := config.NewGlobalImpl(globalConfig)
|
||||
|
||||
|
|
@ -103,29 +97,32 @@ func NewRootCmd(globalConfig *config.GlobalOptions) (*cobra.Command, error) {
|
|||
NewSyncCmd(globalImpl),
|
||||
NewDiffCmd(globalImpl),
|
||||
NewStatusCmd(globalImpl),
|
||||
NewShowDAGCmd(globalImpl),
|
||||
extension.NewVersionCobraCmd(
|
||||
versionOpts...,
|
||||
),
|
||||
)
|
||||
|
||||
// TODO: Remove this function once Helmfile v0.x
|
||||
if !runtime.V1Mode {
|
||||
cmd.AddCommand(
|
||||
NewChartsCmd(globalImpl),
|
||||
NewDeleteCmd(globalImpl),
|
||||
)
|
||||
}
|
||||
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
func setGlobalOptionsForRootCmd(fs *pflag.FlagSet, globalOptions *config.GlobalOptions) {
|
||||
fs.StringVarP(&globalOptions.HelmBinary, "helm-binary", "b", app.DefaultHelmBinary, "Path to the helm binary")
|
||||
fs.StringVarP(&globalOptions.KustomizeBinary, "kustomize-binary", "k", app.DefaultKustomizeBinary, "Path to the kustomize binary")
|
||||
fs.StringVarP(&globalOptions.File, "file", "f", "", "load config from file or directory. defaults to \"`helmfile.yaml`\" or \"helmfile.yaml.gotmpl\" or \"helmfile.d\" (means \"helmfile.d/*.yaml\" or \"helmfile.d/*.yaml.gotmpl\") in this preference. Specify - to load the config from the standard input.")
|
||||
fs.StringVarP(&globalOptions.Environment, "environment", "e", "", `specify the environment name. Overrides "HELMFILE_ENVIRONMENT" OS environment variable when specified. defaults to "default"`)
|
||||
fs.StringArrayVar(&globalOptions.StateValuesSet, "state-values-set", nil, "set state values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template).")
|
||||
fs.StringArrayVar(&globalOptions.StateValuesSetString, "state-values-set-string", nil, "set state STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template).")
|
||||
fs.StringArrayVar(&globalOptions.StateValuesFile, "state-values-file", nil, "specify state values in a YAML file. Used to override .Values within the helmfile template (not values template).")
|
||||
fs.BoolVar(&globalOptions.SkipDeps, "skip-deps", false, `skip running "helm repo update" and "helm dependency build"`)
|
||||
fs.BoolVar(&globalOptions.SkipRefresh, "skip-refresh", false, `skip running "helm repo update"`)
|
||||
fs.BoolVar(&globalOptions.StripArgsValuesOnExitError, "strip-args-values-on-exit-error", true, `Strip the potential secret values of the helm command args contained in a helmfile error message`)
|
||||
fs.BoolVar(&globalOptions.DisableForceUpdate, "disable-force-update", false, `do not force helm repos to update when executing "helm repo add"`)
|
||||
fs.BoolVarP(&globalOptions.Quiet, "quiet", "q", false, "Silence output. Equivalent to log-level warn")
|
||||
fs.StringVar(&globalOptions.Kubeconfig, "kubeconfig", "", "Use a particular kubeconfig file")
|
||||
fs.StringVar(&globalOptions.KubeContext, "kube-context", "", "Set kubectl context. Uses current context by default")
|
||||
fs.BoolVar(&globalOptions.Debug, "debug", false, "Enable verbose output for Helm and set log-level to debug, this disables --quiet/-q effect")
|
||||
fs.BoolVar(&globalOptions.Color, "color", false, "Output with color")
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/app"
|
||||
"github.com/helmfile/helmfile/pkg/config"
|
||||
)
|
||||
|
||||
func NewShowDAGCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||
showDAGOptions := config.NewShowDAGOptions()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "show-dag",
|
||||
Short: "It prints a table with 3 columns, GROUP, RELEASE, and DEPENDENCIES. GROUP is the unsigned, monotonically increasing integer starting from 1. All the releases with the same GROUP are deployed concurrently. Everything in GROUP 2 starts being deployed only after everything in GROUP 1 got successfully deployed. RELEASE is the release that belongs to the GROUP. DEPENDENCIES is the list of releases that the RELEASE depends on. It should always be empty for releases in GROUP 1. DEPENDENCIES for a release in GROUP 2 should have some or all dependencies appeared in GROUP 1. It can be \"some\" because Helmfile simplifies the DAGs of releases into a DAG of groups, so that Helmfile always produce a single DAG for everything written in helmfile.yaml, even when there are technically two or more independent DAGs of releases in it.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
showDAGImpl := config.NewShowDAGImpl(globalCfg, showDAGOptions)
|
||||
err := config.NewCLIConfigImpl(showDAGImpl.GlobalImpl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := showDAGImpl.ValidateConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a := app.New(showDAGImpl)
|
||||
return toCLIError(showDAGImpl.GlobalImpl, a.PrintDAGState(showDAGImpl))
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
|
@ -32,7 +32,6 @@ func NewSyncCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
|||
|
||||
f := cmd.Flags()
|
||||
f.StringVar(&globalCfg.GlobalOptions.Args, "args", "", "pass args to helm sync")
|
||||
f.StringVar(&syncOptions.SyncArgs, "sync-args", "", "pass args to helm upgrade")
|
||||
f.StringArrayVar(&syncOptions.Set, "set", nil, "additional values to be merged into the helm command --set flag")
|
||||
f.StringArrayVar(&syncOptions.Values, "values", nil, "additional value files to be merged into the helm command --values flag")
|
||||
f.IntVar(&syncOptions.Concurrency, "concurrency", 0, "maximum number of concurrent helm processes to run, 0 is unlimited")
|
||||
|
|
@ -41,17 +40,11 @@ func NewSyncCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
|||
f.BoolVar(&syncOptions.SkipCRDs, "skip-crds", false, "if set, no CRDs will be installed on sync. By default, CRDs are installed if not already present")
|
||||
f.BoolVar(&syncOptions.IncludeNeeds, "include-needs", false, `automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
|
||||
f.BoolVar(&syncOptions.IncludeTransitiveNeeds, "include-transitive-needs", false, `like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`)
|
||||
f.BoolVar(&syncOptions.HideNotes, "hide-notes", false, "add --hide-notes flag to helm")
|
||||
f.BoolVar(&syncOptions.TakeOwnership, "take-ownership", false, `add --take-ownership flag to helm`)
|
||||
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.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.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.StringArrayVar(&syncOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`)
|
||||
f.BoolVar(&syncOptions.SkipSchemaValidation, "skip-schema-validation", false, `pass --skip-schema-validation to "helm template" or "helm upgrade --install"`)
|
||||
f.StringVar(&syncOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background")
|
||||
|
||||
return cmd
|
||||
|
|
|
|||
|
|
@ -44,12 +44,8 @@ func NewTemplateCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
|||
f.BoolVar(&templateOptions.IncludeNeeds, "include-needs", false, `automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
|
||||
f.BoolVar(&templateOptions.IncludeTransitiveNeeds, "include-transitive-needs", false, `like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`)
|
||||
f.BoolVar(&templateOptions.SkipCleanup, "skip-cleanup", false, "Stop cleaning up temporary values generated by helmfile and helm-secrets. Useful for debugging. Don't use in production for security")
|
||||
f.BoolVar(&templateOptions.NoHooks, "no-hooks", false, "do not template files made by hooks.")
|
||||
f.StringVar(&templateOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`)
|
||||
f.StringArrayVar(&templateOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`)
|
||||
f.BoolVar(&templateOptions.SkipSchemaValidation, "skip-schema-validation", false, `pass skip-schema-validation to "helm template" or "helm upgrade --install"`)
|
||||
f.StringVar(&templateOptions.KubeVersion, "kube-version", "", `pass --kube-version to "helm template". Overrides kubeVersion in helmfile.yaml`)
|
||||
f.StringArrayVar(&templateOptions.ShowOnly, "show-only", nil, `pass --show-only to "helm template"`)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,16 +14,16 @@ Helmfile integrates [vals]() to import configuration parameters from following b
|
|||
- Vault
|
||||
- SOPS
|
||||
|
||||
See [Vals "Supported Backends"](https://github.com/helmfile/vals#supported-backends) for the full list of available backends.
|
||||
See [Vals "Suported Backends"](https://github.com/helmfile/vals#suported-backends) for the full list of available backends.
|
||||
|
||||
This feature was implemented in https://github.com/roboll/helmfile/pull/906.
|
||||
If you're curious about how it's designed and how it works, please review the pull request.
|
||||
If you're curious how it's designed and how it works, please consult the pull request.
|
||||
|
||||
### Deploy Kustomizations with Helmfile
|
||||
|
||||
You can deploy [kustomize](https://github.com/kubernetes-sigs/kustomize) "kustomization"s with Helmfile.
|
||||
|
||||
Most Kustomize operations are usually done with `kustomize edit` and can be done declaratively via Helm `values.yaml` files.
|
||||
Most of Kustomize operations that is usually done with `kustomize edit` can be done declaratively via Helm values.yaml files.
|
||||
|
||||
Under the hood, Helmfile transforms the kustomization into a local chart in a temporary directory so that it can be `helm upgrade --install`ed.
|
||||
|
||||
|
|
@ -99,9 +99,6 @@ Please also see [test/advanced/helmfile.yaml](https://github.com/helmfile/helmfi
|
|||
|
||||
With Helmfile's integration with Kustomize, not only deploying Kustomization as a Helm chart, you can kustomize charts before installation.
|
||||
|
||||
.. Hint:: The following fields can also specify files, in the same manner as
|
||||
the `values` field.
|
||||
|
||||
Currently, Helmfile allows you to set the following fields for kustomizing the chart:
|
||||
|
||||
- [`releases[].strategicMergePatches`](#strategicmergepatches)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ releases:
|
|||
- `Release.Labels`: The labels to be applied to the release
|
||||
- `Release.Chart`: The chart name of the release
|
||||
- `Release.KubeContext`: The kube context to be used for the release
|
||||
- `Release.ChartVersion`: The version of the current chart
|
||||
- `Values`: Values passed into the environment.
|
||||
- `StateValues`: alias for `Values`.
|
||||
- `Environment`: The information about the environment. This is set by the
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
# Experimental Features
|
||||
|
||||
This document describes the experimental features that are available in Helmfile v1.
|
||||
|
||||
Any experimental feature may be removed or changed in a future release without notice.
|
||||
|
||||
- HCL helmfile-values-file support (PR #1423)
|
||||
|
|
@ -1,667 +0,0 @@
|
|||
# HCL Functions
|
||||
|
||||
## Standard Library
|
||||
The following functions are all from the [go-cty](https://pkg.go.dev/github.com/zclconf/go-cty/cty/function/stdlib#pkg-functions), [go-cty-yaml](https://pkg.go.dev/github.com/zclconf/go-cty-yaml) and [hcl](https://pkg.go.dev/github.com/hashicorp/hcl/v2@v2.20.1/ext/tryfunc#section-readme) libraries
|
||||
#### abs
|
||||
`abs` returns the absolute value
|
||||
```
|
||||
abs(number)
|
||||
```
|
||||
```
|
||||
abs(-1)
|
||||
# 1
|
||||
abs(2)
|
||||
# 2
|
||||
```
|
||||
#### can
|
||||
`can` evaluates an expression and returns a boolean if a result can be produced without any error
|
||||
```
|
||||
can(expr)
|
||||
```
|
||||
```
|
||||
map = {
|
||||
myvar = "myvar"
|
||||
}
|
||||
can1 = can(hv.map.myVar)
|
||||
# true
|
||||
can2 = can(hv.map.notMyVar)
|
||||
# false
|
||||
```
|
||||
#### ceil
|
||||
`ceil` returns the ceiling value of a given number
|
||||
```
|
||||
ceil(number)
|
||||
```
|
||||
```
|
||||
ceil(1)
|
||||
# 1
|
||||
ceil(1.1)
|
||||
# 2
|
||||
```
|
||||
#### chomp
|
||||
`chomp` removes newline characters at the end of a string.
|
||||
```
|
||||
chomp(string)
|
||||
```
|
||||
```
|
||||
chomp("myVar\n")
|
||||
# myVar
|
||||
```
|
||||
#### coalesce
|
||||
|
||||
`coalesce` returns the first of the given arguments that is not null. If all arguments are null, an error is produced.
|
||||
All arguments must be of the same type apart from some cases
|
||||
```
|
||||
coalesce(any...)
|
||||
```
|
||||
```
|
||||
coalesce(null, 2)
|
||||
# 2
|
||||
coalesce(null, "value")
|
||||
# value
|
||||
```
|
||||
Use the three dots notation `...` to expand a list
|
||||
```
|
||||
coalesce([null, "value"]...)
|
||||
# value
|
||||
```
|
||||
#### coalescelist
|
||||
`coalescelist` takes any number of list arguments and returns the first one that isn't empty.
|
||||
```
|
||||
coalescelist(list)
|
||||
```
|
||||
```
|
||||
coalescelist([], ["value"])
|
||||
# ["value"]
|
||||
```
|
||||
Use the three dots notation `...` when using list of lists
|
||||
```
|
||||
coalescelist([[], ["val1", "val2"]]...)
|
||||
# ["val1", "val2"]
|
||||
```
|
||||
#### compact
|
||||
`compact` returns a new list with any empty string elements removed.
|
||||
```
|
||||
compact(list)
|
||||
```
|
||||
```
|
||||
compact(["", "val1", "val2"])
|
||||
# ["val1", "val2"]
|
||||
```
|
||||
#### concat
|
||||
`concat` takes one or more sequences (lists or tuples) and returns the single sequence that results from concatenating them together in order.
|
||||
```
|
||||
concat(list, list...)
|
||||
```
|
||||
```
|
||||
concat(["val1"], ["val2", "val3"])
|
||||
# ["val1", "val2", "val3"]
|
||||
```
|
||||
#### contains
|
||||
`contains` returns a boolean if a list contains a given value
|
||||
```
|
||||
contains(list, value)
|
||||
```
|
||||
```
|
||||
contains(["val1", "val2"], "val2")
|
||||
# true
|
||||
```
|
||||
#### csvdecode
|
||||
`csvdecode` decodes a CSV-formatted string into a list of maps
|
||||
```
|
||||
csvdecode(string)
|
||||
```
|
||||
```
|
||||
csvdecode("col1,col2\nv1,v2\nv3,v4")
|
||||
###
|
||||
[
|
||||
{
|
||||
"col1" = "v1"
|
||||
"col2" = "v2"
|
||||
},
|
||||
{
|
||||
"col1" = "v3"
|
||||
"col2" = "v4"
|
||||
}
|
||||
]
|
||||
```
|
||||
#### distinct
|
||||
`distinct` returns a new list from another by removing all duplicates
|
||||
```
|
||||
distinct(list)
|
||||
```
|
||||
```
|
||||
distinct(["v1","v1","v2"])
|
||||
["v1", "v2"]
|
||||
```
|
||||
#### element
|
||||
`element` returns a single element from a given list at the given index. If index is greater than the length of the list then it is wrapped modulo the list length
|
||||
```
|
||||
element(list, index)
|
||||
```
|
||||
```
|
||||
element(["val1","val2"], 1)
|
||||
# val2
|
||||
```
|
||||
|
||||
#### chunklist
|
||||
`chunklist` splits a single list into fixed-size chunks, returning a list of lists.
|
||||
```
|
||||
chunklist(list, size)
|
||||
```
|
||||
```
|
||||
chunklist(["a","b"], 1)
|
||||
# [["a"], ["b"]]
|
||||
```
|
||||
#### flatten
|
||||
`flatten` takes a list and replaces any elements that are lists with a flattened sequence of the list contents.
|
||||
```
|
||||
flatten(list)
|
||||
```
|
||||
```
|
||||
flatten([["a"], ["a","b"], ["c"]])
|
||||
# ["a","a","b","c"]
|
||||
```
|
||||
#### floor
|
||||
`floor` returns the closest whole number lesser than or equal to the given value.
|
||||
```
|
||||
floor(number)
|
||||
```
|
||||
```
|
||||
floor(1)
|
||||
# 1
|
||||
floor(0.7)
|
||||
# 0
|
||||
```
|
||||
#### format
|
||||
`format` produces a string representation of zero or more values using a format string similar to the "printf" function in C.
|
||||
[Verbs details](https://pkg.go.dev/github.com/zclconf/go-cty/cty/function/stdlib#Format)
|
||||
```
|
||||
format(format, values)
|
||||
```
|
||||
```
|
||||
format("Hello %s", "world")
|
||||
# Hello world
|
||||
```
|
||||
#### formatdate
|
||||
`formatdate` reformats a timestamp given in RFC3339 syntax into another time syntax defined by a given format string.
|
||||
[Syntax details](https://pkg.go.dev/github.com/zclconf/go-cty/cty/function/stdlib#FormatDate)
|
||||
```
|
||||
formatdate(string, timestampString)
|
||||
```
|
||||
```
|
||||
formatdate("MMM DD YYYY", "2024-01-01T00:12:00Z")
|
||||
# Jan 01 2024
|
||||
```
|
||||
|
||||
#### formatlist
|
||||
`formatlist` does the same as `format` but for a list of strings
|
||||
```
|
||||
formatlist(formatString, values...)
|
||||
```
|
||||
```
|
||||
formatlist("%s", ["Hello", "World"])
|
||||
###
|
||||
[
|
||||
"Hello",
|
||||
"World"
|
||||
]
|
||||
|
||||
formatlist("%s %s", "hello", ["World", "You"])
|
||||
###
|
||||
[
|
||||
"hello World",
|
||||
"hello You",
|
||||
]
|
||||
```
|
||||
#### indent
|
||||
`indent` adds a given number of spaces to the beginnings of all but the first line in a given multi-line string.
|
||||
```
|
||||
indent(number, string)
|
||||
```
|
||||
|
||||
```
|
||||
indent(4, "hello,\nWorld\n!")
|
||||
###
|
||||
hello
|
||||
World
|
||||
!
|
||||
```
|
||||
#### int
|
||||
`int` removes the fractional component of the given number returning an integer representing the whole number component, rounding towards zero.
|
||||
|
||||
```
|
||||
int(number)
|
||||
```
|
||||
```
|
||||
int(6.2)
|
||||
# 6
|
||||
```
|
||||
|
||||
#### join
|
||||
`join` concatenates together the string elements of one or more lists with a given separator.
|
||||
```
|
||||
join(listOfStrings, separator)
|
||||
```
|
||||
```
|
||||
join(" ", ["hello", "world"])
|
||||
# hello world
|
||||
```
|
||||
|
||||
#### jsondecode
|
||||
`jsondecode` parses the given JSON string and, if it is valid, returns the value it represents.
|
||||
```
|
||||
jsonencode(string)
|
||||
```
|
||||
Example :
|
||||
```
|
||||
jsonencode({"hello"="world"})
|
||||
# {"hello": "world"}
|
||||
```
|
||||
|
||||
#### jsonencode
|
||||
`jsonencode` returns a JSON serialization of the given value.
|
||||
```
|
||||
jsondecode(string)
|
||||
```
|
||||
Example :
|
||||
```
|
||||
jsondecode("{\"hello\": \"world\"}")
|
||||
# { hello = "world" }
|
||||
```
|
||||
#### keys
|
||||
`keys` takes a map and returns a sorted list of the map keys.
|
||||
|
||||
```
|
||||
keys(map)
|
||||
```
|
||||
|
||||
```
|
||||
keys({val1=1, val2=2, val3=3})
|
||||
# ["val1","val2","val3"]
|
||||
```
|
||||
#### length
|
||||
`length` returns the number of elements in the given __collection__.
|
||||
See `strlen` for strings
|
||||
```
|
||||
length(list)
|
||||
```
|
||||
|
||||
```
|
||||
length([1,2,3])
|
||||
# 3
|
||||
```
|
||||
#### log
|
||||
`log` returns returns the logarithm of a given number in a given base.
|
||||
```
|
||||
log(number, base)
|
||||
```
|
||||
|
||||
```
|
||||
log(1, 10)
|
||||
# 0
|
||||
```
|
||||
#### lookup
|
||||
`lookup` performs a dynamic lookup into a map. There are three required arguments, inputMap and key, plus a defaultValue, which is a value to return if the given key is not found in the inputMap.
|
||||
```
|
||||
lookup(inputMap, key, defaultValue)
|
||||
```
|
||||
|
||||
```
|
||||
map = { "luke" = "skywalker"}
|
||||
lookup(hv.maptest, "luke", "none")
|
||||
# skywalker
|
||||
lookup(hv.maptest, "leia", "none")
|
||||
# none
|
||||
```
|
||||
#### lower
|
||||
`lower` is a Function that converts a given string to lowercase.
|
||||
```
|
||||
lower(string)
|
||||
```
|
||||
|
||||
```
|
||||
lower("HELLO world")
|
||||
# hello world
|
||||
```
|
||||
#### max
|
||||
`max` returns the maximum number from the given numbers.
|
||||
```
|
||||
max(numbers)
|
||||
```
|
||||
|
||||
```
|
||||
max(1,128,70)
|
||||
# 128
|
||||
|
||||
```
|
||||
#### merge
|
||||
`merge` takes an arbitrary number of maps and returns a single map that contains a merged set of elements from all of the maps.
|
||||
```
|
||||
merge(maps)
|
||||
```
|
||||
```
|
||||
merge({a="1"}, {a=[1,2], c="world"}, {d=40})
|
||||
# { a = [1,2], c = "world", d = 40}
|
||||
|
||||
```
|
||||
#### min
|
||||
`min` returns the minimum number from the given numbers.
|
||||
```
|
||||
min(numbers)
|
||||
```
|
||||
```
|
||||
min(1,128,70)
|
||||
# 1
|
||||
```
|
||||
#### parseint
|
||||
`parseint` parses a string argument and returns an integer of the specified base.
|
||||
```
|
||||
parseint(string, base)
|
||||
```
|
||||
```
|
||||
parseint("190", 10)
|
||||
# 190
|
||||
parseint("11001", 2)
|
||||
# 25
|
||||
```
|
||||
#### pow
|
||||
`pow` returns the logarithm of a given number in a given base.
|
||||
```
|
||||
pow(number, power)
|
||||
```
|
||||
|
||||
```
|
||||
pow(1, 10)
|
||||
# 1
|
||||
pow(3, 12)
|
||||
# 531441
|
||||
```
|
||||
#### range
|
||||
`range` creates a list of numbers by starting from the given starting value, then adding the given step value until the result is greater than or equal to the given stopping value. Each intermediate result becomes an element in the resulting list.
|
||||
```
|
||||
range(startingNumber, stoppingNumber, stepNumber)
|
||||
```
|
||||
|
||||
```
|
||||
range(1, 10, 3)
|
||||
# [1, 4, 7]
|
||||
```
|
||||
#### regex
|
||||
`regex` is a function that extracts one or more substrings from a given string by applying a regular expression pattern, describing the first match.
|
||||
The return type depends on the composition of the capture groups (if any) in the pattern:
|
||||
|
||||
If there are no capture groups at all, the result is a single string representing the entire matched pattern.
|
||||
If all of the capture groups are named, the result is an object whose keys are the named groups and whose values are their sub-matches, or null if a particular sub-group was inside another group that didn't match.
|
||||
If none of the capture groups are named, the result is a tuple whose elements are the sub-groups in order and whose values are their sub-matches, or null if a particular sub-group was inside another group that didn't match.
|
||||
It is invalid to use both named and un-named capture groups together in the same pattern.
|
||||
|
||||
If the pattern doesn't match, this function returns an error. To test for a match, call `regexall` and check if the length of the result is greater than zero.
|
||||
```
|
||||
regex(pattern, string)
|
||||
```
|
||||
|
||||
```
|
||||
regex("[0-9]+", "v1.2.3")
|
||||
# 1
|
||||
```
|
||||
#### regexall
|
||||
`regexall` is similar to Regex but it finds all of the non-overlapping matches in the given string and returns a list of them.
|
||||
|
||||
The result type is always a list, whose element type is deduced from the pattern in the same way as the return type for Regex is decided.
|
||||
|
||||
If the pattern doesn't match at all, this function returns an empty list.
|
||||
```
|
||||
regexall(pattern, string)
|
||||
```
|
||||
|
||||
```
|
||||
regexall("[0-9]+", "v1.2.3")
|
||||
# [1 2 3]
|
||||
```
|
||||
#### setintersection
|
||||
`setintersection` returns a new set containing the elements that exist in all of the given sets, which must have element types that can all be converted to some common type using the standard type unification rules. If conversion is not possible, an error is returned.
|
||||
```
|
||||
setintersection(sets...)
|
||||
```
|
||||
|
||||
```
|
||||
setintersection(["val1", "val2"], ["val1", "val3"], ["val1", "val2"])
|
||||
# ["val1"]
|
||||
```
|
||||
#### setproduct
|
||||
`setproduct` computes the Cartesian product of sets or sequences.
|
||||
```
|
||||
setproduct(sets...)
|
||||
```
|
||||
```
|
||||
setproduct(["host1", "host2"], ["stg.domain", "prod.domain"])
|
||||
###
|
||||
[
|
||||
[
|
||||
"host1",
|
||||
"stg.domain"
|
||||
],
|
||||
[
|
||||
"host2",
|
||||
"stg.domain"
|
||||
],
|
||||
[
|
||||
"host1",
|
||||
"prod.domain"
|
||||
],
|
||||
[
|
||||
"host2",
|
||||
"prod.domain"
|
||||
],
|
||||
]
|
||||
```
|
||||
#### setsubtract
|
||||
`setsubtract` returns a new set containing the elements from the first set that are not present in the second set. The sets must have element types that can both be converted to some common type using the standard type unification rules. If conversion is not possible, an error is returned.
|
||||
```
|
||||
setsubtract(sets...)
|
||||
```
|
||||
```
|
||||
setsubtract(["a", "b", "c"], ["a", "b"])
|
||||
###
|
||||
["c"]
|
||||
```
|
||||
#### setunion
|
||||
`setunion` returns a new set containing all of the elements from the given sets, which must have element types that can all be converted to some common type using the standard type unification rules. If conversion is not possible, an error is returned.
|
||||
```
|
||||
setunion(sets...)
|
||||
```
|
||||
|
||||
```
|
||||
setunion(["a", "b"], ["b", "c"], ["a", "d"])
|
||||
###
|
||||
["a", "b", "c", "d"]
|
||||
```
|
||||
#### signum
|
||||
`signum` determines the sign of a number, returning a number between -1 and 1 to represent the sign.
|
||||
```
|
||||
signum(number)
|
||||
```
|
||||
```
|
||||
signum(-182)
|
||||
# -1
|
||||
```
|
||||
#### slice
|
||||
`slice` extracts some consecutive elements from within a list.
|
||||
startIndex is inclusive, endIndex is exclusive
|
||||
```
|
||||
slice(list, startIndex, endIndex)
|
||||
```
|
||||
```
|
||||
slice([{"a" = "b"}, {"c" = "d"}, , {"e" = "f"}], 1, 1)
|
||||
# []
|
||||
slice([{"a" = "b"}, {"c" = "d"}, {"e" = "f"}], 1, 2)
|
||||
# [{"c" = "d"}]
|
||||
```
|
||||
#### sort
|
||||
`sort` re-orders the elements of a given list of strings so that they are in ascending lexicographical order.
|
||||
```
|
||||
sort(list)
|
||||
```
|
||||
```
|
||||
sort(["1", "h", "r", "p", "word"])
|
||||
# ["1", "h", "p", "r", "word"]
|
||||
```
|
||||
#### split
|
||||
`split` divides a given string by a given separator, returning a list of strings containing the characters between the separator sequences.
|
||||
```
|
||||
split(separatorString, string)
|
||||
```
|
||||
```
|
||||
split(".", "host.domain")
|
||||
# ["host", "domain"]
|
||||
```
|
||||
#### strlen
|
||||
`strlen` is a Function that returns the length of the given string in characters.
|
||||
```
|
||||
strlen(string)
|
||||
```
|
||||
```
|
||||
strlen("yes")
|
||||
# 3
|
||||
```
|
||||
#### strrev
|
||||
`strrev` is a Function that reverses the order of the characters in the given string.
|
||||
```
|
||||
strrev(string)
|
||||
```
|
||||
```
|
||||
strrev("yes")
|
||||
# "sey"
|
||||
```
|
||||
#### substr
|
||||
`substr` is a Function that extracts a sequence of characters from another string and creates a new string.
|
||||
```
|
||||
substr(string, offsetNumber, length)
|
||||
```
|
||||
```
|
||||
substr("host.domain", 0, 4)
|
||||
# "host"
|
||||
```
|
||||
#### timeadd
|
||||
`timeadd` adds a duration to a timestamp, returning a new timestamp.
|
||||
Only units "inferior" or equal to `h` are supported.
|
||||
The duration can be negative.
|
||||
```
|
||||
substr(timestamp, duration)
|
||||
```
|
||||
```
|
||||
timeadd("2024-01-01T00:00:00Z", "-2600h10m")
|
||||
# 2023-09-14T15:50:00Z
|
||||
```
|
||||
#### trim
|
||||
`trim` removes the specified characters from the start and end of the given string.
|
||||
```
|
||||
trim(string, string)
|
||||
```
|
||||
```
|
||||
trim("Can you do that ? Yes ?", "?")
|
||||
# "Can you do that ? Yes"
|
||||
```
|
||||
#### trimprefix
|
||||
`trimprefix` removes the specified prefix from the start of the given string.
|
||||
```
|
||||
trimprefix(stringToTrim, trimmingString)
|
||||
```
|
||||
```
|
||||
trimprefix("please, do it", "please, ")
|
||||
# "do it"
|
||||
```
|
||||
#### trimspace
|
||||
`trimspace` removes any space characters from the start and end of the given string.
|
||||
```
|
||||
trimspace(string)
|
||||
```
|
||||
```
|
||||
trimspace(" Hello World ")
|
||||
# "Hello World"
|
||||
```
|
||||
#### trimsuffix
|
||||
`trimsuffix` removes the specified suffix from the end of the given string.
|
||||
```
|
||||
trimsuffix(stringToTrim, trimmingString)
|
||||
```
|
||||
```
|
||||
trimsuffix("Hello World", " World")
|
||||
# "Hello"
|
||||
```
|
||||
#### try
|
||||
`try` is a variadic function that tries to evaluate all of is arguments in sequence until one succeeds, in which case it returns that result, or returns an error if none of them succeed.
|
||||
```
|
||||
try(expressions...)
|
||||
```
|
||||
```
|
||||
values {
|
||||
map = {
|
||||
hello = "you"
|
||||
world = "us"
|
||||
}
|
||||
try(hv.map.do_not_exist, hv.map.world)
|
||||
}
|
||||
# "us"
|
||||
```
|
||||
#### upper
|
||||
`upper` is a Function that converts a given string to uppercase.
|
||||
```
|
||||
upper(string)
|
||||
```
|
||||
```
|
||||
upper("up")
|
||||
# "UP"
|
||||
```
|
||||
#### values
|
||||
`values` returns a list of the map values, in the order of the sorted keys. This function only works on flat maps.
|
||||
```
|
||||
values(map)
|
||||
```
|
||||
```
|
||||
values({"a" = 1,"b" = 2})
|
||||
# [1, 2]
|
||||
```
|
||||
#### yamldecode
|
||||
`yamldecode` parses the given JSON string and, if it is valid, returns the value it represents.
|
||||
```
|
||||
yamldecode(string)
|
||||
```
|
||||
```
|
||||
yamldecode("hello: world\narray: [1, 2, 3]")
|
||||
###
|
||||
{
|
||||
array = [1, 2, 3]
|
||||
hello = "world"
|
||||
}
|
||||
```
|
||||
#### yamlencode
|
||||
`yamlencode` returns a JSON serialization of the given value.
|
||||
```
|
||||
yamlencode({array = [1, 2, 3], hello = "world"})
|
||||
```
|
||||
|
||||
```
|
||||
yamlencode({array = [1, 2, 3], hello = "world"})
|
||||
###
|
||||
"array":
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
"hello": "world"
|
||||
```
|
||||
#### zipmap
|
||||
`zipmap` constructs a map from a list of keys and a corresponding list of values.
|
||||
The lenght of each list must be equal
|
||||
```
|
||||
zipmap(keysList, valuesList)
|
||||
```
|
||||
```
|
||||
zipmap(["key1", "key2"], ["val1", "val2"])
|
||||
###
|
||||
{
|
||||
"key1" = "val1"
|
||||
"key2" = "val2"
|
||||
}
|
||||
```
|
||||
436
docs/index.md
436
docs/index.md
|
|
@ -12,7 +12,7 @@
|
|||
# Helmfile
|
||||
|
||||
[](https://github.com/helmfile/helmfile/actions/workflows/ci.yaml?query=branch%3Amain)
|
||||
[](https://github.com/helmfile/helmfile/pkgs/container/helmfile)
|
||||
[](https://github.com/helmfile/helmfile/pkgs/container/helmfile)
|
||||
[](https://goreportcard.com/report/github.com/helmfile/helmfile)
|
||||
[](https://slack.sweetops.com)
|
||||
[](https://helmfile.readthedocs.io/en/latest/)
|
||||
|
|
@ -24,10 +24,13 @@ Deploy Kubernetes Helm Charts
|
|||
|
||||
## Status
|
||||
|
||||
May 2025 Update
|
||||
March 2022 Update - The helmfile project has been moved to [helmfile/helmfile](https://github.com/helmfile/helmfile) from the former home `roboll/helmfile`. Please see [roboll/helmfile#1824](https://github.com/roboll/helmfile/issues/1824) for more information.
|
||||
|
||||
* Helmfile v1.0 and v1.1 has been released. We recommend upgrading directly to v1.1 if you are still using v0.x.
|
||||
* If you haven't already upgraded, please go over this v1 proposal [here](https://github.com/helmfile/helmfile/blob/main/docs/proposals/towards-1.0.md) to see a small list of breaking changes.
|
||||
Even though Helmfile is used in production environments [across multiple organizations](users.md), it is still in its early stage of development, hence versioned 0.x.
|
||||
|
||||
Helmfile complies to Semantic Versioning 2.0.0 in which v0.x means that there could be backward-incompatible changes for every release.
|
||||
|
||||
Note that we will try our best to document any backward incompatibility. And in reality, helmfile had no breaking change for a year or so.
|
||||
|
||||
## About
|
||||
|
||||
|
|
@ -60,16 +63,27 @@ To avoid upgrades for each iteration of `helm`, the `helmfile` executable delega
|
|||
|
||||
### Running as a container
|
||||
|
||||
The [Helmfile Docker images are available in GHCR](https://github.com/helmfile/helmfile/pkgs/container/helmfile). There is no `latest` tag, since the `0.x` versions can contain breaking changes, so make sure you pick the right tag. Example using `helmfile 0.156.0`:
|
||||
The [Helmfile Docker images are available in GHCR](https://github.com/helmfile/helmfile/pkgs/container/helmfile). There is no `latest` tag, since the `0.x` versions can contain breaking changes, so make sure you pick the right tag. Example using `helmfile 0.145.2`:
|
||||
|
||||
```sh-session
|
||||
$ docker run --rm --net=host -v "${HOME}/.kube:/helm/.kube" -v "${HOME}/.config/helm:/helm/.config/helm" -v "${PWD}:/wd" --workdir /wd ghcr.io/helmfile/helmfile:v0.156.0 helmfile sync
|
||||
# helm 2
|
||||
$ docker run --rm --net=host -v "${HOME}/.kube:/root/.kube" -v "${HOME}/.helm:/root/.helm" -v "${PWD}:/wd" --workdir /wd ghcr.io/helmfile/helmfile:v0.145.2 helmfile sync
|
||||
|
||||
# helm 3
|
||||
$ docker run --rm --net=host -v "${HOME}/.kube:/root/.kube" -v "${HOME}/.config/helm:/root/.config/helm" -v "${PWD}:/wd" --workdir /wd ghcr.io/helmfile/helmfile:helm3-v0.145.2 helmfile sync
|
||||
```
|
||||
|
||||
You can also use a shim to make calling the binary easier:
|
||||
You can also use shims to make calling the binaries easier:
|
||||
|
||||
```sh-session
|
||||
$ printf '%s\n' '#!/bin/sh' 'docker run --rm --net=host -v "${HOME}/.kube:/helm/.kube" -v "${HOME}/.config/helm:/helm/.config/helm" -v "${PWD}:/wd" --workdir /wd ghcr.io/helmfile/helmfile:v0.156.0 helmfile "$@"' |
|
||||
# helm 2
|
||||
$ printf '%s\n' '#!/bin/sh' 'docker run --rm --net=host -v "${HOME}/.kube:/root/.kube" -v "${HOME}/.helm:/root/.helm" -v "${PWD}:/wd" --workdir /wd ghcr.io/helmfile/helmfile:v0.145.2 helmfile "$@"' |
|
||||
tee helmfile
|
||||
$ chmod +x helmfile
|
||||
$ ./helmfile sync
|
||||
|
||||
# helm 3
|
||||
$ printf '%s\n' '#!/bin/sh' 'docker run --rm --net=host -v "${HOME}/.kube:/root/.kube" -v "${HOME}/.config/helm:/root/.config/helm" -v "${PWD}:/wd" --workdir /wd ghcr.io/helmfile/helmfile:helm3-v0.145.2 helmfile "$@"' |
|
||||
tee helmfile
|
||||
$ chmod +x helmfile
|
||||
$ ./helmfile sync
|
||||
|
|
@ -95,12 +109,6 @@ releases:
|
|||
value: false
|
||||
```
|
||||
|
||||
Install required dependencies using [init](https://helmfile.readthedocs.io/en/latest/#init):
|
||||
|
||||
```console
|
||||
helmfile init
|
||||
```
|
||||
|
||||
Sync your Kubernetes cluster state to the desired one by running:
|
||||
|
||||
```console
|
||||
|
|
@ -113,7 +121,7 @@ Iterate on the `helmfile.yaml` by referencing:
|
|||
|
||||
* [Configuration](#configuration)
|
||||
* [CLI reference](#cli-reference).
|
||||
* [Helmfile Best Practices Guide](writing-helmfile.md)
|
||||
* [Helmfile Best Practices Guide](https://github.com/roboll/helmfile/blob/master/docs/writing-helmfile.md)
|
||||
|
||||
## Configuration
|
||||
|
||||
|
|
@ -141,35 +149,27 @@ repositories:
|
|||
url: roboll.io/charts
|
||||
certFile: optional_client_cert
|
||||
keyFile: optional_client_key
|
||||
# username is retrieved from the environment with the format <registryNameUpperCase>_USERNAME for CI usage, here ROBOLL_USERNAME
|
||||
# username is retrieve from the environment with the format <registryNameUpperCase>_USERNAME for CI usage, here ROBOLL_USERNAME
|
||||
username: optional_username
|
||||
# password is retrieved from the environment with the format <registryNameUpperCase>_PASSWORD for CI usage, here ROBOLL_PASSWORD
|
||||
# username is retrieve from the environment with the format <registryNameUpperCase>_PASSWORD for CI usage, here ROBOLL_PASSWORD
|
||||
password: optional_password
|
||||
oci: true
|
||||
passCredentials: true
|
||||
verify: true
|
||||
keyring: path/to/keyring.gpg
|
||||
# Advanced configuration: You can use a ca bundle to use an https repo
|
||||
# with a self-signed certificate
|
||||
- name: insecure
|
||||
url: https://charts.my-insecure-domain.com
|
||||
caFile: optional_ca_crt
|
||||
url: https://charts.my-insecure-domain.com
|
||||
caFile: optional_ca_crt
|
||||
# Advanced configuration: You can skip the verification of TLS for an https repo
|
||||
- name: skipTLS
|
||||
url: https://ss.my-insecure-domain.com
|
||||
skipTLSVerify: true
|
||||
# Advanced configuration: Connect to a repo served over plain http
|
||||
- name: plainHTTP
|
||||
url: http://just.http.domain.com
|
||||
plainHttp: true
|
||||
|
||||
# context: kube-context # this directive is deprecated, please consider using helmDefaults.kubeContext
|
||||
|
||||
# Path to alternative helm binary (--helm-binary)
|
||||
helmBinary: path/to/helm3
|
||||
|
||||
# Path to alternative kustomize binary (--kustomize-binary)
|
||||
kustomizeBinary: path/to/kustomize
|
||||
|
||||
# Path to alternative lock file. The default is <state file name>.lock, i.e for helmfile.yaml it's helmfile.lock.
|
||||
lockFilePath: path/to/lock.file
|
||||
|
|
@ -183,20 +183,10 @@ helmDefaults:
|
|||
# additional and global args passed to helm (default "")
|
||||
args:
|
||||
- "--set k=v"
|
||||
diffArgs:
|
||||
- "--suppress-secrets"
|
||||
syncArgs:
|
||||
- "--labels=app.kubernetes.io/managed-by=helmfile"
|
||||
# verify the chart before upgrading (only works with packaged charts not directories) (default false)
|
||||
verify: true
|
||||
keyring: path/to/keyring.gpg
|
||||
# --skip-schema-validation flag to helm 'install', 'upgrade' and 'lint', starts with helm 3.16.0 (default false)
|
||||
skipSchemaValidation: false
|
||||
# wait for k8s resources via --wait. (default false)
|
||||
wait: true
|
||||
# DEPRECATED: waitRetries is no longer supported as the --wait-retries flag was removed from Helm.
|
||||
# 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)
|
||||
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)
|
||||
|
|
@ -219,28 +209,10 @@ helmDefaults:
|
|||
reuseValues: false
|
||||
# propagate `--post-renderer` to helmv3 template and helm install
|
||||
postRenderer: "path/to/postRenderer"
|
||||
# propagate `--post-renderer-args` to helmv3 template and helm install. This allows using Powershell
|
||||
# scripts on Windows as a post renderer
|
||||
postRendererArgs:
|
||||
- PowerShell
|
||||
- "-Command"
|
||||
- "theScript.ps1"
|
||||
# cascade `--cascade` to helmv3 delete, available values: background, foreground, or orphan, default: background
|
||||
cascade: "background"
|
||||
# insecureSkipTLSVerify is true if the TLS verification should be skipped when fetching remote chart
|
||||
insecureSkipTLSVerify: false
|
||||
# plainHttp is true if fetching the remote chart should be done using HTTP
|
||||
plainHttp: false
|
||||
# --wait flag for destroy/delete, if set to true, will wait until all resources are deleted before mark delete command as successful
|
||||
deleteWait: false
|
||||
# Timeout is the time in seconds to wait for helmfile destroy/delete (default 300)
|
||||
deleteTimeout: 300
|
||||
# suppressOutputLineRegex is a list of regex patterns to suppress output lines from helm diff (default []), available in helmfile v0.162.0
|
||||
suppressOutputLineRegex:
|
||||
- "version"
|
||||
# syncReleaseLabels is a list of labels to be added to the release when syncing.
|
||||
syncReleaseLabels: false
|
||||
|
||||
|
||||
# these labels will be applied to all releases in a Helmfile. Useful in templating if you have a helmfile per environment or customer and don't want to copy the same label to each release
|
||||
commonLabels:
|
||||
|
|
@ -287,16 +259,6 @@ releases:
|
|||
domain: {{ requiredEnv "PLATFORM_ID" }}.my-domain.com
|
||||
scheme: {{ env "SCHEME" | default "https" }}
|
||||
# Use `values` whenever possible!
|
||||
# `setString` translates to helm's `--set-string key=val`
|
||||
setString:
|
||||
# set a single array value in an array, translates to --set-string bar[0]={1,2}
|
||||
- name: bar[0]
|
||||
values:
|
||||
- 1
|
||||
- 2
|
||||
# set a templated value
|
||||
- name: namespace
|
||||
value: {{ .Namespace }}
|
||||
# `set` translates to helm's `--set key=val`, that is known to suffer from type issues like https://github.com/roboll/helmfile/issues/608
|
||||
set:
|
||||
# single value loaded from a local file, translates to --set-file foo.config=path/to/file
|
||||
|
|
@ -313,24 +275,15 @@ releases:
|
|||
# will attempt to decrypt it using helm-secrets plugin
|
||||
secrets:
|
||||
- vault_secret.yaml
|
||||
# Override helmDefaults options for verify, wait, waitForJobs, timeout, recreatePods, force and reuseValues.
|
||||
# Override helmDefaults options for verify, wait, waitForJobs, timeout, recreatePods and force.
|
||||
verify: true
|
||||
keyring: path/to/keyring.gpg
|
||||
# --skip-schema-validation flag to helm 'install', 'upgrade' and 'lint', starts with helm 3.16.0 (default false)
|
||||
skipSchemaValidation: false
|
||||
wait: true
|
||||
# DEPRECATED: waitRetries is no longer supported - see documentation above
|
||||
# waitRetries: 3
|
||||
waitForJobs: true
|
||||
timeout: 60
|
||||
recreatePods: true
|
||||
force: false
|
||||
reuseValues: false
|
||||
# set `false` to uninstall this release on sync. (default true)
|
||||
installed: true
|
||||
# Defines the strategy to use when updating. Possible value is:
|
||||
# - "reinstallIfForbidden": Performs an uninstall before the update only if the update is forbidden (e.g., due to permission issues or conflicts).
|
||||
updateStrategy: ""
|
||||
# restores previous state in case of failed release (default false)
|
||||
atomic: true
|
||||
# when true, cleans up any new resources created during a failed release (default false)
|
||||
|
|
@ -358,26 +311,10 @@ releases:
|
|||
skipDeps: false
|
||||
# propagate `--post-renderer` to helmv3 template and helm install
|
||||
postRenderer: "path/to/postRenderer"
|
||||
# propagate `--post-renderer-args` to helmv3 template and helm install. This allows using Powershell
|
||||
# scripts on Windows as a post renderer
|
||||
postRendererArgs:
|
||||
- PowerShell
|
||||
- "-Command"
|
||||
- "theScript.ps1"
|
||||
# cascade `--cascade` to helmv3 delete, available values: background, foreground, or orphan, default: background
|
||||
cascade: "background"
|
||||
# insecureSkipTLSVerify is true if the TLS verification should be skipped when fetching remote chart
|
||||
insecureSkipTLSVerify: false
|
||||
# plainHttp is true if fetching the remote chart should be done using HTTP
|
||||
plainHttp: false
|
||||
# suppressDiff skip the helm diff output. Useful for charts which produces large not helpful diff, default: false
|
||||
suppressDiff: false
|
||||
# suppressOutputLineRegex is a list of regex patterns to suppress output lines from helm diff (default []), available in helmfile v0.162.0
|
||||
suppressOutputLineRegex:
|
||||
- "version"
|
||||
# syncReleaseLabels is a list of labels to be added to the release when syncing.
|
||||
syncReleaseLabels: false
|
||||
|
||||
|
||||
# Local chart example
|
||||
- name: grafana # name of this release
|
||||
|
|
@ -414,16 +351,9 @@ helmfiles:
|
|||
# The nested-state file is locally checked-out along with the remote directory containing it.
|
||||
# Therefore all the local paths in the file are resolved relative to the file
|
||||
path: git::https://github.com/cloudposse/helmfiles.git@releases/kiam.yaml?ref=0.40.0
|
||||
- # By default git repositories aren't updated unless the ref is updated.
|
||||
# Alternatively, refer to a named ref and disable the caching.
|
||||
path: git::ssh://git@github.com/cloudposse/helmfiles.git@releases/kiam.yaml?ref=main&cache=false
|
||||
# If set to "Error", return an error when a subhelmfile points to a
|
||||
# non-existent path. The default behavior is to print a warning and continue.
|
||||
missingFileHandler: Error
|
||||
missingFileHandlerConfig:
|
||||
# Ignores missing git branch error so that the Debug/Info/Warn handler can treat a missing branch as non-error.
|
||||
# See https://github.com/helmfile/helmfile/issues/392
|
||||
ignoreMissingGitBranch: true
|
||||
|
||||
#
|
||||
# Advanced Configuration: Environments
|
||||
|
|
@ -443,9 +373,6 @@ environments:
|
|||
# `{{ .Values.foo.bar }}` is evaluated to `1`.
|
||||
values:
|
||||
- environments/default/values.yaml
|
||||
# Everything from the values.hcl in the `values` block is available via `{{ .Values.KEY }}`.
|
||||
# More details in its dedicated section
|
||||
- environments/default/values.hcl
|
||||
# Each entry in values can be either a file path or inline values.
|
||||
# The below is an example of inline values, which is merged to the `.Values`
|
||||
- myChartVer: 1.0.0-dev
|
||||
|
|
@ -514,26 +441,22 @@ Helmfile uses [Go templates](https://godoc.org/text/template) for templating you
|
|||
|
||||
We also added the following functions:
|
||||
|
||||
* [`env`](templating_funcs.md#env)
|
||||
* [`requiredEnv`](templating_funcs.md#requiredenv)
|
||||
* [`exec`](templating_funcs.md#exec)
|
||||
* [`envExec`](templating_funcs.md#envexec)
|
||||
* [`readFile`](templating_funcs.md#readfile)
|
||||
* [`readDir`](templating_funcs.md#readdir)
|
||||
* [`readDirEntries`](templating_funcs.md#readdirentries)
|
||||
* [`toYaml`](templating_funcs.md#toyaml)
|
||||
* [`fromYaml`](templating_funcs.md#fromyaml)
|
||||
* [`setValueAtPath`](templating_funcs.md#setvalueatpath)
|
||||
* [`get`](templating_funcs.md#get) (Sprig's original `get` is available as `sprigGet`)
|
||||
* [`getOrNil`](templating_funcs.md#getornil)
|
||||
* [`tpl`](templating_funcs.md#tpl)
|
||||
* [`required`](templating_funcs.md#required)
|
||||
* [`fetchSecretValue`](templating_funcs.md#fetchsecretvalue)
|
||||
* [`expandSecretRefs`](templating_funcs.md#expandsecretrefs)
|
||||
* [`include`](templating_funcs.md#include)
|
||||
|
||||
More details on each function can be found at the ["Template Functions" page in our documentation](templating_funcs.md).
|
||||
* `requiredEnv`
|
||||
* `exec`
|
||||
* `envExec`
|
||||
* `readFile`
|
||||
* `readDir`
|
||||
* `readDirEntries`
|
||||
* `toYaml`
|
||||
* `fromYaml`
|
||||
* `setValueAtPath`
|
||||
* `get` (Sprig's original `get` is available as `sprigGet`)
|
||||
* `tpl`
|
||||
* `required`
|
||||
* `fetchSecretValue`
|
||||
* `expandSecretRefs`
|
||||
|
||||
More details on each function can be found at ["Template Functions" page in our documentation](templating_funcs.md).
|
||||
|
||||
## Using environment variables
|
||||
|
||||
|
|
@ -574,22 +497,20 @@ Helmfile uses some OS environment variables to override default behaviour:
|
|||
* `HELMFILE_DISABLE_INSECURE_FEATURES` - disable insecure features, expecting `true` lower case
|
||||
* `HELMFILE_DISABLE_RUNNER_UNIQUE_ID` - disable unique logging ID, expecting any non-empty value
|
||||
* `HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS` - disable insecure template functions, expecting `true` lower case
|
||||
* `HELMFILE_USE_HELM_STATUS_TO_CHECK_RELEASE_EXISTENCE` - expecting non-empty value to use `helm status` to check release existence, instead of `helm list` which is the default behaviour
|
||||
* `HELMFILE_EXPERIMENTAL` - enable experimental features, expecting `true` lower case
|
||||
* `HELMFILE_ENVIRONMENT` - specify [Helmfile environment](https://helmfile.readthedocs.io/en/latest/#environment), it has lower priority than CLI argument `--environment`
|
||||
* `HELMFILE_TEMPDIR` - specify directory to store temporary files
|
||||
* `HELMFILE_UPGRADE_NOTICE_DISABLED` - expecting any non-empty value to skip the check for the latest version of Helmfile in [helmfile version](https://helmfile.readthedocs.io/en/latest/#version)
|
||||
* `HELMFILE_GO_YAML_V3` - use *go.yaml.in/yaml/v3* instead of *go.yaml.in/yaml/v2*. It's `false` by default in Helmfile v0.x, and `true` in Helmfile v1.x.
|
||||
* `HELMFILE_V1MODE` - Helmfile v0.x behaves like v1.x with `true`, Helmfile v1.x behaves like v0.x with `false` as value
|
||||
* `HELMFILE_GOCCY_GOYAML` - use *goccy/go-yaml* instead of *gopkg.in/yaml.v2*. It's `false` by default in Helmfile v0.x and `true` by default for Helmfile v1.x.
|
||||
* `HELMFILE_CACHE_HOME` - specify directory to store cached files for remote operations
|
||||
* `HELMFILE_FILE_PATH` - specify the path to the helmfile.yaml file
|
||||
* `HELMFILE_INTERACTIVE` - enable interactive mode, expecting `true` lower case. The same as `--interactive` CLI flag
|
||||
|
||||
## CLI Reference
|
||||
|
||||
```
|
||||
Declaratively deploy your Kubernetes manifests, Kustomize configs, and Charts as Helm releases in one shot
|
||||
V1 mode = false
|
||||
YAML library = go.yaml.in/yaml/v3
|
||||
YAML library = gopkg.in/yaml.v2
|
||||
|
||||
Usage:
|
||||
helmfile [command]
|
||||
|
|
@ -610,7 +531,6 @@ Available Commands:
|
|||
lint Lint charts from state file (helm lint)
|
||||
list List releases defined in state file
|
||||
repos Add chart repositories defined in state file
|
||||
show-dag It prints a table with 3 columns, GROUP, RELEASE, and DEPENDENCIES. GROUP is the unsigned, monotonically increasing integer starting from 1. All the releases with the same GROUP are deployed concurrently. Everything in GROUP 2 starts being deployed only after everything in GROUP 1 got successfully deployed. RELEASE is the release that belongs to the GROUP. DEPENDENCIES is the list of releases that the RELEASE depends on. It should always be empty for releases in GROUP 1. DEPENDENCIES for a release in GROUP 2 should have some or all dependencies appeared in GROUP 1. It can be "some" because Helmfile simplifies the DAGs of releases into a DAG of groups, so that Helmfile always produce a single DAG for everything written in helmfile.yaml, even when there are technically two or more independent DAGs of releases in it.
|
||||
status Retrieve status of releases in state file
|
||||
sync Sync releases defined in state file
|
||||
template Template releases defined in state file
|
||||
|
|
@ -619,40 +539,36 @@ Available Commands:
|
|||
write-values Write values files for releases. Similar to `helmfile template`, write values files instead of manifests.
|
||||
|
||||
Flags:
|
||||
--allow-no-matching-release Do not exit with an error code if the provided selector has no matching releases.
|
||||
-c, --chart string Set chart. Uses the chart set in release by default, and is available in template as {{ .Chart }}
|
||||
--color Output with color
|
||||
--debug Enable verbose output for Helm and set log-level to debug, this disables --quiet/-q effect
|
||||
--disable-force-update do not force helm repos to update when executing "helm repo add"
|
||||
--enable-live-output Show live output from the Helm binary Stdout/Stderr into Helmfile own Stdout/Stderr.
|
||||
It only applies for the Helm CLI commands, Stdout/Stderr for Hooks are still displayed only when it's execution finishes.
|
||||
-e, --environment string specify the environment name. Overrides "HELMFILE_ENVIRONMENT" OS environment variable when specified. defaults to "default"
|
||||
-f, --file helmfile.yaml load config from file or directory. defaults to "helmfile.yaml" or "helmfile.yaml.gotmpl" or "helmfile.d" (means "helmfile.d/*.yaml" or "helmfile.d/*.yaml.gotmpl") in this preference. Specify - to load the config from the standard input.
|
||||
-b, --helm-binary string Path to the helm binary (default "helm")
|
||||
-h, --help help for helmfile
|
||||
-i, --interactive Request confirmation before attempting to modify clusters
|
||||
--kube-context string Set kubectl context. Uses current context by default
|
||||
-k, --kustomize-binary string Path to the kustomize binary (default "kustomize")
|
||||
--log-level string Set log level, default info (default "info")
|
||||
-n, --namespace string Set namespace. Uses the namespace set in the context by default, and is available in templates as {{ .Namespace }}
|
||||
--no-color Output without color
|
||||
-q, --quiet Silence output. Equivalent to log-level warn
|
||||
-l, --selector stringArray Only run using the releases that match labels. Labels can take the form of foo=bar or foo!=bar.
|
||||
A release must match all labels in a group in order to be used. Multiple groups can be specified at once.
|
||||
"--selector tier=frontend,tier!=proxy --selector tier=backend" will match all frontend, non-proxy releases AND all backend releases.
|
||||
The name of a release can be used as a label: "--selector name=myrelease"
|
||||
--skip-deps skip running "helm repo update" and "helm dependency build"
|
||||
--state-values-file stringArray specify state values in a YAML file. Used to override .Values within the helmfile template (not values template).
|
||||
--state-values-set stringArray set state values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template).
|
||||
--state-values-set-string stringArray set state STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template).
|
||||
--strip-args-values-on-exit-error Strip the potential secret values of the helm command args contained in a helmfile error message (default true)
|
||||
-v, --version version for helmfile
|
||||
--allow-no-matching-release Do not exit with an error code if the provided selector has no matching releases.
|
||||
-c, --chart string Set chart. Uses the chart set in release by default, and is available in template as {{ .Chart }}
|
||||
--color Output with color
|
||||
--debug Enable verbose output for Helm and set log-level to debug, this disables --quiet/-q effect
|
||||
--disable-force-update do not force helm repos to update when executing "helm repo add"
|
||||
--enable-live-output Show live output from the Helm binary Stdout/Stderr into Helmfile own Stdout/Stderr.
|
||||
It only applies for the Helm CLI commands, Stdout/Stderr for Hooks are still displayed only when it's execution finishes.
|
||||
-e, --environment string specify the environment name. Overrides "HELMFILE_ENVIRONMENT" OS environment variable when specified. defaults to "default"
|
||||
-f, --file helmfile.yaml load config from file or directory. defaults to "helmfile.yaml" or "helmfile.yaml.gotmpl" or "helmfile.d" (means "helmfile.d/*.yaml" or "helmfile.d/*.yaml.gotmpl") in this preference. Specify - to load the config from the standard input.
|
||||
-b, --helm-binary string Path to the helm binary (default "helm")
|
||||
-h, --help help for helmfile
|
||||
-i, --interactive Request confirmation before attempting to modify clusters
|
||||
--kube-context string Set kubectl context. Uses current context by default
|
||||
--log-level string Set log level, default info (default "info")
|
||||
-n, --namespace string Set namespace. Uses the namespace set in the context by default, and is available in templates as {{ .Namespace }}
|
||||
--no-color Output without color
|
||||
-q, --quiet Silence output. Equivalent to log-level warn
|
||||
-l, --selector stringArray Only run using the releases that match labels. Labels can take the form of foo=bar or foo!=bar.
|
||||
A release must match all labels in a group in order to be used. Multiple groups can be specified at once.
|
||||
"--selector tier=frontend,tier!=proxy --selector tier=backend" will match all frontend, non-proxy releases AND all backend releases.
|
||||
The name of a release can be used as a label: "--selector name=myrelease"
|
||||
--skip-deps skip running "helm repo update" and "helm dependency build"
|
||||
--state-values-file stringArray specify state values in a YAML file. Used to override .Values within the helmfile template (not values template).
|
||||
--state-values-set stringArray set state values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template).
|
||||
--strip-args-values-on-exit-error On exit error, strip the values of the args
|
||||
-v, --version version for helmfile
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
|
@ -668,25 +584,6 @@ 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
|
||||
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.
|
||||
|
||||
### deps
|
||||
|
|
@ -727,7 +624,7 @@ The `helmfile destroy` sub-command uninstalls and purges all the releases define
|
|||
`helmfile --interactive destroy` instructs Helmfile to request your confirmation before actually deleting releases.
|
||||
|
||||
`destroy` basically runs `helm uninstall --purge` on all the targeted releases. If you don't want purging, use `helmfile delete` instead.
|
||||
If `--skip-charts` flag is not set, destroy would prepare all releases, by fetching charts and templating them.
|
||||
If `--skip-charts` flag is not set, destory would prepare all releases, by fetching charts and templating them.
|
||||
|
||||
### delete (DEPRECATED)
|
||||
|
||||
|
|
@ -736,7 +633,7 @@ The `helmfile delete` sub-command deletes all the releases defined in the manife
|
|||
`helmfile --interactive delete` instructs Helmfile to request your confirmation before actually deleting releases.
|
||||
|
||||
Note that `delete` doesn't purge releases. So `helmfile delete && helmfile sync` results in sync failed due to that releases names are not deleted but preserved for future references. If you really want to remove releases for reuse, add `--purge` flag to run it like `helmfile delete --purge`.
|
||||
If `--skip-charts` flag is not set, destroy would prepare all releases, by fetching charts and templating them.
|
||||
If `--skip-charts` flag is not set, destory would prepare all releases, by fetching charts and templating them.
|
||||
|
||||
### secrets
|
||||
|
||||
|
|
@ -773,16 +670,6 @@ The `helmfile version` sub-command prints the version of Helmfile.Optional `-o`
|
|||
|
||||
default it will check for the latest version of Helmfile and print a tip if the current version is not the latest. To disable this behavior, set environment variable `HELMFILE_UPGRADE_NOTICE_DISABLED` to any non-empty value.
|
||||
|
||||
### show-dag
|
||||
|
||||
It prints a table with 3 columns, GROUP, RELEASE, and DEPENDENCIES.
|
||||
|
||||
GROUP is the unsigned, monotonically increasing integer starting from 1. All the releases with the same GROUP are deployed concurrently. Everything in GROUP 2 starts being deployed only after everything in GROUP 1 got successfully deployed.
|
||||
|
||||
RELEASE is the release that belongs to the GROUP.
|
||||
|
||||
DEPENDENCIES is the list of releases that the RELEASE depends on. It should always be empty for releases in GROUP 1. DEPENDENCIES for a release in GROUP 2 should have some or all dependencies appeared in GROUP 1. It can be "some" because Helmfile simplifies the DAGs of releases into a DAG of groups, so that Helmfile always produce a single DAG for everything written in helmfile.yaml, even when there are technically two or more independent DAGs of releases in it.
|
||||
|
||||
## Paths Overview
|
||||
|
||||
Using manifest files in conjunction with command line argument can be a bit confusing.
|
||||
|
|
@ -800,7 +687,7 @@ For additional context, take a look at [paths examples](paths.md).
|
|||
|
||||
A selector can be used to only target a subset of releases when running Helmfile. This is useful for large helmfiles with releases that are logically grouped together.
|
||||
|
||||
Labels are simple key value pairs that are an optional field of the release spec. When selecting by label, the search can be inverted. `tier!=backend` would match all releases that do NOT have the `tier: backend` label. `tier=frontend` would only match releases with the `tier: frontend` label.
|
||||
Labels are simple key value pairs that are an optional field of the release spec. When selecting by label, the search can be inverted. `tier!=backend` would match all releases that do NOT have the `tier: backend` label. `tier=fronted` would only match releases with the `tier: frontend` label.
|
||||
|
||||
Multiple labels can be specified using `,` as a separator. A release must match all selectors in order to be selected for the final helm command.
|
||||
|
||||
|
|
@ -948,7 +835,6 @@ proxy:
|
|||
When you want to customize the contents of `helmfile.yaml` or `values.yaml` files per environment, use this feature.
|
||||
|
||||
You can define as many environments as you want under `environments` in `helmfile.yaml`.
|
||||
`environments` section should be separated from `releases` with `---`.
|
||||
|
||||
The environment name defaults to `default`, that is, `helmfile sync` implies the `default` environment.
|
||||
The selected environment name can be referenced from `helmfile.yaml` and `values.yaml.gotmpl` by `{{ .Environment.Name }}`.
|
||||
|
|
@ -972,13 +858,9 @@ releases:
|
|||
# snip
|
||||
```
|
||||
|
||||
### Environment Values
|
||||
Helmfile supports 3 values languages :
|
||||
- Straight yaml
|
||||
- Go templates to generate straight yaml
|
||||
- HCL
|
||||
## Environment Values
|
||||
|
||||
Environment Values allows you to inject a set of values specific to the selected environment, into `values.yaml` templates.
|
||||
Environment Values allows you to inject a set of values specific to the selected environment, into values.yaml templates.
|
||||
Use it to inject common values from the environment to multiple values files, to make your configuration DRY.
|
||||
|
||||
Suppose you have three files `helmfile.yaml`, `production.yaml` and `values.yaml.gotmpl`:
|
||||
|
|
@ -1047,45 +929,7 @@ releases:
|
|||
...
|
||||
```
|
||||
|
||||
#### HCL specifications
|
||||
|
||||
Since Helmfile v0.164.0, HCL language is supported for environment values only.
|
||||
HCL values supports interpolations and sharing values across files
|
||||
|
||||
* Only `.hcl` suffixed files will be interpreted as is
|
||||
* Helmfile supports 2 differents blocks: `values` and `locals`
|
||||
* `values` block is a shared block where all values are accessible everywhere in all loaded files
|
||||
* `locals` block can't reference external values apart from the ones in the block itself, and where its defined values are only accessible in its local file
|
||||
* Only values in `values` blocks are made available to the final root `.Values` (e.g : ` values { myvar = "var" }` is accessed through `{{ .Values.myvar }}`)
|
||||
* There can only be 1 `locals` block per file
|
||||
* Helmfile hcl `values` are referenced using the `hv` accessor.
|
||||
* Helmfile hcl `locals` are referenced using the `local` accessor.
|
||||
* Duplicated variables across .hcl `values` blocks are forbidden (An error will pop up specifying where are the duplicates)
|
||||
* All cty [standard library functions](`https://pkg.go.dev/github.com/zclconf/go-cty@v1.14.3/cty/function/stdlib`) are available and custom functions could be created in the future
|
||||
|
||||
Consider the following example :
|
||||
|
||||
```terraform
|
||||
# values1.hcl
|
||||
locals {
|
||||
hostname = "host1"
|
||||
}
|
||||
values {
|
||||
domain = "DEV.EXAMPLE.COM"
|
||||
hostnameV1 = "${local.hostname}.${lower(hv.domain)}" # "host1.dev.example.com"
|
||||
}
|
||||
```
|
||||
```terraform
|
||||
# values2.hcl
|
||||
locals {
|
||||
hostname = "host2"
|
||||
}
|
||||
|
||||
values {
|
||||
hostnameV2 = "${local.hostname}.${hv.domain}" # "host2.DEV.EXAMPLE.COM"
|
||||
}
|
||||
```
|
||||
#### Note on Environment.Values vs Values
|
||||
### Note on Environment.Values vs Values
|
||||
|
||||
The `{{ .Values.foo }}` syntax is the recommended way of using environment values.
|
||||
|
||||
|
|
@ -1094,7 +938,37 @@ This is still working but is **deprecated** and the new `{{ .Values.foo }}` synt
|
|||
|
||||
You can read more infos about the feature proposal [here](https://github.com/roboll/helmfile/issues/640).
|
||||
|
||||
### Environment Secrets
|
||||
### Loading remote Environment values files
|
||||
|
||||
Since Helmfile v0.118.8, you can use `go-getter`-style URLs to refer to remote values files:
|
||||
|
||||
```yaml
|
||||
environments:
|
||||
cluster-azure-us-west:
|
||||
values:
|
||||
- git::https://git.company.org/helmfiles/global/azure.yaml?ref=master
|
||||
- git::https://git.company.org/helmfiles/global/us-west.yaml?ref=master
|
||||
- git::https://gitlab.com/org/repository-name.git@/config/config.test.yaml?ref=main # Public Gilab Repo
|
||||
cluster-gcp-europe-west:
|
||||
values:
|
||||
- git::https://git.company.org/helmfiles/global/gcp.yaml?ref=master
|
||||
- git::https://git.company.org/helmfiles/global/europe-west.yaml?ref=master
|
||||
- git::https://ci:{{ env "CI_JOB_TOKEN" }}@gitlab.com/org/repository-name.git@/config.dev.yaml?ref={{ env "APP_COMMIT_SHA" }} # Private Gitlab Repo
|
||||
staging:
|
||||
values:
|
||||
- git::https://{{ env "GITHUB_PAT" }}@github.com/[$GITHUB_ORGorGITHUB_USER]/repository-name.git@/values.dev.yaml?ref=main #Github Private repo
|
||||
- http://$HOSTNAME/artifactory/example-repo-local/test.tgz@values.yaml #Artifactory url
|
||||
---
|
||||
|
||||
releases:
|
||||
- ...
|
||||
```
|
||||
|
||||
For more information about the supported protocols see: [go-getter Protocol-Specific Options](https://github.com/hashicorp/go-getter#protocol-specific-options-1).
|
||||
|
||||
This is particularly useful when you co-locate helmfiles within your project repo but want to reuse the definitions in a global repo.
|
||||
|
||||
## Environment Secrets
|
||||
|
||||
Environment Secrets *(not to be confused with Kubernetes Secrets)* are encrypted versions of `Environment Values`.
|
||||
You can list any number of `secrets.yaml` files created using `helm secrets` or `sops`, so that
|
||||
|
|
@ -1135,7 +1009,7 @@ Then the environment secret `foo.bar` can be referenced by the below template ex
|
|||
{{ .Values.foo.bar }}
|
||||
```
|
||||
|
||||
#### Loading remote Environment secrets files
|
||||
### Loading remote Environment secrets files
|
||||
|
||||
Since Helmfile v0.149.0, you can use `go-getter`-style URLs to refer to remote secrets files, the same way as in values files:
|
||||
```yaml
|
||||
|
|
@ -1150,91 +1024,6 @@ environments:
|
|||
- http://$HOSTNAME/artifactory/example-repo-local/test.tgz@environments/production.secret.yaml
|
||||
```
|
||||
|
||||
### Loading remote Environment values files
|
||||
|
||||
Since Helmfile v0.118.8, you can use `go-getter`-style URLs to refer to remote values files:
|
||||
|
||||
```yaml
|
||||
environments:
|
||||
cluster-azure-us-west:
|
||||
values:
|
||||
- git::https://git.company.org/helmfiles/global/azure.yaml?ref=master
|
||||
- git::https://git.company.org/helmfiles/global/us-west.yaml?ref=master
|
||||
- git::https://gitlab.com/org/repository-name.git@/config/config.test.yaml?ref=main # Public Gilab Repo
|
||||
cluster-gcp-europe-west:
|
||||
values:
|
||||
- git::https://git.company.org/helmfiles/global/gcp.yaml?ref=master
|
||||
- git::https://git.company.org/helmfiles/global/europe-west.yaml?ref=master
|
||||
- git::https://ci:{{ env "CI_JOB_TOKEN" }}@gitlab.com/org/repository-name.git@/config.dev.yaml?ref={{ env "APP_COMMIT_SHA" }} # Private Gitlab Repo
|
||||
staging:
|
||||
values:
|
||||
- git::https://{{ env "GITHUB_PAT" }}@github.com/[$GITHUB_ORGorGITHUB_USER]/repository-name.git@/values.dev.yaml?ref=main #Github Private repo
|
||||
- http://$HOSTNAME/artifactory/example-repo-local/test.tgz@values.yaml #Artifactory url
|
||||
---
|
||||
|
||||
releases:
|
||||
- ...
|
||||
```
|
||||
|
||||
Since Helmfile v0.158.0, support more protocols, such as: s3, https, http
|
||||
```
|
||||
values:
|
||||
- s3::https://helm-s3-values-example.s3.us-east-2.amazonaws.com/values.yaml
|
||||
- s3://helm-s3-values-example/subdir/values.yaml
|
||||
- https://john:doe@helm-s3-values-example.s3.us-east-2.amazonaws.com/values.yaml
|
||||
- http://helm-s3-values-example.s3.us-east-2.amazonaws.com/values.yaml
|
||||
```
|
||||
|
||||
For more information about the supported protocols see: [go-getter Protocol-Specific Options](https://github.com/hashicorp/go-getter#protocol-specific-options-1).
|
||||
|
||||
This is particularly useful when you co-locate helmfiles within your project repo but want to reuse the definitions in a global repo.
|
||||
|
||||
### Environment values precedence
|
||||
With the introduction of HCL, a new value precedence was introduced over environment values.
|
||||
Here is the order of precedence from least to greatest (the last one overrides all others)
|
||||
1. `yaml` / `yaml.gotmpl`
|
||||
2. `hcl`
|
||||
3. `yaml` secrets
|
||||
|
||||
Example:
|
||||
|
||||
---
|
||||
|
||||
```yaml
|
||||
# values1.yaml
|
||||
domain: "dev.example.com"
|
||||
```
|
||||
|
||||
```terraform
|
||||
# values2.hcl
|
||||
values {
|
||||
domain = "overdev.example.com"
|
||||
willBeOverriden = "override_me"
|
||||
}
|
||||
```
|
||||
|
||||
```yaml
|
||||
# secrets.yml (assuming this one has been encrypted)
|
||||
willBeOverriden: overrided
|
||||
```
|
||||
|
||||
```
|
||||
# helmfile.yaml.gotmpl
|
||||
environments:
|
||||
default:
|
||||
values:
|
||||
- value1.yaml
|
||||
- value2.hcl
|
||||
secrets:
|
||||
- secrets.yml
|
||||
---
|
||||
releases:
|
||||
- name: random-release
|
||||
[...]
|
||||
values:
|
||||
domain: "{{ .Values.domain }}" # == "overdev.example.com"
|
||||
willBeOverriden: "{{ .Values.willBeOverriden }}" # == "overrided"
|
||||
```
|
||||
## DAG-aware installation/deletion ordering with `needs`
|
||||
|
||||
`needs` controls the order of the installation/deletion of the release:
|
||||
|
|
@ -1399,7 +1188,7 @@ helmfiles:
|
|||
- name=prometheus
|
||||
- tier=frontend
|
||||
- path: apps/b-helmfile.yaml # no selector, so all releases are used
|
||||
selectors: []
|
||||
selectors: []
|
||||
- path: apps/c-helmfile.yaml # parent selector to be used or cli selector for the initial helmfile
|
||||
selectorsInherited: true
|
||||
```
|
||||
|
|
@ -1710,9 +1499,6 @@ Use it when you're running `helmfile` manually on your local machine or a kind o
|
|||
|
||||
For your local use-case, aliasing it like `alias hi='helmfile --interactive'` would be convenient.
|
||||
|
||||
Another way to use it is to set the environment variable `HELMFILE_INTERACTIVE=true` to enable the interactive mode by default.
|
||||
Anything other than `true` will disable the interactive mode. The precedence has the `--interactive` flag.
|
||||
|
||||
## Running Helmfile without an Internet connection
|
||||
|
||||
Once you download all required charts into your machine, you can run `helmfile sync --skip-deps` to deploy your apps.
|
||||
|
|
|
|||
|
|
@ -4,22 +4,6 @@ I'd like to make 3 breaking changes to Helmfile and mark it as 1.0, so that we c
|
|||
|
||||
Note that every breaking change should have an easy alternative way to achieve the same goal achieved using the removed functionality.
|
||||
|
||||
## Backward compatibility
|
||||
|
||||
v1 is backward-compatible with v0.x, except for the following breaking changes.
|
||||
|
||||
Each breaking change has an easy alternative way to achieve the same goal achieved using the removed functionality.
|
||||
|
||||
We also provide the alternative way in the latest v0.x release before v1.0. That way you can start using the alternative way today and be ready for v1.0. Note that in v0.x, some of those alternative ways are enabled only when `HELMFILE_V1MODE=true` is set.
|
||||
|
||||
> Context:
|
||||
>
|
||||
> Even though Helmfile had been used in production environments [across multiple organizations](USERS.md), it had been considered to be in its early stage of development, hence versioned 0.x.
|
||||
>
|
||||
> Helmfile complies to Semantic Versioning 2.0.0 in which v0.x means that there could be backward-incompatible changes for every release. However, Helmfile has been very conservative about breaking changes, and we had no breaking change for a year or so before start thinking about v1.
|
||||
>
|
||||
> That said, you can expect Helmfile v1 to be backward-compatible as much as it was in v0.x.
|
||||
|
||||
## The changes in 1.0
|
||||
|
||||
1. [Forbid the use of `environments` and `releases` within a single helmfile.yaml.gotmpl part](#forbid-the-use-of-environments-and-releases-within-a-single-helmfileyamlgotmpl-part)
|
||||
|
|
@ -27,8 +11,6 @@ We also provide the alternative way in the latest v0.x release before v1.0. That
|
|||
3. [Remove the `--args` flag from the `helmfile` command](#remove-the---args-flag-from-the-helmfile-command)
|
||||
4. [Remove `HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS` in favor of `HELMFILE_DISABLE_INSECURE_FEATURES`](#remove-helmfile_skip_insecure_template_functions-in-favor-of-helmfile_disable_insecure_features)
|
||||
5. [The long deprecated `charts.yaml` has been finally removed](#the-long-deprecated-chartsyaml-has-been-finally-removed)
|
||||
6. [List experimental features](#list-experimental-features)
|
||||
7. [Remove charts and delete sub-commands](#remove-charts-and-delete-subcommands)
|
||||
|
||||
### Forbid the use of `environments` and `releases` within a single helmfile.yaml.gotmpl part
|
||||
|
||||
|
|
@ -93,27 +75,13 @@ We also provide the alternative way in the latest v0.x release before v1.0. That
|
|||
|
||||
### Remove `HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS` in favor of `HELMFILE_DISABLE_INSECURE_FEATURES`
|
||||
|
||||
- This option didn't make much sense in practice. Generally, you'd want to disable all the insecure features altogether to make your deployment secure, or not disable any features. Disabling all is already possible via `HELMFILE_DISABLE_INSECURE_FEATURES `. In addition, `HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS` literally made every insecure template function to silently skipped without any error or warning, which made debugging unnecessarily hard when the user accidentally used an insecure function.
|
||||
- This option didn't make much sense in practical. Generally, you'd want to disable all the insecure features altogether to make your deployment secure, or not disable any features. Disabling all is already possible via `HELMFILE_DISABLE_INSECURE_FEATURES `. In addition, `HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS` literally made every insecure template function to silently skipped without any error or warning, which made debugging unnecessarily hard when the user accidentally used an insecure function.
|
||||
- See https://github.com/helmfile/helmfile/pull/564 for more context.
|
||||
|
||||
### The long deprecated `charts.yaml` has been finally removed
|
||||
|
||||
Helmfile used to load `helmfile.yaml` or `charts.yaml` when you omitted the `-f` flag. `charts.yaml` has been deprecated for a long time but never been removed. We take v1 as a chance to finally remove it.
|
||||
|
||||
### List experimental features
|
||||
|
||||
We have some experimental features that are not stable yet. We should list them in a list and mark them as experimental.
|
||||
|
||||
In Helmfile v1.x, all features should be backward-compatible within v1.x as we follow semver. We can't fix features in a backward incompatible way by default. To do so, we need a list of experimental features and say "anything in the experimentals can be modified backward-incompatible ways", and include features that are consireded experimental into the list beforehand.
|
||||
|
||||
Why now?
|
||||
|
||||
In Helmfile v0.x, all features considered experimental as we follow semver. However, we "ended up" preserving backward-compatibility within v0 and between v0 and v1 "by chance". This doesn't mean anything
|
||||
introduced in v0 is stable. For example, we might have some features implemented in a very later stage of v0 that are not stable yet. We should mark them as experimental, or we can't fix them in a backward-incompatible way in v1.x. That's why we need to list experimental features now.
|
||||
|
||||
### remove-charts-and-delete-subcommands
|
||||
Now we remove `helmfile charts` and `helmfile delete` subcommands. you can use `helmfile destroy` and `helmfile sync` instead.
|
||||
|
||||
## After 1.0
|
||||
|
||||
We won't add any backward-incompatible changes while in 1.x, as long as it's inevitable to fix unseen important bug(s).
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ To fetch single key from remote secret storage you can use `fetchSecretValue` te
|
|||
|
||||
repositories:
|
||||
- name: stable
|
||||
url: https://charts.helm.sh/stable
|
||||
---
|
||||
url: https://kubernetes-charts.storage.googleapis.com
|
||||
|
||||
environments:
|
||||
default:
|
||||
values:
|
||||
|
|
@ -55,3 +55,4 @@ service:
|
|||
password: pass
|
||||
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
Babel==2.17.0
|
||||
Babel==2.9.1
|
||||
click==8.1.2
|
||||
ghp-import==2.0.2
|
||||
gitdb==4.0.9
|
||||
GitPython==3.1.41
|
||||
GitPython==3.1.30
|
||||
importlib-metadata==4.11.3
|
||||
Jinja2==3.1.6
|
||||
Markdown==3.6
|
||||
Jinja2==3.1.1
|
||||
Markdown==3.3.6
|
||||
MarkupSafe==2.1.1
|
||||
mergedeep==1.3.4
|
||||
mkdocs==1.6.0
|
||||
mkdocs==1.3.0
|
||||
mkdocs-git-revision-date-localized-plugin==1.0.1
|
||||
packaging==21.3
|
||||
pyparsing==3.0.7
|
||||
python-dateutil==2.8.2
|
||||
pytz==2022.1
|
||||
PyYAML==6.0.2
|
||||
PyYAML==6.0
|
||||
pyyaml_env_tag==0.1
|
||||
six==1.16.0
|
||||
smmap==5.0.0
|
||||
watchdog==2.1.7
|
||||
zipp==3.19.1
|
||||
zipp==3.7.0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Shared Configuration Across Teams
|
||||
|
||||
Assume you have two or more teams, each work for a different internal or external service, like:
|
||||
Assume you have a two or more teams, each works for a different internal or external service, like:
|
||||
|
||||
- Product 1
|
||||
- Product 2
|
||||
|
|
@ -30,7 +30,7 @@ releases:
|
|||
# snip
|
||||
```
|
||||
|
||||
This works, but what if you wanted to a separate cluster per service to achieve a smaller blast radius?
|
||||
This works, but what if you wanted to a separate cluster per service to achieve smaller blast radius?
|
||||
|
||||
Let's start by creating a `helmfile.yaml` for each service.
|
||||
|
||||
|
|
|
|||
|
|
@ -32,20 +32,6 @@ The `envExec` function allows you to run a command with environment variables de
|
|||
{{ $cmdOutpot := envExec (dict "envKey" "envValue") "./mycmd" (list "arg1" "arg2" "--flag1") }}
|
||||
```
|
||||
|
||||
#### `isFile`
|
||||
The `isFile` function allows you to check if a file exists. On failure, the template rendering will fail with an error message.
|
||||
|
||||
```yaml
|
||||
{{ if isFile "./myfile" }}
|
||||
```
|
||||
|
||||
#### `isDir`
|
||||
The `isDir` function allows you to check if a directory exists. On failure, the template rendering will fail with an error message.
|
||||
|
||||
```yaml
|
||||
{{ if isDir "./mydirectory" }}
|
||||
```
|
||||
|
||||
#### `readFile`
|
||||
The `readFile` function allows you to read a file and return its content as the function output. On failure, the template rendering will fail with an error message.
|
||||
|
||||
|
|
@ -100,14 +86,14 @@ The `setValueAtPath` function allows you to set a value at a path. When has fail
|
|||
```
|
||||
|
||||
#### `get`
|
||||
The `get` function allows you to get a value at a path. you can set a default value when the path is not found. When has failed, the template rendering will fail with an error message.
|
||||
The `get` function allows you to get a value at a path. when defaultValue not set. It will return nil. When has failed, the template rendering will fail with an error message.
|
||||
|
||||
```yaml
|
||||
{{ $Getvalue := $value | get "path.key" "defaultValue" }}
|
||||
```
|
||||
|
||||
#### `getOrNil`
|
||||
The `getOrNil` function allows you to get a value at a path. it will return nil when the value of path is not found. When has failed, the template rendering will fail with an error message.
|
||||
The `getOrNil` function allows you to get a value at a path. when defaultValue not set. It will return nil. When has failed, the template rendering will fail with an error message.
|
||||
|
||||
```yaml
|
||||
{{ $GetOrNlvalue := $value | getOrNil "path.key" }}
|
||||
|
|
@ -140,11 +126,3 @@ The `expandSecretRefs` function takes an object as the argument and expands ever
|
|||
```yaml
|
||||
{{ $expandSecretRefs := $value | expandSecretRefs }}
|
||||
```
|
||||
|
||||
#### `include`
|
||||
The 'include' function allows including and rendering nested templates. The function returns the created template or an error if any occurred. It will load functions from `_*.tpl` files in the directory where the helmfile.yaml is located.
|
||||
|
||||
For nested helmfile.yaml files, it will load `_*.tpl` files in the directory where each nested helmfile.yaml is located. example: [include](https://github.com/helmfile/helmfile/tree/main/test/integration/test-cases/include-template-func/input)
|
||||
```yaml
|
||||
{{ include "my-template" . }}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -104,8 +104,6 @@ releases:
|
|||
version: 0.3.2
|
||||
inherit:
|
||||
- template: default
|
||||
except:
|
||||
- secrets
|
||||
- name: kubernetes-dashboard
|
||||
version: 0.10.0
|
||||
inherit:
|
||||
|
|
@ -155,7 +153,7 @@ Thus we added a new way for inheritance, which uses the `inherit` field we intro
|
|||
|
||||
See [issue helmfile/helmfile#435](https://github.com/helmfile/helmfile/issues/435#issuecomment-1362177510) for more context.
|
||||
|
||||
You might also find [issue roboll/helmfile#428](https://github.com/roboll/helmfile/issues/428) useful for more context on how we originally designed the release template and what it's supposed to solve.
|
||||
You might also find [issue roboll/helmfile#428](https://github.com/roboll/helmfile/issues/428) useful for more context on how we originally designed the relase template and what it's supposed to solve.
|
||||
|
||||
## Layering Release Values
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ releases:
|
|||
# DB host, port, and connection opts for the environment
|
||||
values:
|
||||
- "deploy/environments/{{ env "RAILS_ENV" }}/values.yaml"
|
||||
# DB username and password encrypted with helm-secrets (getsops/sops)
|
||||
# DB username and password encrypted with helm-secrets(mozilla/sops)
|
||||
secrets:
|
||||
- "deploy/environments/{{ env "RAILS_ENV" }}/secrets.yaml"
|
||||
```
|
||||
|
|
|
|||
456
go.mod
456
go.mod
|
|
@ -1,326 +1,250 @@
|
|||
module github.com/helmfile/helmfile
|
||||
|
||||
go 1.24.6
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.2
|
||||
github.com/Masterminds/semver/v3 v3.4.0
|
||||
github.com/Masterminds/sprig/v3 v3.3.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.31.15
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.89.0
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
|
||||
github.com/go-test/deep v1.1.1
|
||||
github.com/Masterminds/semver/v3 v3.2.1
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/go-test/deep v1.1.0
|
||||
github.com/goccy/go-yaml v1.11.0
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/gosuri/uitable v0.0.4
|
||||
github.com/hashicorp/go-getter v1.8.2
|
||||
github.com/hashicorp/hcl/v2 v2.24.0
|
||||
github.com/helmfile/chartify v0.25.0
|
||||
github.com/helmfile/vals v0.42.4
|
||||
github.com/spf13/cobra v1.10.1
|
||||
github.com/spf13/pflag v1.0.10
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/hashicorp/go-getter v1.7.1
|
||||
github.com/helmfile/chartify v0.14.0
|
||||
github.com/helmfile/vals v0.25.0
|
||||
github.com/imdario/mergo v0.3.16
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/tatsushid/go-prettytable v0.0.0-20141013043238-ed2d14c29939
|
||||
github.com/tj/assert v0.0.3
|
||||
github.com/variantdev/dag v1.1.0
|
||||
github.com/zclconf/go-cty v1.17.0
|
||||
github.com/zclconf/go-cty-yaml v1.1.0
|
||||
go.szostok.io/version v1.2.0
|
||||
go.uber.org/zap v1.27.0
|
||||
go.yaml.in/yaml/v2 v2.4.3
|
||||
go.yaml.in/yaml/v3 v3.0.4
|
||||
golang.org/x/sync v0.17.0
|
||||
golang.org/x/term v0.36.0
|
||||
helm.sh/helm/v3 v3.19.0
|
||||
k8s.io/apimachinery v0.34.1
|
||||
go.uber.org/multierr v1.11.0
|
||||
go.uber.org/zap v1.24.0
|
||||
golang.org/x/sync v0.3.0
|
||||
golang.org/x/term v0.9.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
helm.sh/helm/v3 v3.12.1
|
||||
k8s.io/apimachinery v0.27.3
|
||||
)
|
||||
|
||||
replace gopkg.in/yaml.v3 => github.com/colega/go-yaml-yaml v0.0.0-20220720070545-aaba007ebc22
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.121.6 // indirect
|
||||
cloud.google.com/go/iam v1.5.2 // indirect
|
||||
cloud.google.com/go/storage v1.57.0 // indirect
|
||||
filippo.io/age v1.2.1 // indirect
|
||||
cloud.google.com/go v0.110.0 // indirect
|
||||
cloud.google.com/go/compute v1.18.0 // indirect
|
||||
cloud.google.com/go/iam v0.12.0 // indirect
|
||||
cloud.google.com/go/storage v1.28.1 // indirect
|
||||
filippo.io/age v1.0.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go v66.0.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 v0.11.27 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 // indirect
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/a8m/envsubst v1.4.3 // indirect
|
||||
github.com/a8m/envsubst v1.3.0 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.122 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
github.com/fatih/color v1.18.0
|
||||
github.com/fujiwara/tfstate-lookup v1.7.1 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/fujiwara/tfstate-lookup v1.1.1 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
|
||||
github.com/goware/prefixer v0.0.0-20160118172347-395022866408 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
github.com/hashicorp/go-slug v0.16.4 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
|
||||
github.com/hashicorp/go-tfe v1.84.0 // indirect
|
||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.1-vault-7 // indirect
|
||||
github.com/hashicorp/jsonapi v1.4.3-0.20250220162346-81a76b606f3e // indirect
|
||||
github.com/hashicorp/vault/api v1.22.0 // indirect
|
||||
github.com/huandu/xstrings v1.5.0 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-slug v0.8.1 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
|
||||
github.com/hashicorp/go-tfe v1.2.0 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d // indirect
|
||||
github.com/hashicorp/vault/api v1.5.0 // indirect
|
||||
github.com/hashicorp/vault/sdk v0.4.1 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/itchyny/gojq v0.12.16 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/itchyny/gojq v0.12.11 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/klauspost/compress v1.16.0 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.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/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/otiai10/copy v1.14.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/otiai10/copy v1.1.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/ulikunitz/xz v0.5.15 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/ulikunitz/xz v0.5.10 // indirect
|
||||
go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a // indirect
|
||||
go.mozilla.org/sops/v3 v3.7.3 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
golang.org/x/net v0.44.0 // indirect
|
||||
golang.org/x/oauth2 v0.31.0 // indirect
|
||||
golang.org/x/sys v0.37.0 // indirect
|
||||
golang.org/x/text v0.29.0 // indirect
|
||||
golang.org/x/time v0.13.0 // indirect
|
||||
google.golang.org/api v0.252.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/grpc v1.75.1 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/yaml v1.6.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/oauth2 v0.5.0 // indirect
|
||||
golang.org/x/sys v0.9.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/api v0.110.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
|
||||
google.golang.org/grpc v1.53.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/urfave/cli.v1 v1.20.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
al.essio.dev/pkg/shellescape v1.6.0 // indirect
|
||||
cel.dev/expr v0.24.0 // indirect
|
||||
cloud.google.com/go/auth v0.17.0 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||
cloud.google.com/go/kms v1.23.0 // indirect
|
||||
cloud.google.com/go/longrunning v0.6.7 // indirect
|
||||
cloud.google.com/go/monitoring v1.24.2 // 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/onepassword-sdk-go v0.3.1 // indirect
|
||||
github.com/AlecAivazis/survey/v2 v2.3.6 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.12.0 // 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.8.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys 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/storage/azblob v1.1.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 // indirect
|
||||
github.com/DopplerHQ/cli v0.5.11-0.20230908185655-7aef4713e1a4 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.53.0 // indirect
|
||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||
github.com/Masterminds/squirrel v1.5.4 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
||||
github.com/agext/levenshtein v1.2.3 // indirect
|
||||
github.com/antchfx/jsonquery v1.3.6 // indirect
|
||||
github.com/antchfx/xpath v1.3.5 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/secretmanager v1.10.0 // indirect
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.10.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5 // indirect
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.39.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.18.19 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.45.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.65.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.29.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.38.9 // indirect
|
||||
github.com/aws/smithy-go v1.23.1 // indirect
|
||||
github.com/armon/go-metrics v0.3.10 // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.17.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.23 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.54 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.29 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.23 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.30 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.21 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.24 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.23 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.23 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.30.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.12.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.18.4 // indirect
|
||||
github.com/aws/smithy-go v1.13.5 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.2 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect
|
||||
github.com/containerd/containerd v1.7.28 // indirect
|
||||
github.com/containerd/errdefs v0.3.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/platforms v0.2.1 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||
github.com/cyberark/conjur-api-go v0.13.7 // indirect
|
||||
github.com/danieljoos/wincred v1.2.2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/containerd/containerd v1.7.0 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
|
||||
github.com/docker/cli v20.10.21+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.2+incompatible // indirect
|
||||
github.com/docker/docker v20.10.24+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
|
||||
github.com/evanphx/json-patch v5.9.11+incompatible // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||
github.com/extism/go-sdk v1.7.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
github.com/getsops/gopgagent v0.0.0-20241224165529-7044f28e491e // indirect
|
||||
github.com/getsops/sops/v3 v3.11.0 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
||||
github.com/go-errors/errors v1.4.2 // indirect
|
||||
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.1 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/analysis v0.24.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.22.1 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.2 // indirect
|
||||
github.com/go-openapi/loads v0.23.1 // indirect
|
||||
github.com/go-openapi/runtime v0.29.0 // indirect
|
||||
github.com/go-openapi/spec v0.22.0 // indirect
|
||||
github.com/go-openapi/strfmt v0.24.0 // indirect
|
||||
github.com/go-openapi/swag v0.24.1 // indirect
|
||||
github.com/go-openapi/swag/cmdutils v0.24.0 // indirect
|
||||
github.com/go-openapi/swag/conv v0.25.1 // indirect
|
||||
github.com/go-openapi/swag/fileutils v0.25.1 // indirect
|
||||
github.com/go-openapi/swag/jsonname v0.25.1 // indirect
|
||||
github.com/go-openapi/swag/jsonutils v0.25.1 // indirect
|
||||
github.com/go-openapi/swag/loading v0.25.1 // indirect
|
||||
github.com/go-openapi/swag/mangling v0.25.1 // indirect
|
||||
github.com/go-openapi/swag/netutils v0.24.0 // indirect
|
||||
github.com/go-openapi/swag/stringutils v0.25.1 // indirect
|
||||
github.com/go-openapi/swag/typeutils v0.25.1 // indirect
|
||||
github.com/go-openapi/swag/yamlutils v0.25.1 // indirect
|
||||
github.com/go-openapi/validate v0.25.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/goccy/go-yaml v1.17.1 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.1 // indirect
|
||||
github.com/go-openapi/swag v0.22.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/gnostic-models v0.7.0 // indirect
|
||||
github.com/google/go-jsonnet v0.20.0 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/gnostic v0.5.7-v3refs // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // 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.8 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
|
||||
github.com/hashicorp/go-hclog v1.2.0 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-plugin v1.4.3 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.3 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/hcp-sdk-go v0.162.0 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect
|
||||
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f // indirect
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca // indirect
|
||||
github.com/itchyny/timefmt-go v0.1.6 // indirect
|
||||
github.com/jmoiron/sqlx v1.4.0 // indirect
|
||||
github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef // indirect
|
||||
github.com/itchyny/timefmt-go v0.1.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||
github.com/moby/spdystream v0.5.0 // indirect
|
||||
github.com/moby/term v0.5.2 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/muesli/termenv v0.15.1 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/otiai10/mint v1.6.3 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rubenv/sql-migrate v1.8.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33 // 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/wazero v1.9.0 // indirect
|
||||
github.com/tidwall/gjson v1.18.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
|
||||
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
|
||||
github.com/urfave/cli v1.22.17 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
github.com/yandex-cloud/go-genproto v0.29.0 // indirect
|
||||
github.com/yandex-cloud/go-sdk v0.22.0 // indirect
|
||||
github.com/zalando/go-keyring v0.2.6 // indirect
|
||||
github.com/zeebo/errs v1.4.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.17.4 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.36.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.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.42.0 // indirect
|
||||
golang.org/x/mod v0.27.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
gopkg.in/gookit/color.v1 v1.1.6 // indirect
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.37.0 // indirect
|
||||
github.com/prometheus/procfs v0.8.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/xlab/treeprint v1.1.0 // indirect
|
||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
go.uber.org/goleak v1.1.12 // indirect
|
||||
golang.org/x/crypto v0.7.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/api v0.34.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.34.0 // indirect
|
||||
k8s.io/cli-runtime v0.34.0 // indirect
|
||||
k8s.io/client-go v0.34.1 // indirect
|
||||
k8s.io/component-base v0.34.0 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
|
||||
k8s.io/kubectl v0.34.0 // indirect
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
|
||||
oras.land/oras-go/v2 v2.6.0 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.20.1 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
|
||||
k8s.io/api v0.27.2 // indirect
|
||||
k8s.io/cli-runtime v0.27.2 // indirect
|
||||
k8s.io/client-go v0.27.2 // indirect
|
||||
k8s.io/klog/v2 v2.90.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
|
||||
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect
|
||||
oras.land/oras-go v1.2.2 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.13.2 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.14.1 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,15 +17,13 @@ nav:
|
|||
- Home: index.md
|
||||
- Getting Started:
|
||||
- Paths Overview: paths.md
|
||||
- Templating Funcs: templating_funcs.md
|
||||
- HCL Funcs: hcl_funcs.md
|
||||
- Templating Funs: templating_funcs.md
|
||||
- Built-in Objects: builtin-objects.md
|
||||
- Advanced Features:
|
||||
- Best Practices Guide: writing-helmfile.md
|
||||
- Advanced Features: advanced-features.md
|
||||
- Secrets: remote-secrets.md
|
||||
- Shared Configuration Across Teams: shared-configuration-across-teams.md
|
||||
- Experimental Features: experimental-features.md
|
||||
- About:
|
||||
- Users: users.md
|
||||
- License: license.md
|
||||
|
|
|
|||
391
pkg/app/app.go
391
pkg/app/app.go
|
|
@ -15,11 +15,11 @@ import (
|
|||
"go.uber.org/zap"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/argparser"
|
||||
"github.com/helmfile/helmfile/pkg/envvar"
|
||||
"github.com/helmfile/helmfile/pkg/filesystem"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/plugins"
|
||||
"github.com/helmfile/helmfile/pkg/remote"
|
||||
"github.com/helmfile/helmfile/pkg/runtime"
|
||||
"github.com/helmfile/helmfile/pkg/state"
|
||||
)
|
||||
|
||||
|
|
@ -30,13 +30,11 @@ var Cancel goContext.CancelFunc
|
|||
type App struct {
|
||||
OverrideKubeContext string
|
||||
OverrideHelmBinary string
|
||||
OverrideKustomizeBinary string
|
||||
EnableLiveOutput bool
|
||||
StripArgsValuesOnExitError bool
|
||||
DisableForceUpdate bool
|
||||
|
||||
Logger *zap.SugaredLogger
|
||||
Kubeconfig string
|
||||
Env string
|
||||
Namespace string
|
||||
Chart string
|
||||
|
|
@ -76,12 +74,10 @@ func New(conf ConfigProvider) *App {
|
|||
return Init(&App{
|
||||
OverrideKubeContext: conf.KubeContext(),
|
||||
OverrideHelmBinary: conf.HelmBinary(),
|
||||
OverrideKustomizeBinary: conf.KustomizeBinary(),
|
||||
EnableLiveOutput: conf.EnableLiveOutput(),
|
||||
StripArgsValuesOnExitError: conf.StripArgsValuesOnExitError(),
|
||||
DisableForceUpdate: conf.DisableForceUpdate(),
|
||||
Logger: conf.Logger(),
|
||||
Kubeconfig: conf.Kubeconfig(),
|
||||
Env: conf.Env(),
|
||||
Namespace: conf.Namespace(),
|
||||
Chart: conf.Chart(),
|
||||
|
|
@ -121,7 +117,19 @@ func (a *App) Init(c InitConfigProvider) error {
|
|||
|
||||
func (a *App) Deps(c DepsConfigProvider) error {
|
||||
return a.ForEachState(func(run *Run) (_ bool, errs []error) {
|
||||
errs = run.Deps(c)
|
||||
prepErr := run.withPreparedCharts("deps", state.ChartPrepareOptions{
|
||||
SkipRepos: c.SkipRepos(),
|
||||
SkipDeps: true,
|
||||
SkipResolve: true,
|
||||
Concurrency: c.Concurrency(),
|
||||
}, func() {
|
||||
errs = run.Deps(c)
|
||||
})
|
||||
|
||||
if prepErr != nil {
|
||||
errs = append(errs, prepErr)
|
||||
}
|
||||
|
||||
return
|
||||
}, c.IncludeTransitiveNeeds(), SetFilter(true))
|
||||
}
|
||||
|
|
@ -138,6 +146,25 @@ func (a *App) Repos(c ReposConfigProvider) error {
|
|||
}, c.IncludeTransitiveNeeds(), SetFilter(true))
|
||||
}
|
||||
|
||||
// TODO: Remove this function once Helmfile v0.x
|
||||
func (a *App) DeprecatedSyncCharts(c DeprecatedChartsConfigProvider) error {
|
||||
return a.ForEachState(func(run *Run) (_ bool, errs []error) {
|
||||
err := run.withPreparedCharts("charts", state.ChartPrepareOptions{
|
||||
SkipRepos: true,
|
||||
SkipDeps: true,
|
||||
Concurrency: 2,
|
||||
}, func() {
|
||||
errs = run.DeprecatedSyncCharts(c)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
return
|
||||
}, c.IncludeTransitiveNeeds(), SetFilter(true))
|
||||
}
|
||||
|
||||
func (a *App) Diff(c DiffConfigProvider) error {
|
||||
var allDiffDetectedErrs []error
|
||||
|
||||
|
|
@ -155,8 +182,7 @@ func (a *App) Diff(c DiffConfigProvider) error {
|
|||
includeCRDs := !c.SkipCRDs()
|
||||
|
||||
prepErr := run.withPreparedCharts("diff", state.ChartPrepareOptions{
|
||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||
SkipRefresh: c.SkipRefresh(),
|
||||
SkipRepos: c.SkipDeps(),
|
||||
SkipDeps: c.SkipDeps(),
|
||||
IncludeCRDs: &includeCRDs,
|
||||
Validate: c.Validate(),
|
||||
|
|
@ -199,7 +225,7 @@ func (a *App) Diff(c DiffConfigProvider) error {
|
|||
}
|
||||
|
||||
if c.DetailedExitcode() && (len(allDiffDetectedErrs) > 0 || affectedAny) {
|
||||
// We take the first release error w/ exit status 2 (although all the deferred errs should have exit status 2)
|
||||
// We take the first release error w/ exit status 2 (although all the defered errs should have exit status 2)
|
||||
// to just let helmfile itself to exit with 2
|
||||
// See https://github.com/roboll/helmfile/issues/749
|
||||
code := 2
|
||||
|
|
@ -220,13 +246,8 @@ func (a *App) Template(c TemplateConfigProvider) error {
|
|||
// Live output should never be enabled for the "template" subcommand to avoid breaking `helmfile template | kubectl apply -f -`
|
||||
run.helm.SetEnableLiveOutput(false)
|
||||
|
||||
// Reset helm extra args to not pollute BuildDeps() and AddRepo() on subsequent helmfiles
|
||||
// https://github.com/helmfile/helmfile/issues/1749
|
||||
run.helm.SetExtraArgs()
|
||||
|
||||
prepErr := run.withPreparedCharts("template", state.ChartPrepareOptions{
|
||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||
SkipRefresh: c.SkipRefresh(),
|
||||
SkipRepos: c.SkipDeps(),
|
||||
SkipDeps: c.SkipDeps(),
|
||||
IncludeCRDs: &includeCRDs,
|
||||
SkipCleanup: c.SkipCleanup(),
|
||||
|
|
@ -234,8 +255,6 @@ func (a *App) Template(c TemplateConfigProvider) error {
|
|||
Concurrency: c.Concurrency(),
|
||||
IncludeTransitiveNeeds: c.IncludeNeeds(),
|
||||
Set: c.Set(),
|
||||
Values: c.Values(),
|
||||
KubeVersion: c.KubeVersion(),
|
||||
}, func() {
|
||||
ok, errs = a.template(run, c)
|
||||
})
|
||||
|
|
@ -251,8 +270,7 @@ func (a *App) Template(c TemplateConfigProvider) error {
|
|||
func (a *App) WriteValues(c WriteValuesConfigProvider) error {
|
||||
return a.ForEachState(func(run *Run) (ok bool, errs []error) {
|
||||
prepErr := run.withPreparedCharts("write-values", state.ChartPrepareOptions{
|
||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||
SkipRefresh: c.SkipRefresh(),
|
||||
SkipRepos: c.SkipDeps(),
|
||||
SkipDeps: c.SkipDeps(),
|
||||
SkipCleanup: c.SkipCleanup(),
|
||||
Concurrency: c.Concurrency(),
|
||||
|
|
@ -303,8 +321,7 @@ func (a *App) Lint(c LintConfigProvider) error {
|
|||
// `helm lint` on helm v2 and v3 does not support remote charts, that we need to set `forceDownload=true` here
|
||||
prepErr := run.withPreparedCharts("lint", state.ChartPrepareOptions{
|
||||
ForceDownload: true,
|
||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||
SkipRefresh: c.SkipRefresh(),
|
||||
SkipRepos: c.SkipDeps(),
|
||||
SkipDeps: c.SkipDeps(),
|
||||
SkipCleanup: c.SkipCleanup(),
|
||||
Concurrency: c.Concurrency(),
|
||||
|
|
@ -339,13 +356,13 @@ func (a *App) Fetch(c FetchConfigProvider) error {
|
|||
return a.ForEachState(func(run *Run) (ok bool, errs []error) {
|
||||
prepErr := run.withPreparedCharts("pull", state.ChartPrepareOptions{
|
||||
ForceDownload: true,
|
||||
SkipRefresh: c.SkipRefresh(),
|
||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||
SkipRepos: c.SkipDeps(),
|
||||
SkipDeps: c.SkipDeps(),
|
||||
OutputDir: c.OutputDir(),
|
||||
OutputDirTemplate: c.OutputDirTemplate(),
|
||||
Concurrency: c.Concurrency(),
|
||||
}, func() {})
|
||||
}, func() {
|
||||
})
|
||||
|
||||
if prepErr != nil {
|
||||
errs = append(errs, prepErr)
|
||||
|
|
@ -360,11 +377,9 @@ func (a *App) Sync(c SyncConfigProvider) error {
|
|||
includeCRDs := !c.SkipCRDs()
|
||||
|
||||
prepErr := run.withPreparedCharts("sync", state.ChartPrepareOptions{
|
||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||
SkipRefresh: c.SkipRefresh(),
|
||||
SkipRepos: c.SkipDeps(),
|
||||
SkipDeps: c.SkipDeps(),
|
||||
Wait: c.Wait(),
|
||||
WaitRetries: c.WaitRetries(),
|
||||
WaitForJobs: c.WaitForJobs(),
|
||||
IncludeCRDs: &includeCRDs,
|
||||
IncludeTransitiveNeeds: c.IncludeNeeds(),
|
||||
|
|
@ -389,20 +404,18 @@ func (a *App) Apply(c ApplyConfigProvider) error {
|
|||
|
||||
var opts []LoadOption
|
||||
|
||||
opts = append(opts, SetRetainValuesFiles(c.SkipCleanup()))
|
||||
opts = append(opts, SetRetainValuesFiles(c.RetainValuesFiles() || c.SkipCleanup()))
|
||||
|
||||
err := a.ForEachState(func(run *Run) (ok bool, errs []error) {
|
||||
includeCRDs := !c.SkipCRDs()
|
||||
|
||||
prepErr := run.withPreparedCharts("apply", state.ChartPrepareOptions{
|
||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||
SkipRefresh: c.SkipRefresh(),
|
||||
SkipRepos: c.SkipDeps(),
|
||||
SkipDeps: c.SkipDeps(),
|
||||
Wait: c.Wait(),
|
||||
WaitRetries: c.WaitRetries(),
|
||||
WaitForJobs: c.WaitForJobs(),
|
||||
IncludeCRDs: &includeCRDs,
|
||||
SkipCleanup: c.SkipCleanup(),
|
||||
SkipCleanup: c.RetainValuesFiles() || c.SkipCleanup(),
|
||||
Validate: c.Validate(),
|
||||
Concurrency: c.Concurrency(),
|
||||
IncludeTransitiveNeeds: c.IncludeNeeds(),
|
||||
|
|
@ -454,16 +467,35 @@ func (a *App) Status(c StatusesConfigProvider) error {
|
|||
}, false, SetFilter(true))
|
||||
}
|
||||
|
||||
// TODO: Remove this function once Helmfile v0.x
|
||||
func (a *App) Delete(c DeleteConfigProvider) error {
|
||||
return a.ForEachState(func(run *Run) (ok bool, errs []error) {
|
||||
if !c.SkipCharts() {
|
||||
err := run.withPreparedCharts("delete", state.ChartPrepareOptions{
|
||||
SkipRepos: c.SkipDeps(),
|
||||
SkipDeps: c.SkipDeps(),
|
||||
Concurrency: c.Concurrency(),
|
||||
}, func() {
|
||||
ok, errs = a.delete(run, c.Purge(), c)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
} else {
|
||||
ok, errs = a.delete(run, c.Purge(), c)
|
||||
}
|
||||
return
|
||||
}, false, SetReverse(true))
|
||||
}
|
||||
|
||||
func (a *App) Destroy(c DestroyConfigProvider) error {
|
||||
return a.ForEachState(func(run *Run) (ok bool, errs []error) {
|
||||
if !c.SkipCharts() {
|
||||
err := run.withPreparedCharts("destroy", state.ChartPrepareOptions{
|
||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||
SkipRefresh: c.SkipRefresh(),
|
||||
SkipDeps: c.SkipDeps(),
|
||||
Concurrency: c.Concurrency(),
|
||||
DeleteWait: c.DeleteWait(),
|
||||
DeleteTimeout: c.DeleteTimeout(),
|
||||
SkipRepos: c.SkipDeps(),
|
||||
SkipDeps: c.SkipDeps(),
|
||||
Concurrency: c.Concurrency(),
|
||||
}, func() {
|
||||
ok, errs = a.delete(run, true, c)
|
||||
})
|
||||
|
|
@ -486,8 +518,7 @@ func (a *App) Test(c TestConfigProvider) error {
|
|||
}
|
||||
|
||||
err := run.withPreparedCharts("test", state.ChartPrepareOptions{
|
||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||
SkipRefresh: c.SkipRefresh(),
|
||||
SkipRepos: c.SkipDeps(),
|
||||
SkipDeps: c.SkipDeps(),
|
||||
Concurrency: c.Concurrency(),
|
||||
}, func() {
|
||||
|
|
@ -502,23 +533,6 @@ func (a *App) Test(c TestConfigProvider) error {
|
|||
}, false, SetFilter(true))
|
||||
}
|
||||
|
||||
func (a *App) PrintDAGState(c DAGConfigProvider) error {
|
||||
var err error
|
||||
return a.ForEachState(func(run *Run) (ok bool, errs []error) {
|
||||
err = run.withPreparedCharts("show-dag", state.ChartPrepareOptions{
|
||||
SkipRepos: true,
|
||||
SkipDeps: true,
|
||||
Concurrency: 2,
|
||||
}, func() {
|
||||
err = a.dag(run)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
})
|
||||
return ok, errs
|
||||
}, false, SetFilter(true))
|
||||
}
|
||||
|
||||
func (a *App) PrintState(c StateConfigProvider) error {
|
||||
return a.ForEachState(func(run *Run) (_ bool, errs []error) {
|
||||
err := run.withPreparedCharts("build", state.ChartPrepareOptions{
|
||||
|
|
@ -572,19 +586,6 @@ func (a *App) PrintState(c StateConfigProvider) error {
|
|||
}, false, SetFilter(true))
|
||||
}
|
||||
|
||||
func (a *App) dag(r *Run) error {
|
||||
st := r.state
|
||||
|
||||
batches, err := st.PlanReleases(state.PlanOptions{SelectedReleases: st.Releases, Reverse: false, SkipNeeds: false, IncludeNeeds: true, IncludeTransitiveNeeds: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Print(printDAG(batches))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) ListReleases(c ListConfigProvider) error {
|
||||
var releases []*HelmRelease
|
||||
|
||||
|
|
@ -659,10 +660,11 @@ func (a *App) list(run *Run) ([]*HelmRelease, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
installed := r.Installed == nil || *r.Installed
|
||||
releases = append(releases, &HelmRelease{
|
||||
Name: r.Name,
|
||||
Namespace: r.Namespace,
|
||||
Installed: r.Desired(),
|
||||
Installed: installed,
|
||||
Enabled: enabled,
|
||||
Labels: labels,
|
||||
Chart: r.Chart,
|
||||
|
|
@ -680,7 +682,7 @@ func (a *App) within(dir string, do func() error) error {
|
|||
|
||||
prev, err := a.fs.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed getting current working directory: %v", err)
|
||||
return fmt.Errorf("failed getting current working direcotyr: %v", err)
|
||||
}
|
||||
|
||||
absDir, err := a.fs.Abs(dir)
|
||||
|
|
@ -756,12 +758,11 @@ func (a *App) loadDesiredStateFromYaml(file string, opts ...LoadOpts) (*state.He
|
|||
logger: a.Logger,
|
||||
remote: a.remote,
|
||||
|
||||
overrideKubeContext: a.OverrideKubeContext,
|
||||
overrideHelmBinary: a.OverrideHelmBinary,
|
||||
overrideKustomizeBinary: a.OverrideKustomizeBinary,
|
||||
enableLiveOutput: a.EnableLiveOutput,
|
||||
getHelm: a.getHelm,
|
||||
valsRuntime: a.valsRuntime,
|
||||
overrideKubeContext: a.OverrideKubeContext,
|
||||
overrideHelmBinary: a.OverrideHelmBinary,
|
||||
enableLiveOutput: a.EnableLiveOutput,
|
||||
getHelm: a.getHelm,
|
||||
valsRuntime: a.valsRuntime,
|
||||
}
|
||||
|
||||
return ld.Load(file, op)
|
||||
|
|
@ -784,7 +785,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
|
||||
// once we enable each release to have its own helm binary/version.
|
||||
func (a *App) getHelm(st *state.HelmState) (helmexec.Interface, error) {
|
||||
func (a *App) getHelm(st *state.HelmState) helmexec.Interface {
|
||||
a.helmsMutex.Lock()
|
||||
defer a.helmsMutex.Unlock()
|
||||
|
||||
|
|
@ -793,27 +794,19 @@ func (a *App) getHelm(st *state.HelmState) (helmexec.Interface, error) {
|
|||
}
|
||||
|
||||
bin := st.DefaultHelmBinary
|
||||
if bin == "" {
|
||||
bin = state.DefaultHelmBinary
|
||||
}
|
||||
kubeconfig := a.Kubeconfig
|
||||
kubectx := st.HelmDefaults.KubeContext
|
||||
|
||||
key := createHelmKey(bin, kubectx)
|
||||
|
||||
if _, ok := a.helms[key]; !ok {
|
||||
exec, err := helmexec.New(bin, helmexec.HelmExecOptions{EnableLiveOutput: a.EnableLiveOutput, DisableForceUpdate: a.DisableForceUpdate}, a.Logger, kubeconfig, kubectx, &helmexec.ShellRunner{
|
||||
a.helms[key] = helmexec.New(bin, helmexec.HelmExecOptions{EnableLiveOutput: a.EnableLiveOutput, DisableForceUpdate: a.DisableForceUpdate}, a.Logger, kubectx, &helmexec.ShellRunner{
|
||||
Logger: a.Logger,
|
||||
Ctx: a.ctx,
|
||||
StripArgsValuesOnExitError: a.StripArgsValuesOnExitError,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a.helms[key] = exec
|
||||
}
|
||||
|
||||
return a.helms[key], nil
|
||||
return a.helms[key]
|
||||
}
|
||||
|
||||
func (a *App) visitStates(fileOrDir string, defOpts LoadOpts, converge func(*state.HelmState) (bool, []error)) error {
|
||||
|
|
@ -965,10 +958,7 @@ var (
|
|||
func (a *App) ForEachState(do func(*Run) (bool, []error), includeTransitiveNeeds bool, o ...LoadOption) error {
|
||||
ctx := NewContext()
|
||||
err := a.visitStatesWithSelectorsAndRemoteSupport(a.FileOrDir, func(st *state.HelmState) (bool, []error) {
|
||||
helm, err := a.getHelm(st)
|
||||
if err != nil {
|
||||
return false, []error{err}
|
||||
}
|
||||
helm := a.getHelm(st)
|
||||
|
||||
run, err := NewRun(st, helm, ctx)
|
||||
if err != nil {
|
||||
|
|
@ -987,36 +977,14 @@ func printBatches(batches [][]state.Release) string {
|
|||
|
||||
w.Init(buf, 0, 1, 1, ' ', 0)
|
||||
|
||||
_, _ = fmt.Fprintln(w, "GROUP\tRELEASES")
|
||||
fmt.Fprintln(w, "GROUP\tRELEASES")
|
||||
|
||||
for i, batch := range batches {
|
||||
ids := []string{}
|
||||
for _, r := range batch {
|
||||
ids = append(ids, state.ReleaseToID(&r.ReleaseSpec))
|
||||
}
|
||||
_, _ = fmt.Fprintf(w, "%d\t%s\n", i+1, strings.Join(ids, ", "))
|
||||
}
|
||||
|
||||
_ = w.Flush()
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func printDAG(batches [][]state.Release) string {
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
w := new(tabwriter.Writer)
|
||||
|
||||
w.Init(buf, 0, 1, 1, ' ', 0)
|
||||
|
||||
_, _ = fmt.Fprintln(w, "GROUP\tRELEASE\tDEPENDENCIES")
|
||||
|
||||
for i, batch := range batches {
|
||||
for _, r := range batch {
|
||||
id := state.ReleaseToID(&r.ReleaseSpec)
|
||||
needs := r.Needs
|
||||
_, _ = fmt.Fprintf(w, "%d\t%s\t%s\n", i+1, id, strings.Join(needs, ", "))
|
||||
}
|
||||
fmt.Fprintf(w, "%d\t%s\n", i+1, strings.Join(ids, ", "))
|
||||
}
|
||||
|
||||
_ = w.Flush()
|
||||
|
|
@ -1115,17 +1083,9 @@ func (a *App) visitStatesWithSelectorsAndRemoteSupport(fileOrDir string, converg
|
|||
}
|
||||
}
|
||||
|
||||
// pre-handles HelmState
|
||||
// pre-overrides HelmState
|
||||
fHelmStatsWithOverrides := func(st *state.HelmState) (bool, []error) {
|
||||
var err error
|
||||
// override release settings
|
||||
st.Releases, err = st.GetReleasesWithOverrides()
|
||||
if err != nil {
|
||||
return false, []error{err}
|
||||
}
|
||||
|
||||
// override release labels
|
||||
st.Releases = st.GetReleasesWithLabels()
|
||||
st.Releases = st.GetReleasesWithOverrides()
|
||||
return f(st)
|
||||
}
|
||||
|
||||
|
|
@ -1153,7 +1113,7 @@ func processFilteredReleases(st *state.HelmState, converge func(st *state.HelmSt
|
|||
|
||||
func checkDuplicates(releases []state.ReleaseSpec) error {
|
||||
type Key struct {
|
||||
Namespace, Name, KubeContext string
|
||||
TillerNamespace, Name, KubeContext string
|
||||
}
|
||||
|
||||
releaseNameCounts := map[Key]int{}
|
||||
|
|
@ -1165,8 +1125,8 @@ func checkDuplicates(releases []state.ReleaseSpec) error {
|
|||
if c > 1 {
|
||||
var msg string
|
||||
|
||||
if name.Namespace != "" {
|
||||
msg += fmt.Sprintf(" in namespace %q", name.Namespace)
|
||||
if name.TillerNamespace != "" {
|
||||
msg += fmt.Sprintf(" in namespace %q", name.TillerNamespace)
|
||||
}
|
||||
|
||||
if name.KubeContext != "" {
|
||||
|
|
@ -1228,6 +1188,16 @@ func (a *App) findDesiredStateFiles(specifiedPath string, opts LoadOpts) ([]stri
|
|||
|
||||
case a.fs.FileExistsAt(DefaultGotmplHelmfile):
|
||||
defaultFile = DefaultGotmplHelmfile
|
||||
|
||||
// TODO: Remove this block when we remove v0 code
|
||||
case !runtime.V1Mode && a.fs.FileExistsAt(DeprecatedHelmfile):
|
||||
a.Logger.Warnf(
|
||||
"warn: %s is being loaded: %s is deprecated in favor of %s. See https://github.com/roboll/helmfile/issues/25 for more information",
|
||||
DeprecatedHelmfile,
|
||||
DeprecatedHelmfile,
|
||||
DefaultHelmfile,
|
||||
)
|
||||
defaultFile = DeprecatedHelmfile
|
||||
}
|
||||
|
||||
switch {
|
||||
|
|
@ -1240,7 +1210,7 @@ func (a *App) findDesiredStateFiles(specifiedPath string, opts LoadOpts) ([]stri
|
|||
case defaultFile != "":
|
||||
return []string{defaultFile}, nil
|
||||
default:
|
||||
return []string{}, fmt.Errorf("no state file found. It must be named %s/*.{yaml,yml,yaml.gotmpl,yml.gotmpl}, %s, or %s, otherwise specified with the --file flag or %s environment variable", DefaultHelmfileDirectory, DefaultHelmfile, DefaultGotmplHelmfile, envvar.FilePath)
|
||||
return []string{}, fmt.Errorf("no state file found. It must be named %s/*.{yaml,yml,yaml.gotmpl,yml.gotmpl}, %s, or %s, otherwise specified with the --file flag", DefaultHelmfileDirectory, DefaultHelmfile, DefaultGotmplHelmfile)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1282,6 +1252,7 @@ func (a *App) getSelectedReleases(r *Run, includeTransitiveNeeds bool) ([]state.
|
|||
selectedIds := map[string]state.ReleaseSpec{}
|
||||
selectedCounts := map[string]int{}
|
||||
for _, r := range selected {
|
||||
r := r
|
||||
id := state.ReleaseToID(&r)
|
||||
selectedIds[id] = r
|
||||
selectedCounts[id]++
|
||||
|
|
@ -1295,6 +1266,7 @@ func (a *App) getSelectedReleases(r *Run, includeTransitiveNeeds bool) ([]state.
|
|||
|
||||
groupsByID := map[string][]*state.ReleaseSpec{}
|
||||
for _, r := range allReleases {
|
||||
r := r
|
||||
groupsByID[state.ReleaseToID(&r)] = append(groupsByID[state.ReleaseToID(&r)], &r)
|
||||
}
|
||||
|
||||
|
|
@ -1348,7 +1320,7 @@ func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, bool, []error) {
|
|||
st := r.state
|
||||
helm := r.helm
|
||||
|
||||
helm.SetExtraArgs(GetArgs(c.Args(), r.state)...)
|
||||
helm.SetExtraArgs(argparser.GetArgs(c.Args(), r.state)...)
|
||||
|
||||
selectedReleases, selectedAndNeededReleases, err := a.getSelectedReleases(r, c.IncludeTransitiveNeeds())
|
||||
if err != nil {
|
||||
|
|
@ -1385,21 +1357,16 @@ func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, bool, []error) {
|
|||
detailedExitCode := true
|
||||
|
||||
diffOpts := &state.DiffOpts{
|
||||
Color: c.Color(),
|
||||
NoColor: c.NoColor(),
|
||||
Context: c.Context(),
|
||||
Output: c.DiffOutput(),
|
||||
Set: c.Set(),
|
||||
SkipCleanup: c.SkipCleanup(),
|
||||
SkipDiffOnInstall: c.SkipDiffOnInstall(),
|
||||
ReuseValues: c.ReuseValues(),
|
||||
ResetValues: c.ResetValues(),
|
||||
DiffArgs: c.DiffArgs(),
|
||||
PostRenderer: c.PostRenderer(),
|
||||
PostRendererArgs: c.PostRendererArgs(),
|
||||
SkipSchemaValidation: c.SkipSchemaValidation(),
|
||||
SuppressOutputLineRegex: c.SuppressOutputLineRegex(),
|
||||
TakeOwnership: c.TakeOwnership(),
|
||||
Color: c.Color(),
|
||||
NoColor: c.NoColor(),
|
||||
Context: c.Context(),
|
||||
Output: c.DiffOutput(),
|
||||
Set: c.Set(),
|
||||
SkipCleanup: c.RetainValuesFiles() || c.SkipCleanup(),
|
||||
SkipDiffOnInstall: c.SkipDiffOnInstall(),
|
||||
ReuseValues: c.ReuseValues(),
|
||||
ResetValues: c.ResetValues(),
|
||||
PostRenderer: c.PostRenderer(),
|
||||
}
|
||||
|
||||
infoMsg, releasesToBeUpdated, releasesToBeDeleted, errs := r.diff(false, detailedExitCode, c, diffOpts)
|
||||
|
|
@ -1502,21 +1469,14 @@ Do you really want to apply?
|
|||
subst.Releases = rs
|
||||
|
||||
syncOpts := &state.SyncOpts{
|
||||
Set: c.Set(),
|
||||
SkipCleanup: c.SkipCleanup(),
|
||||
SkipCRDs: c.SkipCRDs(),
|
||||
Wait: c.Wait(),
|
||||
WaitRetries: c.WaitRetries(),
|
||||
WaitForJobs: c.WaitForJobs(),
|
||||
ReuseValues: c.ReuseValues(),
|
||||
ResetValues: c.ResetValues(),
|
||||
PostRenderer: c.PostRenderer(),
|
||||
PostRendererArgs: c.PostRendererArgs(),
|
||||
SkipSchemaValidation: c.SkipSchemaValidation(),
|
||||
SyncArgs: c.SyncArgs(),
|
||||
HideNotes: c.HideNotes(),
|
||||
TakeOwnership: c.TakeOwnership(),
|
||||
SyncReleaseLabels: c.SyncReleaseLabels(),
|
||||
Set: c.Set(),
|
||||
SkipCleanup: c.RetainValuesFiles() || c.SkipCleanup(),
|
||||
SkipCRDs: c.SkipCRDs(),
|
||||
Wait: c.Wait(),
|
||||
WaitForJobs: c.WaitForJobs(),
|
||||
ReuseValues: c.ReuseValues(),
|
||||
ResetValues: c.ResetValues(),
|
||||
PostRenderer: c.PostRenderer(),
|
||||
}
|
||||
return subst.SyncReleases(&affectedReleases, helm, c.Values(), c.Concurrency(), syncOpts)
|
||||
}))
|
||||
|
|
@ -1601,7 +1561,7 @@ Do you really want to delete?
|
|||
`, strings.Join(names, "\n"))
|
||||
interactive := c.Interactive()
|
||||
if !interactive || interactive && r.askForConfirmation(msg) {
|
||||
r.helm.SetExtraArgs(GetArgs(c.Args(), r.state)...)
|
||||
r.helm.SetExtraArgs(argparser.GetArgs(c.Args(), r.state)...)
|
||||
|
||||
if len(releasesToDelete) > 0 {
|
||||
_, deletionErrs := withDAG(st, helm, a.Logger, state.PlanOptions{SelectedReleases: toDelete, Reverse: true, SkipNeeds: true}, a.WrapWithoutSelector(func(subst *state.HelmState, helm helmexec.Interface) []error {
|
||||
|
|
@ -1626,25 +1586,20 @@ func (a *App) diff(r *Run, c DiffConfigProvider) (*string, bool, bool, []error)
|
|||
ok, errs := a.withNeeds(r, c, true, func(st *state.HelmState) []error {
|
||||
helm := r.helm
|
||||
|
||||
helm.SetExtraArgs(argparser.GetArgs(c.Args(), r.state)...)
|
||||
|
||||
var errs []error
|
||||
|
||||
helm.SetExtraArgs(GetArgs(c.Args(), r.state)...)
|
||||
|
||||
opts := &state.DiffOpts{
|
||||
Context: c.Context(),
|
||||
Output: c.DiffOutput(),
|
||||
Color: c.Color(),
|
||||
NoColor: c.NoColor(),
|
||||
Set: c.Set(),
|
||||
DiffArgs: c.DiffArgs(),
|
||||
SkipDiffOnInstall: c.SkipDiffOnInstall(),
|
||||
ReuseValues: c.ReuseValues(),
|
||||
ResetValues: c.ResetValues(),
|
||||
PostRenderer: c.PostRenderer(),
|
||||
PostRendererArgs: c.PostRendererArgs(),
|
||||
SkipSchemaValidation: c.SkipSchemaValidation(),
|
||||
SuppressOutputLineRegex: c.SuppressOutputLineRegex(),
|
||||
TakeOwnership: c.TakeOwnership(),
|
||||
Context: c.Context(),
|
||||
Output: c.DiffOutput(),
|
||||
Color: c.Color(),
|
||||
NoColor: c.NoColor(),
|
||||
Set: c.Set(),
|
||||
SkipDiffOnInstall: c.SkipDiffOnInstall(),
|
||||
ReuseValues: c.ReuseValues(),
|
||||
ResetValues: c.ResetValues(),
|
||||
PostRenderer: c.PostRenderer(),
|
||||
}
|
||||
|
||||
filtered := &Run{
|
||||
|
|
@ -1667,7 +1622,7 @@ func (a *App) lint(r *Run, c LintConfigProvider) (bool, []error, []error) {
|
|||
ok, errs := a.withNeeds(r, c, false, func(st *state.HelmState) []error {
|
||||
helm := r.helm
|
||||
|
||||
args := GetArgs(c.Args(), st)
|
||||
args := argparser.GetArgs(c.Args(), st)
|
||||
|
||||
// Reset the extra args if already set, not to break `helm fetch` by adding the args intended for `lint`
|
||||
helm.SetExtraArgs()
|
||||
|
|
@ -1717,9 +1672,10 @@ func (a *App) status(r *Run, c StatusesConfigProvider) (bool, []error) {
|
|||
|
||||
var toStatus []state.ReleaseSpec
|
||||
for _, r := range selectedReleases {
|
||||
if r.Desired() {
|
||||
toStatus = append(toStatus, r)
|
||||
if r.Installed != nil && !*r.Installed {
|
||||
continue
|
||||
}
|
||||
toStatus = append(toStatus, r)
|
||||
}
|
||||
|
||||
var errs []error
|
||||
|
|
@ -1727,7 +1683,7 @@ func (a *App) status(r *Run, c StatusesConfigProvider) (bool, []error) {
|
|||
// Traverse DAG of all the releases so that we don't suffer from false-positive missing dependencies
|
||||
st.Releases = allReleases
|
||||
|
||||
args := GetArgs(c.Args(), st)
|
||||
args := argparser.GetArgs(c.Args(), st)
|
||||
|
||||
// Reset the extra args if already set, not to break `helm fetch` by adding the args intended for `lint`
|
||||
helm.SetExtraArgs()
|
||||
|
|
@ -1799,7 +1755,7 @@ func (a *App) sync(r *Run, c SyncConfigProvider) (bool, []error) {
|
|||
for _, r := range toSyncWithNeeds {
|
||||
release := r
|
||||
if _, deleted := releasesToDelete[state.ReleaseToID(&release)]; !deleted {
|
||||
if r.Desired() {
|
||||
if release.Installed == nil || *release.Installed {
|
||||
toUpdate = append(toUpdate, release)
|
||||
}
|
||||
// TODO Emit error when the user opted to fail when the needed release is disabled,
|
||||
|
|
@ -1860,7 +1816,7 @@ Do you really want to sync?
|
|||
|
||||
var errs []error
|
||||
|
||||
r.helm.SetExtraArgs(GetArgs(c.Args(), r.state)...)
|
||||
r.helm.SetExtraArgs(argparser.GetArgs(c.Args(), r.state)...)
|
||||
|
||||
// Traverse DAG of all the releases so that we don't suffer from false-positive missing dependencies
|
||||
st.Releases = selectedAndNeededReleases
|
||||
|
|
@ -1903,20 +1859,13 @@ Do you really want to sync?
|
|||
subst.Releases = rs
|
||||
|
||||
opts := &state.SyncOpts{
|
||||
Set: c.Set(),
|
||||
SkipCRDs: c.SkipCRDs(),
|
||||
Wait: c.Wait(),
|
||||
WaitRetries: c.WaitRetries(),
|
||||
WaitForJobs: c.WaitForJobs(),
|
||||
ReuseValues: c.ReuseValues(),
|
||||
ResetValues: c.ResetValues(),
|
||||
PostRenderer: c.PostRenderer(),
|
||||
PostRendererArgs: c.PostRendererArgs(),
|
||||
SyncArgs: c.SyncArgs(),
|
||||
HideNotes: c.HideNotes(),
|
||||
TakeOwnership: c.TakeOwnership(),
|
||||
SkipSchemaValidation: c.SkipSchemaValidation(),
|
||||
SyncReleaseLabels: c.SyncReleaseLabels(),
|
||||
Set: c.Set(),
|
||||
SkipCRDs: c.SkipCRDs(),
|
||||
Wait: c.Wait(),
|
||||
WaitForJobs: c.WaitForJobs(),
|
||||
ReuseValues: c.ReuseValues(),
|
||||
ResetValues: c.ResetValues(),
|
||||
PostRenderer: c.PostRenderer(),
|
||||
}
|
||||
return subst.SyncReleases(&affectedReleases, helm, c.Values(), c.Concurrency(), opts)
|
||||
}))
|
||||
|
|
@ -1934,7 +1883,7 @@ func (a *App) template(r *Run, c TemplateConfigProvider) (bool, []error) {
|
|||
return a.withNeeds(r, c, false, func(st *state.HelmState) []error {
|
||||
helm := r.helm
|
||||
|
||||
args := GetArgs(c.Args(), st)
|
||||
args := argparser.GetArgs(c.Args(), st)
|
||||
|
||||
// Reset the extra args if already set, not to break `helm fetch` by adding the args intended for `lint`
|
||||
helm.SetExtraArgs()
|
||||
|
|
@ -1944,17 +1893,13 @@ func (a *App) template(r *Run, c TemplateConfigProvider) (bool, []error) {
|
|||
}
|
||||
|
||||
opts := &state.TemplateOpts{
|
||||
Set: c.Set(),
|
||||
IncludeCRDs: c.IncludeCRDs(),
|
||||
NoHooks: c.NoHooks(),
|
||||
OutputDirTemplate: c.OutputDirTemplate(),
|
||||
SkipCleanup: c.SkipCleanup(),
|
||||
SkipTests: c.SkipTests(),
|
||||
PostRenderer: c.PostRenderer(),
|
||||
PostRendererArgs: c.PostRendererArgs(),
|
||||
KubeVersion: c.KubeVersion(),
|
||||
ShowOnly: c.ShowOnly(),
|
||||
SkipSchemaValidation: c.SkipSchemaValidation(),
|
||||
Set: c.Set(),
|
||||
IncludeCRDs: c.IncludeCRDs(),
|
||||
OutputDirTemplate: c.OutputDirTemplate(),
|
||||
SkipCleanup: c.SkipCleanup(),
|
||||
SkipTests: c.SkipTests(),
|
||||
PostRenderer: c.PostRenderer(),
|
||||
KubeVersion: c.KubeVersion(),
|
||||
}
|
||||
return st.TemplateReleases(helm, c.OutputDir(), c.Values(), args, c.Concurrency(), c.Validate(), opts)
|
||||
})
|
||||
|
|
@ -2001,7 +1946,7 @@ func (a *App) withNeeds(r *Run, c DAGConfig, includeDisabled bool, f func(*state
|
|||
for _, r := range selectedReleasesWithNeeds {
|
||||
release := r
|
||||
id := state.ReleaseToID(&release)
|
||||
if !release.Desired() {
|
||||
if release.Installed != nil && !*release.Installed {
|
||||
releasesToUninstall[id] = release
|
||||
} else {
|
||||
toRender = append(toRender, release)
|
||||
|
|
@ -2061,7 +2006,7 @@ func (a *App) test(r *Run, c TestConfigProvider) []error {
|
|||
// with conditions and selectors
|
||||
st.Releases = toTest
|
||||
|
||||
r.helm.SetExtraArgs(GetArgs(c.Args(), r.state)...)
|
||||
r.helm.SetExtraArgs(argparser.GetArgs(c.Args(), r.state)...)
|
||||
|
||||
return st.TestReleases(r.helm, cleanup, timeout, concurrency, state.Logs(c.Logs()))
|
||||
}
|
||||
|
|
@ -2086,9 +2031,10 @@ func (a *App) writeValues(r *Run, c WriteValuesConfigProvider) (bool, []error) {
|
|||
for _, r := range toRender {
|
||||
release := r
|
||||
id := state.ReleaseToID(&release)
|
||||
if release.Desired() {
|
||||
releasesToWrite[id] = release
|
||||
if release.Installed != nil && !*release.Installed {
|
||||
continue
|
||||
}
|
||||
releasesToWrite[id] = release
|
||||
}
|
||||
|
||||
var errs []error
|
||||
|
|
@ -2265,18 +2211,3 @@ func (a *App) CleanCacheDir(c CacheConfigProvider) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetArgs(args string, state *state.HelmState) []string {
|
||||
baseArgs := []string{}
|
||||
stateArgs := []string{}
|
||||
if len(args) > 0 {
|
||||
baseArgs = argparser.CollectArgs(args)
|
||||
}
|
||||
|
||||
if len(state.HelmDefaults.Args) > 0 {
|
||||
stateArgs = argparser.CollectArgs(strings.Join(state.HelmDefaults.Args, " "))
|
||||
}
|
||||
state.HelmDefaults.Args = append(baseArgs, stateArgs...)
|
||||
|
||||
return state.HelmDefaults.Args
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/helmfile/vals"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/exectest"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/testhelper"
|
||||
)
|
||||
|
||||
func TestApply_hooks(t *testing.T) {
|
||||
|
|
@ -133,7 +133,10 @@ func TestApply_hooks(t *testing.T) {
|
|||
if tc.log != "" {
|
||||
actual := bs.String()
|
||||
|
||||
assert.Equal(t, tc.log, actual)
|
||||
diff, exists := testhelper.Diff(tc.log, actual, 3)
|
||||
if exists {
|
||||
t.Errorf("unexpected log:\nDIFF\n%s\nEOD", diff)
|
||||
}
|
||||
} else {
|
||||
assertLogEqualsToSnapshot(t, bs.String())
|
||||
}
|
||||
|
|
@ -161,7 +164,7 @@ releases:
|
|||
{Name: "foo"},
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
error: "",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
|
|
@ -192,7 +195,7 @@ releases:
|
|||
{Name: "foo"},
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
error: "",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
|
|
@ -223,7 +226,7 @@ releases:
|
|||
{Name: "foo"},
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
error: "",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
|
|
@ -252,7 +255,7 @@ releases:
|
|||
},
|
||||
selectors: []string{"app=test"},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: nil,
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: nil,
|
||||
},
|
||||
error: "",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
|
|
@ -299,8 +302,8 @@ releases:
|
|||
{Name: "bar"},
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
error: "",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
|
|
@ -346,7 +349,7 @@ releases:
|
|||
{Name: "foo"},
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
error: "",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
|
|
@ -396,7 +399,7 @@ bar 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 default
|
|||
{Name: "foo"},
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
error: "",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
|
|
@ -444,7 +447,7 @@ foo 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 default
|
|||
{Name: "foo"},
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
error: "",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/helmfile/vals"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/exectest"
|
||||
"github.com/helmfile/helmfile/pkg/filesystem"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/testhelper"
|
||||
)
|
||||
|
||||
func TestApply_3(t *testing.T) {
|
||||
|
|
@ -134,7 +134,10 @@ func TestApply_3(t *testing.T) {
|
|||
if tc.log != "" {
|
||||
actual := bs.String()
|
||||
|
||||
assert.Equal(t, tc.log, actual)
|
||||
diff, exists := testhelper.Diff(tc.log, actual, 3)
|
||||
if exists {
|
||||
t.Errorf("unexpected log:\nDIFF\n%s\nEOD", diff)
|
||||
}
|
||||
} else {
|
||||
assertLogEqualsToSnapshot(t, bs.String())
|
||||
}
|
||||
|
|
@ -146,7 +149,7 @@ func TestApply_3(t *testing.T) {
|
|||
skipNeeds: true,
|
||||
},
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -177,8 +180,8 @@ releases:
|
|||
{Name: "my-release", Flags: []string{"--namespace", "default"}},
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^external-secrets$", Flags: listFlags("default", "")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -199,7 +202,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
skipNeeds: true,
|
||||
},
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -234,8 +237,8 @@ releases:
|
|||
`,
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: nil,
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: nil,
|
||||
},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
|
|
@ -250,7 +253,7 @@ releases:
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -278,9 +281,9 @@ releases:
|
|||
selectors: []string{"app=test"},
|
||||
upgraded: []exectest.Release{},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "kubernetes-external-secrets", Chart: "incubator/raw", Flags: "--namespace kube-system --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "kubernetes-external-secrets", Chart: "incubator/raw", Flags: "--namespacekube-system--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^kubernetes-external-secrets$", Flags: listFlags("kube-system", "")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -306,7 +309,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -334,9 +337,9 @@ releases:
|
|||
selectors: []string{"app=test"},
|
||||
upgraded: []exectest.Release{},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "kubernetes-external-secrets", Chart: "incubator/raw", Flags: "--namespace kube-system --reset-values --detailed-exitcode"}: nil,
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "kubernetes-external-secrets", Chart: "incubator/raw", Flags: "--namespacekube-system--detailed-exitcode--reset-values"}: nil,
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^external-secrets$", Flags: listFlags("default", "")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -359,7 +362,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -399,8 +402,8 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
`,
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
|
|
@ -415,7 +418,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -453,8 +456,8 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
`,
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
|
|
@ -464,7 +467,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
t.Run("bad --selector", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -494,6 +497,72 @@ releases:
|
|||
error: "err: no releases found that matches specified selector(app=test_non_existent) and environment(default), in any helmfile",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
0 release(s) matching app=test_non_existent found in helmfile.yaml
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/helmfile/vals"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/exectest"
|
||||
"github.com/helmfile/helmfile/pkg/filesystem"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/testhelper"
|
||||
)
|
||||
|
||||
func TestApply_2(t *testing.T) {
|
||||
|
|
@ -134,7 +134,10 @@ func TestApply_2(t *testing.T) {
|
|||
if tc.log != "" {
|
||||
actual := bs.String()
|
||||
|
||||
assert.Equal(t, tc.log, actual)
|
||||
diff, exists := testhelper.Diff(tc.log, actual, 3)
|
||||
if exists {
|
||||
t.Errorf("unexpected log:\nDIFF\n%s\nEOD", diff)
|
||||
}
|
||||
} else {
|
||||
assertLogEqualsToSnapshot(t, bs.String())
|
||||
}
|
||||
|
|
@ -146,7 +149,7 @@ func TestApply_2(t *testing.T) {
|
|||
skipNeeds: true,
|
||||
},
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -177,8 +180,8 @@ releases:
|
|||
{Name: "my-release", Flags: []string{"--kube-context", "default", "--namespace", "default"}},
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^external-secrets$", Flags: listFlags("default", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -199,7 +202,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
skipNeeds: true,
|
||||
},
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -234,8 +237,8 @@ releases:
|
|||
`,
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: nil,
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: nil,
|
||||
},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
|
|
@ -250,7 +253,7 @@ releases:
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -278,9 +281,9 @@ releases:
|
|||
selectors: []string{"app=test"},
|
||||
upgraded: []exectest.Release{},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "kubernetes-external-secrets", Chart: "incubator/raw", Flags: "--kube-context default --namespace kube-system --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "kubernetes-external-secrets", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacekube-system--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^kubernetes-external-secrets$", Flags: listFlags("kube-system", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -306,7 +309,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -334,9 +337,9 @@ releases:
|
|||
selectors: []string{"app=test"},
|
||||
upgraded: []exectest.Release{},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "kubernetes-external-secrets", Chart: "incubator/raw", Flags: "--kube-context default --namespace kube-system --reset-values --detailed-exitcode"}: nil,
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "kubernetes-external-secrets", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacekube-system--detailed-exitcode--reset-values"}: nil,
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^external-secrets$", Flags: listFlags("default", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -359,7 +362,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -399,8 +402,8 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
`,
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
|
|
@ -415,7 +418,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -453,8 +456,8 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
`,
|
||||
},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
|
|
@ -470,7 +473,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -494,9 +497,9 @@ releases:
|
|||
selectors: []string{"name=serviceA"},
|
||||
upgraded: []exectest.Release{},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "serviceA", Chart: "my/chart", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "serviceB", Chart: "my/chart", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "serviceC", Chart: "my/chart", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "serviceA", Chart: "my/chart", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "serviceB", Chart: "my/chart", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "serviceC", Chart: "my/chart", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^serviceA$", Flags: listFlags("", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -517,7 +520,7 @@ serviceC 4 Fri Nov 1 08:40:07 2019 DEPLOYED chart-3.1.0 3.1.0 def
|
|||
t.Run("bad --selector", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -547,6 +550,72 @@ releases:
|
|||
error: "err: no releases found that matches specified selector(app=test_non_existent) and environment(default), in any helmfile",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
0 release(s) matching app=test_non_existent found in helmfile.yaml
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -575,7 +644,7 @@ releases:
|
|||
selectors: []string{"index=1"},
|
||||
upgraded: []exectest.Release{},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("default", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -641,7 +710,7 @@ releases:
|
|||
selectors: []string{"name=foo"},
|
||||
upgraded: []exectest.Release{},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("default", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
|
|||
|
|
@ -280,8 +280,8 @@ releases:
|
|||
},
|
||||
selectors: []string{"app=test"},
|
||||
diffed: []exectest.Release{
|
||||
{Name: "external-secrets", Flags: []string{"--kube-context", "default", "--namespace", "default", "--reset-values", "--no-hooks"}},
|
||||
{Name: "my-release", Flags: []string{"--kube-context", "default", "--namespace", "default", "--reset-values", "--no-hooks"}},
|
||||
{Name: "external-secrets", Flags: []string{"--kube-context", "default", "--namespace", "default", "--no-hooks", "--reset-values"}},
|
||||
{Name: "my-release", Flags: []string{"--kube-context", "default", "--namespace", "default", "--no-hooks", "--reset-values"}},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
@ -415,28 +415,4 @@ releases:
|
|||
},
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("show diff on changed selected release with reinstall", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
helmfile: `
|
||||
releases:
|
||||
- name: a
|
||||
chart: incubator/raw
|
||||
namespace: default
|
||||
updateStrategy: reinstallIfForbidden
|
||||
- name: b
|
||||
chart: incubator/raw
|
||||
namespace: default
|
||||
`,
|
||||
selectors: []string{"name=a"},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^a$", Flags: listFlags("default", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
foo 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 default
|
||||
`,
|
||||
},
|
||||
diffed: []exectest.Release{
|
||||
{Name: "a", Flags: []string{"--kube-context", "default", "--namespace", "default", "--reset-values"}},
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
goContext "context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/state"
|
||||
)
|
||||
|
||||
// TestGetHelmWithEmptyDefaultHelmBinary tests that getHelm properly defaults to "helm"
|
||||
// when st.DefaultHelmBinary is empty. This addresses the issue where base files with
|
||||
// environment secrets would fail with "exec: no command" error.
|
||||
//
|
||||
// Background: When a base file has environment secrets but doesn't specify helmBinary,
|
||||
// the state.DefaultHelmBinary would be empty, causing helmexec.New to be called with
|
||||
// an empty string, which results in "error determining helm version: exec: no command".
|
||||
//
|
||||
// The fix in app.getHelm() ensures that when st.DefaultHelmBinary is empty, it defaults
|
||||
// to state.DefaultHelmBinary ("helm").
|
||||
func TestGetHelmWithEmptyDefaultHelmBinary(t *testing.T) {
|
||||
// Test that app.getHelm() handles empty DefaultHelmBinary correctly by applying a default
|
||||
st := &state.HelmState{
|
||||
ReleaseSetSpec: state.ReleaseSetSpec{
|
||||
DefaultHelmBinary: "", // Empty, as would be the case for base files
|
||||
},
|
||||
}
|
||||
|
||||
logger := newAppTestLogger()
|
||||
app := &App{
|
||||
OverrideHelmBinary: "",
|
||||
OverrideKubeContext: "",
|
||||
Logger: logger,
|
||||
Env: "default",
|
||||
ctx: goContext.Background(),
|
||||
}
|
||||
|
||||
// This should NOT fail because app.getHelm() defaults empty DefaultHelmBinary to "helm"
|
||||
helm, err := app.getHelm(st)
|
||||
|
||||
// Verify that no error occurred - the fix in app.getHelm() prevents the "exec: no command" error
|
||||
require.NoError(t, err, "getHelm should not fail when DefaultHelmBinary is empty (fix should apply default)")
|
||||
|
||||
// Verify that a valid helm execer was returned
|
||||
require.NotNil(t, helm, "getHelm should return a valid helm execer")
|
||||
|
||||
// Verify that the helm version is accessible (confirms the helm binary is valid)
|
||||
version := helm.GetVersion()
|
||||
require.NotNil(t, version, "helm version should be accessible")
|
||||
}
|
||||
|
|
@ -9,13 +9,13 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/helmfile/vals"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/exectest"
|
||||
ffs "github.com/helmfile/helmfile/pkg/filesystem"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/testhelper"
|
||||
)
|
||||
|
||||
func TestLint(t *testing.T) {
|
||||
|
|
@ -167,7 +167,10 @@ releases:
|
|||
}
|
||||
}
|
||||
|
||||
assert.Equal(t, wantLog, gotLog)
|
||||
diff, exists := testhelper.Diff(wantLog, gotLog, 3)
|
||||
if exists {
|
||||
t.Errorf("unexpected log:\nDIFF\n%s\nEOD", diff)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("fail on unselected need by default", func(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ func testListWithEnvironment(t *testing.T, cfg configImpl) {
|
|||
environments:
|
||||
development: {}
|
||||
shared: {}
|
||||
---
|
||||
|
||||
releases:
|
||||
- name: logging
|
||||
chart: incubator/raw
|
||||
|
|
@ -90,7 +90,7 @@ releases:
|
|||
environments:
|
||||
test: {}
|
||||
shared: {}
|
||||
---
|
||||
|
||||
repositories:
|
||||
- name: bitnami
|
||||
url: https://charts.bitnami.com/bitnami
|
||||
|
|
@ -159,17 +159,17 @@ releases:
|
|||
t.Run("default environment includes all releases", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
environment: "default",
|
||||
expected: `NAME NAMESPACE ENABLED INSTALLED LABELS CHART VERSION
|
||||
logging kube-system true true chart:raw,name:logging,namespace:kube-system incubator/raw
|
||||
kubernetes-external-secrets kube-system true true chart:raw,name:kubernetes-external-secrets,namespace:kube-system incubator/raw
|
||||
external-secrets default true true app:test,chart:raw,name:external-secrets,namespace:default incubator/raw
|
||||
my-release default true true app:test,chart:raw,name:my-release,namespace:default incubator/raw
|
||||
disabled kube-system true false chart:raw,name:disabled,namespace:kube-system incubator/raw
|
||||
test2 true true chart:raw,name:test2,namespace: incubator/raw
|
||||
test3 true true chart:raw,name:test3,namespace: incubator/raw
|
||||
cache my-app true true app:test,chart:redis,name:cache,namespace:my-app bitnami/redis 17.0.7
|
||||
database my-app true true chart:postgres,name:database,namespace:my-app bitnami/postgres 11.6.22
|
||||
global kube-system true true chart:raw,name:global,namespace:kube-system incubator/raw
|
||||
expected: `NAME NAMESPACE ENABLED INSTALLED LABELS CHART VERSION
|
||||
logging kube-system true true incubator/raw
|
||||
kubernetes-external-secrets kube-system true true incubator/raw
|
||||
external-secrets default true true app:test incubator/raw
|
||||
my-release default true true app:test incubator/raw
|
||||
disabled kube-system true false incubator/raw
|
||||
test2 true true incubator/raw
|
||||
test3 true true incubator/raw
|
||||
cache my-app true true app:test bitnami/redis 17.0.7
|
||||
database my-app true true bitnami/postgres 11.6.22
|
||||
global kube-system true true incubator/raw
|
||||
`,
|
||||
}, cfg)
|
||||
})
|
||||
|
|
@ -195,9 +195,9 @@ my-release default true true app:test,chart:raw,name:my-release,
|
|||
t.Run("filters releases for environment used in one file only", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
environment: "test",
|
||||
expected: `NAME NAMESPACE ENABLED INSTALLED LABELS CHART VERSION
|
||||
cache my-app true true app:test,chart:redis,name:cache,namespace:my-app bitnami/redis 17.0.7
|
||||
database my-app true true chart:postgres,name:database,namespace:my-app bitnami/postgres 11.6.22
|
||||
expected: `NAME NAMESPACE ENABLED INSTALLED LABELS CHART VERSION
|
||||
cache my-app true true app:test bitnami/redis 17.0.7
|
||||
database my-app true true bitnami/postgres 11.6.22
|
||||
`,
|
||||
}, cfg)
|
||||
})
|
||||
|
|
@ -206,16 +206,16 @@ database my-app true true chart:postgres,name:database,namespace:my-a
|
|||
check(t, testcase{
|
||||
environment: "shared",
|
||||
// 'global' release has no environments, so is still excluded
|
||||
expected: `NAME NAMESPACE ENABLED INSTALLED LABELS CHART VERSION
|
||||
logging kube-system true true chart:raw,name:logging,namespace:kube-system incubator/raw
|
||||
kubernetes-external-secrets kube-system true true chart:raw,name:kubernetes-external-secrets,namespace:kube-system incubator/raw
|
||||
external-secrets default true true app:test,chart:raw,name:external-secrets,namespace:default incubator/raw
|
||||
my-release default true true app:test,chart:raw,name:my-release,namespace:default incubator/raw
|
||||
disabled kube-system true false chart:raw,name:disabled,namespace:kube-system incubator/raw
|
||||
test2 true true chart:raw,name:test2,namespace: incubator/raw
|
||||
test3 true true chart:raw,name:test3,namespace: incubator/raw
|
||||
cache my-app true true app:test,chart:redis,name:cache,namespace:my-app bitnami/redis 17.0.7
|
||||
database my-app true true chart:postgres,name:database,namespace:my-app bitnami/postgres 11.6.22
|
||||
expected: `NAME NAMESPACE ENABLED INSTALLED LABELS CHART VERSION
|
||||
logging kube-system true true incubator/raw
|
||||
kubernetes-external-secrets kube-system true true incubator/raw
|
||||
external-secrets default true true app:test incubator/raw
|
||||
my-release default true true app:test incubator/raw
|
||||
disabled kube-system true false incubator/raw
|
||||
test2 true true incubator/raw
|
||||
test3 true true incubator/raw
|
||||
cache my-app true true app:test bitnami/redis 17.0.7
|
||||
database my-app true true bitnami/postgres 11.6.22
|
||||
`,
|
||||
}, cfg)
|
||||
})
|
||||
|
|
@ -240,7 +240,6 @@ environments:
|
|||
values:
|
||||
- myrelease2:
|
||||
enabled: false
|
||||
---
|
||||
releases:
|
||||
- name: myrelease1
|
||||
chart: mychart1
|
||||
|
|
@ -285,7 +284,7 @@ releases:
|
|||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
expected := `[{"name":"myrelease1","namespace":"testNamespace","enabled":true,"installed":false,"labels":"chart:mychart1,id:myrelease1,name:myrelease1,namespace:testNamespace","chart":"mychart1","version":""},{"name":"myrelease2","namespace":"testNamespace","enabled":false,"installed":true,"labels":"chart:mychart1,name:myrelease2,namespace:testNamespace","chart":"mychart1","version":""},{"name":"myrelease3","namespace":"testNamespace","enabled":true,"installed":true,"labels":"chart:mychart1,name:myrelease3,namespace:testNamespace","chart":"mychart1","version":""},{"name":"myrelease4","namespace":"testNamespace","enabled":true,"installed":true,"labels":"chart:mychart1,id:myrelease1,name:myrelease4,namespace:testNamespace","chart":"mychart1","version":""}]
|
||||
expected := `[{"name":"myrelease1","namespace":"testNamespace","enabled":true,"installed":false,"labels":"id:myrelease1","chart":"mychart1","version":""},{"name":"myrelease2","namespace":"testNamespace","enabled":false,"installed":true,"labels":"","chart":"mychart1","version":""},{"name":"myrelease3","namespace":"testNamespace","enabled":true,"installed":true,"labels":"","chart":"mychart1","version":""},{"name":"myrelease4","namespace":"testNamespace","enabled":true,"installed":true,"labels":"id:myrelease1","chart":"mychart1","version":""}]
|
||||
`
|
||||
assert.Equal(t, expected, out)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/helmfile/vals"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/exectest"
|
||||
ffs "github.com/helmfile/helmfile/pkg/filesystem"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/testhelper"
|
||||
)
|
||||
|
||||
func TestSync(t *testing.T) {
|
||||
|
|
@ -132,7 +132,10 @@ func TestSync(t *testing.T) {
|
|||
if tc.log != "" {
|
||||
actual := bs.String()
|
||||
|
||||
assert.Equal(t, tc.log, actual)
|
||||
diff, exists := testhelper.Diff(tc.log, actual, 3)
|
||||
if exists {
|
||||
t.Errorf("unexpected log:\nDIFF\n%s\nEOD", diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -142,7 +145,7 @@ func TestSync(t *testing.T) {
|
|||
skipNeeds: true,
|
||||
},
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -182,6 +185,89 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
Affected releases are:
|
||||
external-secrets (incubator/raw) UPDATED
|
||||
my-release (incubator/raw) UPDATED
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default/default/external-secrets
|
||||
2 default/default/my-release
|
||||
|
||||
processing releases in group 1/2: default/default/external-secrets
|
||||
processing releases in group 2/2: default/default/my-release
|
||||
|
||||
UPDATED RELEASES:
|
||||
NAME CHART VERSION DURATION
|
||||
external-secrets incubator/raw 3.1.0 0s
|
||||
my-release incubator/raw 3.1.0 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -191,7 +277,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
skipNeeds: true,
|
||||
},
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -238,6 +324,111 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23: hooks:
|
||||
24: - name: my-release
|
||||
25: events:
|
||||
26: - postsync
|
||||
27: showlogs: true
|
||||
28: command: sleep
|
||||
29: args: [5s]
|
||||
30:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23: hooks:
|
||||
24: - name: my-release
|
||||
25: events:
|
||||
26: - postsync
|
||||
27: showlogs: true
|
||||
28: command: sleep
|
||||
29: args: [5s]
|
||||
30:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
Affected releases are:
|
||||
external-secrets (incubator/raw) UPDATED
|
||||
my-release (incubator/raw) UPDATED
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default/default/external-secrets
|
||||
2 default/default/my-release
|
||||
|
||||
processing releases in group 1/2: default/default/external-secrets
|
||||
processing releases in group 2/2: default/default/my-release
|
||||
hook[my-release]: stateFilePath=helmfile.yaml, basePath=.
|
||||
|
||||
hook[my-release]: triggered by event "postsync"
|
||||
|
||||
hook[my-release]:
|
||||
|
||||
|
||||
hook[postsync] logs |
|
||||
|
||||
UPDATED RELEASES:
|
||||
NAME CHART VERSION DURATION
|
||||
external-secrets incubator/raw 3.1.0 0s
|
||||
my-release incubator/raw 3.1.0 5s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -249,7 +440,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -289,6 +480,93 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
Affected releases are:
|
||||
external-secrets (incubator/raw) UPDATED
|
||||
kubernetes-external-secrets (incubator/raw) UPDATED
|
||||
my-release (incubator/raw) UPDATED
|
||||
|
||||
processing 3 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default/kube-system/kubernetes-external-secrets
|
||||
2 default/default/external-secrets
|
||||
3 default/default/my-release
|
||||
|
||||
processing releases in group 1/3: default/kube-system/kubernetes-external-secrets
|
||||
processing releases in group 2/3: default/default/external-secrets
|
||||
processing releases in group 3/3: default/default/my-release
|
||||
|
||||
UPDATED RELEASES:
|
||||
NAME CHART VERSION DURATION
|
||||
kubernetes-external-secrets incubator/raw 3.1.0 0s
|
||||
external-secrets incubator/raw 3.1.0 0s
|
||||
my-release incubator/raw 3.1.0 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -300,7 +578,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -336,6 +614,85 @@ serviceA 4 Fri Nov 1 08:40:07 2019 DEPLOYED chart-3.1.0 3.1.0 def
|
|||
},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: serviceA
|
||||
5: chart: my/chart
|
||||
6: needs:
|
||||
7: - serviceB
|
||||
8:
|
||||
9: - name: serviceB
|
||||
10: chart: my/chart
|
||||
11: needs:
|
||||
12: - serviceC
|
||||
13:
|
||||
14: - name: serviceC
|
||||
15: chart: my/chart
|
||||
16:
|
||||
17: - name: serviceD
|
||||
18: chart: my/chart
|
||||
19:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: serviceA
|
||||
5: chart: my/chart
|
||||
6: needs:
|
||||
7: - serviceB
|
||||
8:
|
||||
9: - name: serviceB
|
||||
10: chart: my/chart
|
||||
11: needs:
|
||||
12: - serviceC
|
||||
13:
|
||||
14: - name: serviceC
|
||||
15: chart: my/chart
|
||||
16:
|
||||
17: - name: serviceD
|
||||
18: chart: my/chart
|
||||
19:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
3 release(s) matching name=serviceA found in helmfile.yaml
|
||||
|
||||
Affected releases are:
|
||||
serviceA (my/chart) UPDATED
|
||||
serviceB (my/chart) UPDATED
|
||||
serviceC (my/chart) UPDATED
|
||||
|
||||
processing 3 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default//serviceC
|
||||
2 default//serviceB
|
||||
3 default//serviceA
|
||||
|
||||
processing releases in group 1/3: default//serviceC
|
||||
processing releases in group 2/3: default//serviceB
|
||||
processing releases in group 3/3: default//serviceA
|
||||
|
||||
UPDATED RELEASES:
|
||||
NAME CHART VERSION DURATION
|
||||
serviceC my/chart 3.1.0 0s
|
||||
serviceB my/chart 3.1.0 0s
|
||||
serviceA my/chart 3.1.0 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -348,7 +705,7 @@ serviceA 4 Fri Nov 1 08:40:07 2019 DEPLOYED chart-3.1.0 3.1.0 def
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -389,6 +746,102 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7: installed: false
|
||||
8:
|
||||
9: - name: external-secrets
|
||||
10: chart: incubator/raw
|
||||
11: namespace: default
|
||||
12: labels:
|
||||
13: app: test
|
||||
14: needs:
|
||||
15: - kube-system/kubernetes-external-secrets
|
||||
16:
|
||||
17: - name: my-release
|
||||
18: chart: incubator/raw
|
||||
19: namespace: default
|
||||
20: labels:
|
||||
21: app: test
|
||||
22: needs:
|
||||
23: - default/external-secrets
|
||||
24:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7: installed: false
|
||||
8:
|
||||
9: - name: external-secrets
|
||||
10: chart: incubator/raw
|
||||
11: namespace: default
|
||||
12: labels:
|
||||
13: app: test
|
||||
14: needs:
|
||||
15: - kube-system/kubernetes-external-secrets
|
||||
16:
|
||||
17: - name: my-release
|
||||
18: chart: incubator/raw
|
||||
19: namespace: default
|
||||
20: labels:
|
||||
21: app: test
|
||||
22: needs:
|
||||
23: - default/external-secrets
|
||||
24:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
Affected releases are:
|
||||
external-secrets (incubator/raw) UPDATED
|
||||
kubernetes-external-secrets (incubator/raw) DELETED
|
||||
my-release (incubator/raw) UPDATED
|
||||
|
||||
processing 1 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default/kube-system/kubernetes-external-secrets
|
||||
|
||||
processing releases in group 1/1: default/kube-system/kubernetes-external-secrets
|
||||
processing 2 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default/default/external-secrets
|
||||
2 default/default/my-release
|
||||
|
||||
processing releases in group 1/2: default/default/external-secrets
|
||||
processing releases in group 2/2: default/default/my-release
|
||||
|
||||
UPDATED RELEASES:
|
||||
NAME CHART VERSION DURATION
|
||||
external-secrets incubator/raw 3.1.0 0s
|
||||
my-release incubator/raw 3.1.0 0s
|
||||
|
||||
|
||||
DELETED RELEASES:
|
||||
NAME DURATION
|
||||
kubernetes-external-secrets 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -401,7 +854,7 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
error: ``,
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -441,13 +894,98 @@ my-release 4 Fri Nov 1 08:40:07 2019 DEPLOYED raw-3.1.0 3.1.0 def
|
|||
},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7: installed: false
|
||||
8:
|
||||
9: - name: external-secrets
|
||||
10: chart: incubator/raw
|
||||
11: namespace: default
|
||||
12: labels:
|
||||
13: app: test
|
||||
14: needs:
|
||||
15: - kube-system/kubernetes-external-secrets
|
||||
16:
|
||||
17: - name: my-release
|
||||
18: chart: incubator/raw
|
||||
19: namespace: default
|
||||
20: labels:
|
||||
21: app: test
|
||||
22: needs:
|
||||
23: - default/external-secrets
|
||||
24:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7: installed: false
|
||||
8:
|
||||
9: - name: external-secrets
|
||||
10: chart: incubator/raw
|
||||
11: namespace: default
|
||||
12: labels:
|
||||
13: app: test
|
||||
14: needs:
|
||||
15: - kube-system/kubernetes-external-secrets
|
||||
16:
|
||||
17: - name: my-release
|
||||
18: chart: incubator/raw
|
||||
19: namespace: default
|
||||
20: labels:
|
||||
21: app: test
|
||||
22: needs:
|
||||
23: - default/external-secrets
|
||||
24:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
Affected releases are:
|
||||
external-secrets (incubator/raw) UPDATED
|
||||
my-release (incubator/raw) UPDATED
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default/default/external-secrets
|
||||
2 default/default/my-release
|
||||
|
||||
processing releases in group 1/2: default/default/external-secrets
|
||||
processing releases in group 2/2: default/default/my-release
|
||||
|
||||
UPDATED RELEASES:
|
||||
NAME CHART VERSION DURATION
|
||||
external-secrets incubator/raw 3.1.0 0s
|
||||
my-release incubator/raw 3.1.0 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("bad --selector", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -477,6 +1015,72 @@ releases:
|
|||
error: "err: no releases found that matches specified selector(app=test_non_existent) and environment(default), in any helmfile",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
0 release(s) matching app=test_non_existent found in helmfile.yaml
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/helmfile/vals"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
|
||||
|
|
@ -17,6 +16,7 @@ import (
|
|||
ffs "github.com/helmfile/helmfile/pkg/filesystem"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/runtime"
|
||||
"github.com/helmfile/helmfile/pkg/testhelper"
|
||||
)
|
||||
|
||||
func TestTemplate(t *testing.T) {
|
||||
|
|
@ -24,8 +24,6 @@ func TestTemplate(t *testing.T) {
|
|||
skipNeeds bool
|
||||
includeNeeds bool
|
||||
includeTransitiveNeeds bool
|
||||
noHooks bool
|
||||
showOnly []string
|
||||
}
|
||||
|
||||
type testcase struct {
|
||||
|
|
@ -133,8 +131,6 @@ releases:
|
|||
skipNeeds: tc.fields.skipNeeds,
|
||||
includeNeeds: tc.fields.includeNeeds,
|
||||
includeTransitiveNeeds: tc.fields.includeTransitiveNeeds,
|
||||
showOnly: tc.fields.showOnly,
|
||||
noHooks: tc.fields.noHooks,
|
||||
})
|
||||
|
||||
var gotErr string
|
||||
|
|
@ -172,7 +168,10 @@ releases:
|
|||
}
|
||||
}
|
||||
|
||||
assert.Equal(t, wantLog, gotLog)
|
||||
diff, exists := testhelper.Diff(wantLog, gotLog, 3)
|
||||
if exists {
|
||||
t.Errorf("unexpected log:\nDIFF\n%s\nEOD", diff)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("fail on unselected need by default", func(t *testing.T) {
|
||||
|
|
@ -238,7 +237,7 @@ releases:
|
|||
},
|
||||
selectors: []string{"name=test2"},
|
||||
templated: []exectest.Release{
|
||||
{Name: "test2"},
|
||||
{Name: "test2", Flags: []string{}},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
@ -251,8 +250,8 @@ releases:
|
|||
},
|
||||
selectors: []string{"name=test3"},
|
||||
templated: []exectest.Release{
|
||||
{Name: "test2"},
|
||||
{Name: "test3"},
|
||||
{Name: "test2", Flags: []string{}},
|
||||
{Name: "test3", Flags: []string{}},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
@ -266,8 +265,8 @@ releases:
|
|||
},
|
||||
selectors: []string{"name=test3"},
|
||||
templated: []exectest.Release{
|
||||
{Name: "test2"},
|
||||
{Name: "test3"},
|
||||
{Name: "test2", Flags: []string{}},
|
||||
{Name: "test3", Flags: []string{}},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
@ -281,7 +280,7 @@ releases:
|
|||
},
|
||||
selectors: []string{"name=test2"},
|
||||
templated: []exectest.Release{
|
||||
{Name: "test2"},
|
||||
{Name: "test2", Flags: []string{}},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
@ -295,22 +294,8 @@ releases:
|
|||
},
|
||||
selectors: []string{"name=test3"},
|
||||
templated: []exectest.Release{
|
||||
{Name: "test2"},
|
||||
{Name: "test3"},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("no-hooks", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
fields: fields{
|
||||
skipNeeds: true,
|
||||
noHooks: true,
|
||||
},
|
||||
selectors: []string{"app=test"},
|
||||
templated: []exectest.Release{
|
||||
{Name: "external-secrets", Flags: []string{"--namespace", "default", "--no-hooks"}},
|
||||
{Name: "my-release", Flags: []string{"--namespace", "default", "--no-hooks"}},
|
||||
{Name: "test2", Flags: []string{}},
|
||||
{Name: "test3", Flags: []string{}},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
@ -322,34 +307,22 @@ releases:
|
|||
error: "err: no releases found that matches specified selector(app=test_non_existent) and environment(default), in any helmfile",
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("show-only", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
fields: fields{
|
||||
showOnly: []string{"templates/resources.yaml"},
|
||||
},
|
||||
selectors: []string{"name=logging"},
|
||||
templated: []exectest.Release{
|
||||
{Name: "logging", Flags: []string{"--show-only", "templates/resources.yaml", "--namespace", "kube-system"}},
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestTemplate_StrictParsing(t *testing.T) {
|
||||
type testcase struct {
|
||||
GoYamlV3 bool
|
||||
ns string
|
||||
error string
|
||||
goccyGoYaml bool
|
||||
ns string
|
||||
error string
|
||||
}
|
||||
|
||||
check := func(t *testing.T, tc testcase) {
|
||||
t.Helper()
|
||||
|
||||
v := runtime.GoYamlV3
|
||||
runtime.GoYamlV3 = tc.GoYamlV3
|
||||
v := runtime.GoccyGoYaml
|
||||
runtime.GoccyGoYaml = tc.goccyGoYaml
|
||||
t.Cleanup(func() {
|
||||
runtime.GoYamlV3 = v
|
||||
runtime.GoccyGoYaml = v
|
||||
})
|
||||
|
||||
var helm = &exectest.Helm{
|
||||
|
|
@ -411,18 +384,22 @@ releases:
|
|||
})
|
||||
}
|
||||
|
||||
t.Run("fail due to unknown field with go.yaml.in/yaml/v3", func(t *testing.T) {
|
||||
t.Run("fail due to unknown field with goccy/go-yaml", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
GoYamlV3: true,
|
||||
error: `in ./helmfile.yaml: failed to read helmfile.yaml: reading document at index 1. Started seeing this since Helmfile v1? Add the .gotmpl file extension: yaml: unmarshal errors:
|
||||
line 4: field foobar not found in type state.ReleaseSpec`,
|
||||
goccyGoYaml: true,
|
||||
error: `in ./helmfile.yaml: failed to read helmfile.yaml: reading document at index 1: [4:3] unknown field "foobar"
|
||||
2 | releases:
|
||||
3 | - name: app1
|
||||
> 4 | foobar: FOOBAR
|
||||
^
|
||||
5 | chart: incubator/raw`,
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("fail due to unknown field with go.yaml.in/yaml/v2", func(t *testing.T) {
|
||||
t.Run("fail due to unknown field with gopkg.in/yaml.v2", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
GoYamlV3: false,
|
||||
error: `in ./helmfile.yaml: failed to read helmfile.yaml: reading document at index 1. Started seeing this since Helmfile v1? Add the .gotmpl file extension: yaml: unmarshal errors:
|
||||
goccyGoYaml: false,
|
||||
error: `in ./helmfile.yaml: failed to read helmfile.yaml: reading document at index 1: yaml: unmarshal errors:
|
||||
line 4: field foobar not found in type state.ReleaseSpec`,
|
||||
})
|
||||
})
|
||||
|
|
|
|||
1032
pkg/app/app_test.go
1032
pkg/app/app_test.go
File diff suppressed because it is too large
Load Diff
|
|
@ -24,10 +24,9 @@ func AskForConfirmation(s string) bool {
|
|||
|
||||
response = strings.ToLower(strings.TrimSpace(response))
|
||||
|
||||
switch response {
|
||||
case "y", "yes":
|
||||
if response == "y" || response == "yes" {
|
||||
return true
|
||||
case "n", "no":
|
||||
} else if response == "n" || response == "no" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,10 @@ import "go.uber.org/zap"
|
|||
type ConfigProvider interface {
|
||||
Args() string
|
||||
HelmBinary() string
|
||||
KustomizeBinary() string
|
||||
EnableLiveOutput() bool
|
||||
StripArgsValuesOnExitError() bool
|
||||
DisableForceUpdate() bool
|
||||
SkipDeps() bool
|
||||
SkipRefresh() bool
|
||||
|
||||
FileOrDir() string
|
||||
KubeContext() string
|
||||
|
|
@ -19,12 +17,20 @@ type ConfigProvider interface {
|
|||
Selectors() []string
|
||||
StateValuesSet() map[string]any
|
||||
StateValuesFiles() []string
|
||||
Kubeconfig() string
|
||||
Env() string
|
||||
|
||||
loggingConfig
|
||||
}
|
||||
|
||||
// TODO: Remove this function once Helmfile v0.x
|
||||
type DeprecatedChartsConfigProvider interface {
|
||||
Values() []string
|
||||
|
||||
concurrencyConfig
|
||||
loggingConfig
|
||||
IncludeTransitiveNeeds() bool
|
||||
}
|
||||
|
||||
type DepsConfigProvider interface {
|
||||
Args() string
|
||||
SkipRepos() bool
|
||||
|
|
@ -41,20 +47,13 @@ type ReposConfigProvider interface {
|
|||
type ApplyConfigProvider interface {
|
||||
Args() string
|
||||
PostRenderer() string
|
||||
PostRendererArgs() []string
|
||||
SkipSchemaValidation() bool
|
||||
Cascade() string
|
||||
HideNotes() bool
|
||||
TakeOwnership() bool
|
||||
SuppressOutputLineRegex() []string
|
||||
|
||||
Values() []string
|
||||
Set() []string
|
||||
SkipCRDs() bool
|
||||
SkipDeps() bool
|
||||
SkipRefresh() bool
|
||||
Wait() bool
|
||||
WaitRetries() int
|
||||
WaitForJobs() bool
|
||||
|
||||
IncludeTests() bool
|
||||
|
|
@ -73,15 +72,13 @@ type ApplyConfigProvider interface {
|
|||
Context() int
|
||||
DiffOutput() string
|
||||
|
||||
// TODO: Remove this function once Helmfile v0.x
|
||||
RetainValuesFiles() bool
|
||||
|
||||
Validate() bool
|
||||
SkipCleanup() bool
|
||||
SkipDiffOnInstall() bool
|
||||
|
||||
DiffArgs() string
|
||||
SyncArgs() string
|
||||
|
||||
SyncReleaseLabels() bool
|
||||
|
||||
DAGConfig
|
||||
|
||||
concurrencyConfig
|
||||
|
|
@ -93,30 +90,20 @@ type ApplyConfigProvider interface {
|
|||
type SyncConfigProvider interface {
|
||||
Args() string
|
||||
PostRenderer() string
|
||||
SkipSchemaValidation() bool
|
||||
PostRendererArgs() []string
|
||||
HideNotes() bool
|
||||
TakeOwnership() bool
|
||||
Cascade() string
|
||||
|
||||
Values() []string
|
||||
Set() []string
|
||||
SkipCRDs() bool
|
||||
SkipDeps() bool
|
||||
SkipRefresh() bool
|
||||
Wait() bool
|
||||
WaitRetries() int
|
||||
WaitForJobs() bool
|
||||
SyncArgs() string
|
||||
|
||||
Validate() bool
|
||||
|
||||
SkipNeeds() bool
|
||||
IncludeNeeds() bool
|
||||
IncludeTransitiveNeeds() bool
|
||||
|
||||
SyncReleaseLabels() bool
|
||||
|
||||
DAGConfig
|
||||
|
||||
concurrencyConfig
|
||||
|
|
@ -128,16 +115,12 @@ type SyncConfigProvider interface {
|
|||
type DiffConfigProvider interface {
|
||||
Args() string
|
||||
PostRenderer() string
|
||||
PostRendererArgs() []string
|
||||
SkipSchemaValidation() bool
|
||||
SuppressOutputLineRegex() []string
|
||||
|
||||
Values() []string
|
||||
Set() []string
|
||||
Validate() bool
|
||||
SkipCRDs() bool
|
||||
SkipDeps() bool
|
||||
SkipRefresh() bool
|
||||
|
||||
IncludeTests() bool
|
||||
|
||||
|
|
@ -147,7 +130,6 @@ type DiffConfigProvider interface {
|
|||
NoHooks() bool
|
||||
SuppressDiff() bool
|
||||
SkipDiffOnInstall() bool
|
||||
DiffArgs() string
|
||||
|
||||
DAGConfig
|
||||
|
||||
|
|
@ -157,21 +139,31 @@ type DiffConfigProvider interface {
|
|||
NoColor() bool
|
||||
Context() int
|
||||
DiffOutput() string
|
||||
TakeOwnership() bool
|
||||
|
||||
concurrencyConfig
|
||||
valuesControlMode
|
||||
}
|
||||
|
||||
// TODO: Remove this function once Helmfile v0.x
|
||||
type DeleteConfigProvider interface {
|
||||
Args() string
|
||||
Cascade() string
|
||||
|
||||
Purge() bool
|
||||
SkipDeps() bool
|
||||
SkipCharts() bool
|
||||
|
||||
interactive
|
||||
loggingConfig
|
||||
concurrencyConfig
|
||||
}
|
||||
|
||||
type DestroyConfigProvider interface {
|
||||
Args() string
|
||||
Cascade() string
|
||||
|
||||
SkipDeps() bool
|
||||
SkipRefresh() bool
|
||||
SkipCharts() bool
|
||||
DeleteWait() bool
|
||||
DeleteTimeout() int
|
||||
|
||||
interactive
|
||||
loggingConfig
|
||||
|
|
@ -182,7 +174,6 @@ type TestConfigProvider interface {
|
|||
Args() string
|
||||
|
||||
SkipDeps() bool
|
||||
SkipRefresh() bool
|
||||
Timeout() int
|
||||
Cleanup() bool
|
||||
Logs() bool
|
||||
|
|
@ -196,7 +187,6 @@ type LintConfigProvider interface {
|
|||
Values() []string
|
||||
Set() []string
|
||||
SkipDeps() bool
|
||||
SkipRefresh() bool
|
||||
SkipCleanup() bool
|
||||
|
||||
DAGConfig
|
||||
|
|
@ -206,7 +196,6 @@ type LintConfigProvider interface {
|
|||
|
||||
type FetchConfigProvider interface {
|
||||
SkipDeps() bool
|
||||
SkipRefresh() bool
|
||||
OutputDir() string
|
||||
OutputDirTemplate() string
|
||||
|
||||
|
|
@ -216,22 +205,17 @@ type FetchConfigProvider interface {
|
|||
type TemplateConfigProvider interface {
|
||||
Args() string
|
||||
PostRenderer() string
|
||||
PostRendererArgs() []string
|
||||
SkipSchemaValidation() bool
|
||||
|
||||
Values() []string
|
||||
Set() []string
|
||||
OutputDirTemplate() string
|
||||
Validate() bool
|
||||
SkipDeps() bool
|
||||
SkipRefresh() bool
|
||||
SkipCleanup() bool
|
||||
SkipTests() bool
|
||||
OutputDir() string
|
||||
IncludeCRDs() bool
|
||||
NoHooks() bool
|
||||
KubeVersion() string
|
||||
ShowOnly() []string
|
||||
|
||||
DAGConfig
|
||||
|
||||
|
|
@ -249,7 +233,6 @@ type WriteValuesConfigProvider interface {
|
|||
Set() []string
|
||||
OutputFileTemplate() string
|
||||
SkipDeps() bool
|
||||
SkipRefresh() bool
|
||||
SkipCleanup() bool
|
||||
IncludeTransitiveNeeds() bool
|
||||
|
||||
|
|
@ -266,8 +249,6 @@ type StateConfigProvider interface {
|
|||
EmbedValues() bool
|
||||
}
|
||||
|
||||
type DAGConfigProvider any
|
||||
|
||||
type concurrencyConfig interface {
|
||||
Concurrency() int
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
DefaultHelmfile = "helmfile.yaml"
|
||||
DefaultHelmfile = "helmfile.yaml"
|
||||
// TODO: Remove this function once Helmfile v0.x
|
||||
DeprecatedHelmfile = "charts.yaml"
|
||||
|
||||
DefaultHelmfileDirectory = "helmfile.d"
|
||||
ExperimentalSelectorExplicit = "explicit-selector-inheritance" // value to remove default selector inheritance to sub-helmfiles and use the explicit one
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,147 +0,0 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/helmfile/vals"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
|
||||
ffs "github.com/helmfile/helmfile/pkg/filesystem"
|
||||
"github.com/helmfile/helmfile/pkg/testhelper"
|
||||
"github.com/helmfile/helmfile/pkg/testutil"
|
||||
)
|
||||
|
||||
func testDAG(t *testing.T, cfg configImpl) {
|
||||
type testcase struct {
|
||||
environment string
|
||||
ns string
|
||||
error string
|
||||
selectors []string
|
||||
expected string
|
||||
}
|
||||
|
||||
check := func(t *testing.T, tc testcase, cfg configImpl) {
|
||||
t.Helper()
|
||||
|
||||
bs := runWithLogCapture(t, "debug", func(t *testing.T, logger *zap.SugaredLogger) {
|
||||
t.Helper()
|
||||
|
||||
valsRuntime, err := vals.New(vals.Options{CacheSize: 32})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error creating vals runtime: %v", err)
|
||||
}
|
||||
|
||||
files := map[string]string{
|
||||
"/path/to/helmfile.yaml": `
|
||||
environments:
|
||||
development: {}
|
||||
shared: {}
|
||||
---
|
||||
releases:
|
||||
- name: logging
|
||||
chart: incubator/raw
|
||||
namespace: kube-system
|
||||
- name: kubernetes-external-secrets
|
||||
chart: incubator/raw
|
||||
namespace: kube-system
|
||||
needs:
|
||||
- kube-system/logging
|
||||
- name: external-secrets
|
||||
chart: incubator/raw
|
||||
namespace: default
|
||||
labels:
|
||||
app: test
|
||||
needs:
|
||||
- kube-system/kubernetes-external-secrets
|
||||
- name: my-release
|
||||
chart: incubator/raw
|
||||
namespace: default
|
||||
labels:
|
||||
app: test
|
||||
needs:
|
||||
- default/external-secrets
|
||||
# Disabled releases are treated as missing
|
||||
- name: disabled
|
||||
chart: incubator/raw
|
||||
namespace: kube-system
|
||||
installed: false
|
||||
- name: test2
|
||||
chart: incubator/raw
|
||||
needs:
|
||||
- kube-system/disabled
|
||||
- name: test3
|
||||
chart: incubator/raw
|
||||
needs:
|
||||
- test2
|
||||
- name: test4
|
||||
chart: incubator/raw
|
||||
needs:
|
||||
- test2
|
||||
- test3
|
||||
`,
|
||||
}
|
||||
|
||||
app := appWithFs(&App{
|
||||
OverrideHelmBinary: DefaultHelmBinary,
|
||||
fs: ffs.DefaultFileSystem(),
|
||||
OverrideKubeContext: "default",
|
||||
Env: tc.environment,
|
||||
Logger: logger,
|
||||
valsRuntime: valsRuntime,
|
||||
}, files)
|
||||
|
||||
expectNoCallsToHelm(app)
|
||||
|
||||
if tc.ns != "" {
|
||||
app.Namespace = tc.ns
|
||||
}
|
||||
|
||||
if tc.selectors != nil {
|
||||
app.Selectors = tc.selectors
|
||||
}
|
||||
|
||||
var dagErr error
|
||||
out, err := testutil.CaptureStdout(func() {
|
||||
dagErr = app.PrintDAGState(cfg)
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
var gotErr string
|
||||
if dagErr != nil {
|
||||
gotErr = dagErr.Error()
|
||||
}
|
||||
|
||||
if d := cmp.Diff(tc.error, gotErr); d != "" {
|
||||
t.Fatalf("unexpected error: want (-), got (+): %s", d)
|
||||
}
|
||||
|
||||
assert.Equal(t, tc.expected, out)
|
||||
})
|
||||
|
||||
testhelper.RequireLog(t, "dag_test", bs)
|
||||
}
|
||||
|
||||
t.Run("DAG lists dependencies in order", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
environment: "default",
|
||||
expected: `GROUP RELEASE DEPENDENCIES
|
||||
1 default/kube-system/logging
|
||||
1 default/kube-system/disabled
|
||||
2 default/kube-system/kubernetes-external-secrets default/kube-system/logging
|
||||
2 default//test2 default/kube-system/disabled
|
||||
3 default/default/external-secrets default/kube-system/kubernetes-external-secrets
|
||||
3 default//test3 default//test2
|
||||
4 default/default/my-release default/default/external-secrets
|
||||
4 default//test4 default//test2, default//test3
|
||||
`,
|
||||
}, cfg)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDAG(t *testing.T) {
|
||||
t.Run("DAG", func(t *testing.T) {
|
||||
testDAG(t, configImpl{})
|
||||
})
|
||||
}
|
||||
|
|
@ -5,37 +5,34 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
|
||||
"dario.cat/mergo"
|
||||
"github.com/helmfile/vals"
|
||||
"github.com/imdario/mergo"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/environment"
|
||||
"github.com/helmfile/helmfile/pkg/filesystem"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/policy"
|
||||
"github.com/helmfile/helmfile/pkg/remote"
|
||||
"github.com/helmfile/helmfile/pkg/runtime"
|
||||
"github.com/helmfile/helmfile/pkg/state"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultHelmBinary = state.DefaultHelmBinary
|
||||
DefaultKustomizeBinary = state.DefaultKustomizeBinary
|
||||
DefaultHelmBinary = state.DefaultHelmBinary
|
||||
)
|
||||
|
||||
type desiredStateLoader struct {
|
||||
overrideKubeContext string
|
||||
overrideHelmBinary string
|
||||
overrideKustomizeBinary string
|
||||
enableLiveOutput bool
|
||||
overrideKubeContext string
|
||||
overrideHelmBinary string
|
||||
enableLiveOutput bool
|
||||
|
||||
env string
|
||||
namespace string
|
||||
chart string
|
||||
fs *filesystem.FileSystem
|
||||
|
||||
getHelm func(*state.HelmState) (helmexec.Interface, error)
|
||||
getHelm func(*state.HelmState) helmexec.Interface
|
||||
|
||||
remote *remote.Remote
|
||||
logger *zap.SugaredLogger
|
||||
|
|
@ -154,7 +151,7 @@ func (ld *desiredStateLoader) loadFileWithOverrides(inheritedEnv, overrodeEnv *e
|
|||
}
|
||||
|
||||
func (a *desiredStateLoader) underlying() *state.StateCreator {
|
||||
c := state.NewCreator(a.logger, a.fs, a.valsRuntime, a.getHelm, a.overrideHelmBinary, a.overrideKustomizeBinary, a.remote, a.enableLiveOutput, a.lockFilePath)
|
||||
c := state.NewCreator(a.logger, a.fs, a.valsRuntime, a.getHelm, a.overrideHelmBinary, a.remote, a.enableLiveOutput, a.lockFilePath)
|
||||
c.LoadFile = a.loadFile
|
||||
return c
|
||||
}
|
||||
|
|
@ -162,14 +159,21 @@ func (a *desiredStateLoader) underlying() *state.StateCreator {
|
|||
func (a *desiredStateLoader) rawLoad(yaml []byte, baseDir, file string, evaluateBases bool, env, overrodeEnv *environment.Environment) (*state.HelmState, error) {
|
||||
var st *state.HelmState
|
||||
var err error
|
||||
merged, err := env.Merge(overrodeEnv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if runtime.V1Mode {
|
||||
st, err = a.underlying().ParseAndLoad(yaml, baseDir, file, a.env, false, evaluateBases, env, overrodeEnv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
merged, err := env.Merge(overrodeEnv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
st, err = a.underlying().ParseAndLoad(yaml, baseDir, file, a.env, false, evaluateBases, merged, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
st, err = a.underlying().ParseAndLoad(yaml, baseDir, file, a.env, false, evaluateBases, merged, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
helmfiles, err := st.ExpandedHelmfiles()
|
||||
if err != nil {
|
||||
|
|
@ -183,16 +187,8 @@ func (a *desiredStateLoader) rawLoad(yaml []byte, baseDir, file string, evaluate
|
|||
func (ld *desiredStateLoader) load(env, overrodeEnv *environment.Environment, baseDir, filename string, content []byte, evaluateBases bool) (*state.HelmState, error) {
|
||||
// Allows part-splitting to work with CLRF-ed content
|
||||
normalizedContent := bytes.ReplaceAll(content, []byte("\r\n"), []byte("\n"))
|
||||
isStrict, err := policy.Checker(filename, normalizedContent)
|
||||
if err != nil {
|
||||
if isStrict {
|
||||
return nil, err
|
||||
}
|
||||
ld.logger.Warnf("WARNING: %v", err)
|
||||
}
|
||||
parts := bytes.Split(normalizedContent, []byte("\n---\n"))
|
||||
|
||||
hasEnv := env != nil || overrodeEnv != nil
|
||||
var finalState *state.HelmState
|
||||
|
||||
for i, part := range parts {
|
||||
|
|
@ -200,7 +196,7 @@ func (ld *desiredStateLoader) load(env, overrodeEnv *environment.Environment, ba
|
|||
|
||||
var rawContent []byte
|
||||
|
||||
if filepath.Ext(filename) == ".gotmpl" {
|
||||
if filepath.Ext(filename) == ".gotmpl" || !runtime.V1Mode {
|
||||
var yamlBuf *bytes.Buffer
|
||||
var err error
|
||||
|
||||
|
|
@ -242,62 +238,23 @@ func (ld *desiredStateLoader) load(env, overrodeEnv *environment.Environment, ba
|
|||
finalState.RenderedValues = currentState.RenderedValues
|
||||
}
|
||||
|
||||
if len(finalState.HelmDefaults.PostRendererArgs) > 0 {
|
||||
for i := range finalState.Releases {
|
||||
if len(finalState.Releases[i].PostRendererArgs) == 0 {
|
||||
finalState.Releases[i].PostRendererArgs = finalState.HelmDefaults.PostRendererArgs
|
||||
}
|
||||
}
|
||||
finalState.HelmDefaults.PostRendererArgs = nil
|
||||
}
|
||||
env = &finalState.Env
|
||||
|
||||
ld.logger.Debugf("merged environment: %v", env)
|
||||
|
||||
if len(finalState.Environments) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// At this point, we are sure that the env has been
|
||||
// read from the vanilla or rendered YAML document.
|
||||
// We can now check if the env is defined in it and fail accordingly.
|
||||
// See https://github.com/helmfile/helmfile/issues/913
|
||||
|
||||
// We defer the missing env detection and failure until
|
||||
// all the helmfile parts are loaded and merged.
|
||||
// Otherwise, any single helmfile part missing the env would fail the whole helmfile run.
|
||||
// That's problematic, because each helmfile part is supposed to be incomplete, and
|
||||
// they become complete only after merging all the parts.
|
||||
// See https://github.com/helmfile/helmfile/issues/807 for the rationale of this.
|
||||
if _, ok := finalState.Environments[env.Name]; evaluateBases && env.Name != state.DefaultEnv && !ok {
|
||||
return nil, &state.StateLoadError{
|
||||
Msg: fmt.Sprintf("failed to read %s", finalState.FilePath),
|
||||
Cause: &state.UndefinedEnvError{Env: env.Name},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If environments are not defined in the helmfile at all although the env is specified,
|
||||
// it's a missing env situation. Let's fail.
|
||||
if len(finalState.Environments) == 0 && evaluateBases && !hasEnv && env.Name != state.DefaultEnv {
|
||||
// We defer the missing env detection and failure until
|
||||
// all the helmfile parts are loaded and merged.
|
||||
// Otherwise, any single helmfile part missing the env would fail the whole helmfile run.
|
||||
// That's problematic, because each helmfile part is supposed to be incomplete, and
|
||||
// they become complete only after merging all the parts.
|
||||
// See https://github.com/helmfile/helmfile/issues/807 for the rationale of this.
|
||||
if _, ok := finalState.Environments[env.Name]; evaluateBases && env.Name != state.DefaultEnv && !ok {
|
||||
return nil, &state.StateLoadError{
|
||||
Msg: fmt.Sprintf("failed to read %s", finalState.FilePath),
|
||||
Cause: &state.UndefinedEnvError{Env: env.Name},
|
||||
}
|
||||
}
|
||||
|
||||
// Validate updateStrategy value if set in the releases
|
||||
for i := range finalState.Releases {
|
||||
if finalState.Releases[i].UpdateStrategy != "" {
|
||||
if !slices.Contains(state.ValidUpdateStrategyValues, finalState.Releases[i].UpdateStrategy) {
|
||||
return nil, &state.StateLoadError{
|
||||
Msg: fmt.Sprintf("failed to read %s", finalState.FilePath),
|
||||
Cause: &state.InvalidUpdateStrategyError{UpdateStrategy: finalState.Releases[i].UpdateStrategy},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finalState.OrginReleases = finalState.Releases
|
||||
return finalState, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/helmfile/vals"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/exectest"
|
||||
ffs "github.com/helmfile/helmfile/pkg/filesystem"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/testhelper"
|
||||
)
|
||||
|
||||
func TestDestroy_2(t *testing.T) {
|
||||
type testcase struct {
|
||||
ns string
|
||||
concurrency int
|
||||
error string
|
||||
files map[string]string
|
||||
selectors []string
|
||||
lists map[exectest.ListKey]string
|
||||
diffs map[exectest.DiffKey]error
|
||||
upgraded []exectest.Release
|
||||
deleted []exectest.Release
|
||||
log string
|
||||
deleteWait bool
|
||||
deleteTimeout int
|
||||
ns string
|
||||
concurrency int
|
||||
error string
|
||||
files map[string]string
|
||||
selectors []string
|
||||
lists map[exectest.ListKey]string
|
||||
diffs map[exectest.DiffKey]error
|
||||
upgraded []exectest.Release
|
||||
deleted []exectest.Release
|
||||
log string
|
||||
}
|
||||
|
||||
check := func(t *testing.T, tc testcase) {
|
||||
|
|
@ -79,8 +77,6 @@ func TestDestroy_2(t *testing.T) {
|
|||
concurrency: tc.concurrency,
|
||||
logger: logger,
|
||||
includeTransitiveNeeds: false,
|
||||
deleteWait: tc.deleteWait,
|
||||
deleteTimeout: tc.deleteTimeout,
|
||||
})
|
||||
|
||||
switch {
|
||||
|
|
@ -126,9 +122,10 @@ func TestDestroy_2(t *testing.T) {
|
|||
if tc.log != "" {
|
||||
actual := bs.String()
|
||||
|
||||
assert.Equal(t, tc.log, actual)
|
||||
} else {
|
||||
assertLogEqualsToSnapshot(t, bs.String())
|
||||
diff, exists := testhelper.Diff(tc.log, actual, 3)
|
||||
if exists {
|
||||
t.Errorf("unexpected log:\nDIFF\n%s\nEOD", diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -255,6 +252,171 @@ anotherbackend 4 Fri Nov 1 08:40:07 2019 DEPLOYED anotherbackend-3.1.0
|
|||
{Name: "front-proxy", Flags: []string{}},
|
||||
{Name: "logging", Flags: []string{}},
|
||||
},
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: database
|
||||
3: chart: charts/mysql
|
||||
4: needs:
|
||||
5: - logging
|
||||
6: - name: frontend-v1
|
||||
7: chart: charts/frontend
|
||||
8: installed: false
|
||||
9: needs:
|
||||
10: - servicemesh
|
||||
11: - logging
|
||||
12: - backend-v1
|
||||
13: - name: frontend-v2
|
||||
14: chart: charts/frontend
|
||||
15: needs:
|
||||
16: - servicemesh
|
||||
17: - logging
|
||||
18: - backend-v2
|
||||
19: - name: frontend-v3
|
||||
20: chart: charts/frontend
|
||||
21: needs:
|
||||
22: - servicemesh
|
||||
23: - logging
|
||||
24: - backend-v2
|
||||
25: - name: backend-v1
|
||||
26: chart: charts/backend
|
||||
27: installed: false
|
||||
28: needs:
|
||||
29: - servicemesh
|
||||
30: - logging
|
||||
31: - database
|
||||
32: - anotherbackend
|
||||
33: - name: backend-v2
|
||||
34: chart: charts/backend
|
||||
35: needs:
|
||||
36: - servicemesh
|
||||
37: - logging
|
||||
38: - database
|
||||
39: - anotherbackend
|
||||
40: - name: anotherbackend
|
||||
41: chart: charts/anotherbackend
|
||||
42: needs:
|
||||
43: - servicemesh
|
||||
44: - logging
|
||||
45: - database
|
||||
46: - name: servicemesh
|
||||
47: chart: charts/istio
|
||||
48: needs:
|
||||
49: - logging
|
||||
50: - name: logging
|
||||
51: chart: charts/fluent-bit
|
||||
52: - name: front-proxy
|
||||
53: chart: stable/envoy
|
||||
54:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: database
|
||||
3: chart: charts/mysql
|
||||
4: needs:
|
||||
5: - logging
|
||||
6: - name: frontend-v1
|
||||
7: chart: charts/frontend
|
||||
8: installed: false
|
||||
9: needs:
|
||||
10: - servicemesh
|
||||
11: - logging
|
||||
12: - backend-v1
|
||||
13: - name: frontend-v2
|
||||
14: chart: charts/frontend
|
||||
15: needs:
|
||||
16: - servicemesh
|
||||
17: - logging
|
||||
18: - backend-v2
|
||||
19: - name: frontend-v3
|
||||
20: chart: charts/frontend
|
||||
21: needs:
|
||||
22: - servicemesh
|
||||
23: - logging
|
||||
24: - backend-v2
|
||||
25: - name: backend-v1
|
||||
26: chart: charts/backend
|
||||
27: installed: false
|
||||
28: needs:
|
||||
29: - servicemesh
|
||||
30: - logging
|
||||
31: - database
|
||||
32: - anotherbackend
|
||||
33: - name: backend-v2
|
||||
34: chart: charts/backend
|
||||
35: needs:
|
||||
36: - servicemesh
|
||||
37: - logging
|
||||
38: - database
|
||||
39: - anotherbackend
|
||||
40: - name: anotherbackend
|
||||
41: chart: charts/anotherbackend
|
||||
42: needs:
|
||||
43: - servicemesh
|
||||
44: - logging
|
||||
45: - database
|
||||
46: - name: servicemesh
|
||||
47: chart: charts/istio
|
||||
48: needs:
|
||||
49: - logging
|
||||
50: - name: logging
|
||||
51: chart: charts/fluent-bit
|
||||
52: - name: front-proxy
|
||||
53: chart: stable/envoy
|
||||
54:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
10 release(s) found in helmfile.yaml
|
||||
|
||||
processing 5 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 frontend-v3, frontend-v2, frontend-v1
|
||||
2 backend-v2, backend-v1
|
||||
3 anotherbackend
|
||||
4 servicemesh, database
|
||||
5 front-proxy, logging
|
||||
|
||||
processing releases in group 1/5: frontend-v3, frontend-v2, frontend-v1
|
||||
release "frontend-v3" processed
|
||||
release "frontend-v2" processed
|
||||
release "frontend-v1" processed
|
||||
processing releases in group 2/5: backend-v2, backend-v1
|
||||
release "backend-v2" processed
|
||||
release "backend-v1" processed
|
||||
processing releases in group 3/5: anotherbackend
|
||||
release "anotherbackend" processed
|
||||
processing releases in group 4/5: servicemesh, database
|
||||
release "servicemesh" processed
|
||||
release "database" processed
|
||||
processing releases in group 5/5: front-proxy, logging
|
||||
release "front-proxy" processed
|
||||
release "logging" processed
|
||||
|
||||
DELETED RELEASES:
|
||||
NAME DURATION
|
||||
frontend-v3 0s
|
||||
frontend-v2 0s
|
||||
frontend-v1 0s
|
||||
backend-v2 0s
|
||||
backend-v1 0s
|
||||
anotherbackend 0s
|
||||
servicemesh 0s
|
||||
database 0s
|
||||
front-proxy 0s
|
||||
logging 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -293,15 +455,151 @@ database 4 Fri Nov 1 08:40:07 2019 DEPLOYED mysql-3.1.0 3.1.0 def
|
|||
anotherbackend 4 Fri Nov 1 08:40:07 2019 DEPLOYED anotherbackend-3.1.0 3.1.0 default
|
||||
`,
|
||||
},
|
||||
// Enable wait and set timeout for destroy
|
||||
deleteWait: true,
|
||||
deleteTimeout: 300,
|
||||
// Disable concurrency to avoid in-deterministic result
|
||||
concurrency: 1,
|
||||
upgraded: []exectest.Release{},
|
||||
deleted: []exectest.Release{
|
||||
{Name: "logging", Flags: []string{}},
|
||||
},
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: database
|
||||
3: chart: charts/mysql
|
||||
4: needs:
|
||||
5: - logging
|
||||
6: - name: frontend-v1
|
||||
7: chart: charts/frontend
|
||||
8: installed: false
|
||||
9: needs:
|
||||
10: - servicemesh
|
||||
11: - logging
|
||||
12: - backend-v1
|
||||
13: - name: frontend-v2
|
||||
14: chart: charts/frontend
|
||||
15: needs:
|
||||
16: - servicemesh
|
||||
17: - logging
|
||||
18: - backend-v2
|
||||
19: - name: frontend-v3
|
||||
20: chart: charts/frontend
|
||||
21: needs:
|
||||
22: - servicemesh
|
||||
23: - logging
|
||||
24: - backend-v2
|
||||
25: - name: backend-v1
|
||||
26: chart: charts/backend
|
||||
27: installed: false
|
||||
28: needs:
|
||||
29: - servicemesh
|
||||
30: - logging
|
||||
31: - database
|
||||
32: - anotherbackend
|
||||
33: - name: backend-v2
|
||||
34: chart: charts/backend
|
||||
35: needs:
|
||||
36: - servicemesh
|
||||
37: - logging
|
||||
38: - database
|
||||
39: - anotherbackend
|
||||
40: - name: anotherbackend
|
||||
41: chart: charts/anotherbackend
|
||||
42: needs:
|
||||
43: - servicemesh
|
||||
44: - logging
|
||||
45: - database
|
||||
46: - name: servicemesh
|
||||
47: chart: charts/istio
|
||||
48: needs:
|
||||
49: - logging
|
||||
50: - name: logging
|
||||
51: chart: charts/fluent-bit
|
||||
52: - name: front-proxy
|
||||
53: chart: stable/envoy
|
||||
54:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: database
|
||||
3: chart: charts/mysql
|
||||
4: needs:
|
||||
5: - logging
|
||||
6: - name: frontend-v1
|
||||
7: chart: charts/frontend
|
||||
8: installed: false
|
||||
9: needs:
|
||||
10: - servicemesh
|
||||
11: - logging
|
||||
12: - backend-v1
|
||||
13: - name: frontend-v2
|
||||
14: chart: charts/frontend
|
||||
15: needs:
|
||||
16: - servicemesh
|
||||
17: - logging
|
||||
18: - backend-v2
|
||||
19: - name: frontend-v3
|
||||
20: chart: charts/frontend
|
||||
21: needs:
|
||||
22: - servicemesh
|
||||
23: - logging
|
||||
24: - backend-v2
|
||||
25: - name: backend-v1
|
||||
26: chart: charts/backend
|
||||
27: installed: false
|
||||
28: needs:
|
||||
29: - servicemesh
|
||||
30: - logging
|
||||
31: - database
|
||||
32: - anotherbackend
|
||||
33: - name: backend-v2
|
||||
34: chart: charts/backend
|
||||
35: needs:
|
||||
36: - servicemesh
|
||||
37: - logging
|
||||
38: - database
|
||||
39: - anotherbackend
|
||||
40: - name: anotherbackend
|
||||
41: chart: charts/anotherbackend
|
||||
42: needs:
|
||||
43: - servicemesh
|
||||
44: - logging
|
||||
45: - database
|
||||
46: - name: servicemesh
|
||||
47: chart: charts/istio
|
||||
48: needs:
|
||||
49: - logging
|
||||
50: - name: logging
|
||||
51: chart: charts/fluent-bit
|
||||
52: - name: front-proxy
|
||||
53: chart: stable/envoy
|
||||
54:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
1 release(s) matching name=logging found in helmfile.yaml
|
||||
|
||||
processing 1 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 logging
|
||||
|
||||
processing releases in group 1/1: logging
|
||||
release "logging" processed
|
||||
|
||||
DELETED RELEASES:
|
||||
NAME DURATION
|
||||
logging 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -321,6 +619,59 @@ anotherbackend 4 Fri Nov 1 08:40:07 2019 DEPLOYED anotherbackend-3.1.0
|
|||
deleted: []exectest.Release{
|
||||
{Name: "frontend-v1", Flags: []string{}},
|
||||
},
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: backend-v1
|
||||
3: chart: charts/backend
|
||||
4: installed: false
|
||||
5: - name: frontend-v1
|
||||
6: chart: charts/frontend
|
||||
7: needs:
|
||||
8: - backend-v1
|
||||
9:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: backend-v1
|
||||
3: chart: charts/backend
|
||||
4: installed: false
|
||||
5: - name: frontend-v1
|
||||
6: chart: charts/frontend
|
||||
7: needs:
|
||||
8: - backend-v1
|
||||
9:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 frontend-v1
|
||||
2 backend-v1
|
||||
|
||||
processing releases in group 1/2: frontend-v1
|
||||
release "frontend-v1" processed
|
||||
processing releases in group 2/2: backend-v1
|
||||
release "backend-v1" processed
|
||||
|
||||
DELETED RELEASES:
|
||||
NAME DURATION
|
||||
frontend-v1 0s
|
||||
backend-v1 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -340,6 +691,59 @@ anotherbackend 4 Fri Nov 1 08:40:07 2019 DEPLOYED anotherbackend-3.1.0
|
|||
deleted: []exectest.Release{
|
||||
{Name: "frontend-v1", Flags: []string{}},
|
||||
},
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: backend-v1
|
||||
3: chart: charts/backend
|
||||
4: installed: false
|
||||
5: - name: frontend-v1
|
||||
6: chart: charts/frontend
|
||||
7: needs:
|
||||
8: - backend-v1
|
||||
9:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: backend-v1
|
||||
3: chart: charts/backend
|
||||
4: installed: false
|
||||
5: - name: frontend-v1
|
||||
6: chart: charts/frontend
|
||||
7: needs:
|
||||
8: - backend-v1
|
||||
9:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 frontend-v1
|
||||
2 backend-v1
|
||||
|
||||
processing releases in group 1/2: frontend-v1
|
||||
release "frontend-v1" processed
|
||||
processing releases in group 2/2: backend-v1
|
||||
release "backend-v1" processed
|
||||
|
||||
DELETED RELEASES:
|
||||
NAME DURATION
|
||||
frontend-v1 0s
|
||||
backend-v1 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,17 +6,17 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/helmfile/vals"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/exectest"
|
||||
ffs "github.com/helmfile/helmfile/pkg/filesystem"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/testhelper"
|
||||
)
|
||||
|
||||
const (
|
||||
helmV3ListFlags = "--kube-context default --uninstalling --deployed --failed --pending"
|
||||
helmV3ListFlagsWithoutKubeContext = "--uninstalling --deployed --failed --pending"
|
||||
helmV3ListFlags = "--kube-contextdefault--uninstalling--deployed--failed--pending"
|
||||
helmV3ListFlagsWithoutKubeContext = "--uninstalling--deployed--failed--pending"
|
||||
)
|
||||
|
||||
func listFlags(namespace, kubeContext string) string {
|
||||
|
|
@ -27,9 +27,9 @@ func listFlags(namespace, kubeContext string) string {
|
|||
if namespace != "" {
|
||||
flags = append(flags, "--namespace", namespace)
|
||||
}
|
||||
flags = append(flags, "--uninstalling --deployed --failed --pending")
|
||||
flags = append(flags, "--uninstalling--deployed--failed--pending")
|
||||
|
||||
return strings.Join(flags, " ")
|
||||
return strings.Join(flags, "")
|
||||
}
|
||||
|
||||
type destroyConfig struct {
|
||||
|
|
@ -38,12 +38,9 @@ type destroyConfig struct {
|
|||
concurrency int
|
||||
interactive bool
|
||||
skipDeps bool
|
||||
skipRefresh bool
|
||||
logger *zap.SugaredLogger
|
||||
includeTransitiveNeeds bool
|
||||
skipCharts bool
|
||||
deleteWait bool
|
||||
deleteTimeout int
|
||||
}
|
||||
|
||||
func (d destroyConfig) Args() string {
|
||||
|
|
@ -74,36 +71,22 @@ func (d destroyConfig) SkipDeps() bool {
|
|||
return d.skipDeps
|
||||
}
|
||||
|
||||
func (d destroyConfig) SkipRefresh() bool {
|
||||
return d.skipRefresh
|
||||
}
|
||||
|
||||
func (d destroyConfig) IncludeTransitiveNeeds() bool {
|
||||
return d.includeTransitiveNeeds
|
||||
}
|
||||
|
||||
func (d destroyConfig) DeleteWait() bool {
|
||||
return d.deleteWait
|
||||
}
|
||||
|
||||
func (d destroyConfig) DeleteTimeout() int {
|
||||
return d.deleteTimeout
|
||||
}
|
||||
|
||||
func TestDestroy(t *testing.T) {
|
||||
type testcase struct {
|
||||
ns string
|
||||
concurrency int
|
||||
error string
|
||||
files map[string]string
|
||||
selectors []string
|
||||
lists map[exectest.ListKey]string
|
||||
diffs map[exectest.DiffKey]error
|
||||
upgraded []exectest.Release
|
||||
deleted []exectest.Release
|
||||
log string
|
||||
deleteWait bool
|
||||
deleteTimeout int
|
||||
ns string
|
||||
concurrency int
|
||||
error string
|
||||
files map[string]string
|
||||
selectors []string
|
||||
lists map[exectest.ListKey]string
|
||||
diffs map[exectest.DiffKey]error
|
||||
upgraded []exectest.Release
|
||||
deleted []exectest.Release
|
||||
log string
|
||||
}
|
||||
|
||||
check := func(t *testing.T, tc testcase) {
|
||||
|
|
@ -200,9 +183,10 @@ func TestDestroy(t *testing.T) {
|
|||
if tc.log != "" {
|
||||
actual := bs.String()
|
||||
|
||||
assert.Equal(t, tc.log, actual)
|
||||
} else {
|
||||
assertLogEqualsToSnapshot(t, bs.String())
|
||||
diff, exists := testhelper.Diff(tc.log, actual, 3)
|
||||
if exists {
|
||||
t.Errorf("unexpected log:\nDIFF\n%s\nEOD", diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -316,10 +300,7 @@ anotherbackend 4 Fri Nov 1 08:40:07 2019 DEPLOYED anotherbackend-3.1.0
|
|||
},
|
||||
// Disable concurrency to avoid in-deterministic result
|
||||
concurrency: 1,
|
||||
// Enable wait and set timeout for destroy
|
||||
deleteWait: true,
|
||||
deleteTimeout: 300,
|
||||
upgraded: []exectest.Release{},
|
||||
upgraded: []exectest.Release{},
|
||||
deleted: []exectest.Release{
|
||||
{Name: "frontend-v3", Flags: []string{}},
|
||||
{Name: "frontend-v2", Flags: []string{}},
|
||||
|
|
@ -332,6 +313,171 @@ anotherbackend 4 Fri Nov 1 08:40:07 2019 DEPLOYED anotherbackend-3.1.0
|
|||
{Name: "front-proxy", Flags: []string{}},
|
||||
{Name: "logging", Flags: []string{}},
|
||||
},
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: database
|
||||
3: chart: charts/mysql
|
||||
4: needs:
|
||||
5: - logging
|
||||
6: - name: frontend-v1
|
||||
7: chart: charts/frontend
|
||||
8: installed: false
|
||||
9: needs:
|
||||
10: - servicemesh
|
||||
11: - logging
|
||||
12: - backend-v1
|
||||
13: - name: frontend-v2
|
||||
14: chart: charts/frontend
|
||||
15: needs:
|
||||
16: - servicemesh
|
||||
17: - logging
|
||||
18: - backend-v2
|
||||
19: - name: frontend-v3
|
||||
20: chart: charts/frontend
|
||||
21: needs:
|
||||
22: - servicemesh
|
||||
23: - logging
|
||||
24: - backend-v2
|
||||
25: - name: backend-v1
|
||||
26: chart: charts/backend
|
||||
27: installed: false
|
||||
28: needs:
|
||||
29: - servicemesh
|
||||
30: - logging
|
||||
31: - database
|
||||
32: - anotherbackend
|
||||
33: - name: backend-v2
|
||||
34: chart: charts/backend
|
||||
35: needs:
|
||||
36: - servicemesh
|
||||
37: - logging
|
||||
38: - database
|
||||
39: - anotherbackend
|
||||
40: - name: anotherbackend
|
||||
41: chart: charts/anotherbackend
|
||||
42: needs:
|
||||
43: - servicemesh
|
||||
44: - logging
|
||||
45: - database
|
||||
46: - name: servicemesh
|
||||
47: chart: charts/istio
|
||||
48: needs:
|
||||
49: - logging
|
||||
50: - name: logging
|
||||
51: chart: charts/fluent-bit
|
||||
52: - name: front-proxy
|
||||
53: chart: stable/envoy
|
||||
54:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: database
|
||||
3: chart: charts/mysql
|
||||
4: needs:
|
||||
5: - logging
|
||||
6: - name: frontend-v1
|
||||
7: chart: charts/frontend
|
||||
8: installed: false
|
||||
9: needs:
|
||||
10: - servicemesh
|
||||
11: - logging
|
||||
12: - backend-v1
|
||||
13: - name: frontend-v2
|
||||
14: chart: charts/frontend
|
||||
15: needs:
|
||||
16: - servicemesh
|
||||
17: - logging
|
||||
18: - backend-v2
|
||||
19: - name: frontend-v3
|
||||
20: chart: charts/frontend
|
||||
21: needs:
|
||||
22: - servicemesh
|
||||
23: - logging
|
||||
24: - backend-v2
|
||||
25: - name: backend-v1
|
||||
26: chart: charts/backend
|
||||
27: installed: false
|
||||
28: needs:
|
||||
29: - servicemesh
|
||||
30: - logging
|
||||
31: - database
|
||||
32: - anotherbackend
|
||||
33: - name: backend-v2
|
||||
34: chart: charts/backend
|
||||
35: needs:
|
||||
36: - servicemesh
|
||||
37: - logging
|
||||
38: - database
|
||||
39: - anotherbackend
|
||||
40: - name: anotherbackend
|
||||
41: chart: charts/anotherbackend
|
||||
42: needs:
|
||||
43: - servicemesh
|
||||
44: - logging
|
||||
45: - database
|
||||
46: - name: servicemesh
|
||||
47: chart: charts/istio
|
||||
48: needs:
|
||||
49: - logging
|
||||
50: - name: logging
|
||||
51: chart: charts/fluent-bit
|
||||
52: - name: front-proxy
|
||||
53: chart: stable/envoy
|
||||
54:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
10 release(s) found in helmfile.yaml
|
||||
|
||||
processing 5 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default//frontend-v3, default//frontend-v2, default//frontend-v1
|
||||
2 default//backend-v2, default//backend-v1
|
||||
3 default//anotherbackend
|
||||
4 default//servicemesh, default//database
|
||||
5 default//front-proxy, default//logging
|
||||
|
||||
processing releases in group 1/5: default//frontend-v3, default//frontend-v2, default//frontend-v1
|
||||
release "frontend-v3" processed
|
||||
release "frontend-v2" processed
|
||||
release "frontend-v1" processed
|
||||
processing releases in group 2/5: default//backend-v2, default//backend-v1
|
||||
release "backend-v2" processed
|
||||
release "backend-v1" processed
|
||||
processing releases in group 3/5: default//anotherbackend
|
||||
release "anotherbackend" processed
|
||||
processing releases in group 4/5: default//servicemesh, default//database
|
||||
release "servicemesh" processed
|
||||
release "database" processed
|
||||
processing releases in group 5/5: default//front-proxy, default//logging
|
||||
release "front-proxy" processed
|
||||
release "logging" processed
|
||||
|
||||
DELETED RELEASES:
|
||||
NAME DURATION
|
||||
frontend-v3 0s
|
||||
frontend-v2 0s
|
||||
frontend-v1 0s
|
||||
backend-v2 0s
|
||||
backend-v1 0s
|
||||
anotherbackend 0s
|
||||
servicemesh 0s
|
||||
database 0s
|
||||
front-proxy 0s
|
||||
logging 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -376,6 +522,145 @@ anotherbackend 4 Fri Nov 1 08:40:07 2019 DEPLOYED anotherbackend-3.1.0
|
|||
deleted: []exectest.Release{
|
||||
{Name: "logging", Flags: []string{}},
|
||||
},
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: database
|
||||
3: chart: charts/mysql
|
||||
4: needs:
|
||||
5: - logging
|
||||
6: - name: frontend-v1
|
||||
7: chart: charts/frontend
|
||||
8: installed: false
|
||||
9: needs:
|
||||
10: - servicemesh
|
||||
11: - logging
|
||||
12: - backend-v1
|
||||
13: - name: frontend-v2
|
||||
14: chart: charts/frontend
|
||||
15: needs:
|
||||
16: - servicemesh
|
||||
17: - logging
|
||||
18: - backend-v2
|
||||
19: - name: frontend-v3
|
||||
20: chart: charts/frontend
|
||||
21: needs:
|
||||
22: - servicemesh
|
||||
23: - logging
|
||||
24: - backend-v2
|
||||
25: - name: backend-v1
|
||||
26: chart: charts/backend
|
||||
27: installed: false
|
||||
28: needs:
|
||||
29: - servicemesh
|
||||
30: - logging
|
||||
31: - database
|
||||
32: - anotherbackend
|
||||
33: - name: backend-v2
|
||||
34: chart: charts/backend
|
||||
35: needs:
|
||||
36: - servicemesh
|
||||
37: - logging
|
||||
38: - database
|
||||
39: - anotherbackend
|
||||
40: - name: anotherbackend
|
||||
41: chart: charts/anotherbackend
|
||||
42: needs:
|
||||
43: - servicemesh
|
||||
44: - logging
|
||||
45: - database
|
||||
46: - name: servicemesh
|
||||
47: chart: charts/istio
|
||||
48: needs:
|
||||
49: - logging
|
||||
50: - name: logging
|
||||
51: chart: charts/fluent-bit
|
||||
52: - name: front-proxy
|
||||
53: chart: stable/envoy
|
||||
54:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: database
|
||||
3: chart: charts/mysql
|
||||
4: needs:
|
||||
5: - logging
|
||||
6: - name: frontend-v1
|
||||
7: chart: charts/frontend
|
||||
8: installed: false
|
||||
9: needs:
|
||||
10: - servicemesh
|
||||
11: - logging
|
||||
12: - backend-v1
|
||||
13: - name: frontend-v2
|
||||
14: chart: charts/frontend
|
||||
15: needs:
|
||||
16: - servicemesh
|
||||
17: - logging
|
||||
18: - backend-v2
|
||||
19: - name: frontend-v3
|
||||
20: chart: charts/frontend
|
||||
21: needs:
|
||||
22: - servicemesh
|
||||
23: - logging
|
||||
24: - backend-v2
|
||||
25: - name: backend-v1
|
||||
26: chart: charts/backend
|
||||
27: installed: false
|
||||
28: needs:
|
||||
29: - servicemesh
|
||||
30: - logging
|
||||
31: - database
|
||||
32: - anotherbackend
|
||||
33: - name: backend-v2
|
||||
34: chart: charts/backend
|
||||
35: needs:
|
||||
36: - servicemesh
|
||||
37: - logging
|
||||
38: - database
|
||||
39: - anotherbackend
|
||||
40: - name: anotherbackend
|
||||
41: chart: charts/anotherbackend
|
||||
42: needs:
|
||||
43: - servicemesh
|
||||
44: - logging
|
||||
45: - database
|
||||
46: - name: servicemesh
|
||||
47: chart: charts/istio
|
||||
48: needs:
|
||||
49: - logging
|
||||
50: - name: logging
|
||||
51: chart: charts/fluent-bit
|
||||
52: - name: front-proxy
|
||||
53: chart: stable/envoy
|
||||
54:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
1 release(s) matching name=logging found in helmfile.yaml
|
||||
|
||||
processing 1 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default//logging
|
||||
|
||||
processing releases in group 1/1: default//logging
|
||||
release "logging" processed
|
||||
|
||||
DELETED RELEASES:
|
||||
NAME DURATION
|
||||
logging 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -395,6 +680,59 @@ anotherbackend 4 Fri Nov 1 08:40:07 2019 DEPLOYED anotherbackend-3.1.0
|
|||
deleted: []exectest.Release{
|
||||
{Name: "frontend-v1", Flags: []string{}},
|
||||
},
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: backend-v1
|
||||
3: chart: charts/backend
|
||||
4: installed: false
|
||||
5: - name: frontend-v1
|
||||
6: chart: charts/frontend
|
||||
7: needs:
|
||||
8: - backend-v1
|
||||
9:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: backend-v1
|
||||
3: chart: charts/backend
|
||||
4: installed: false
|
||||
5: - name: frontend-v1
|
||||
6: chart: charts/frontend
|
||||
7: needs:
|
||||
8: - backend-v1
|
||||
9:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default//frontend-v1
|
||||
2 default//backend-v1
|
||||
|
||||
processing releases in group 1/2: default//frontend-v1
|
||||
release "frontend-v1" processed
|
||||
processing releases in group 2/2: default//backend-v1
|
||||
release "backend-v1" processed
|
||||
|
||||
DELETED RELEASES:
|
||||
NAME DURATION
|
||||
frontend-v1 0s
|
||||
backend-v1 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -410,13 +748,63 @@ anotherbackend 4 Fri Nov 1 08:40:07 2019 DEPLOYED anotherbackend-3.1.0
|
|||
},
|
||||
// Disable concurrency to avoid in-deterministic result
|
||||
concurrency: 1,
|
||||
// Enable wait and set timeout for destroy
|
||||
deleteWait: true,
|
||||
deleteTimeout: 300,
|
||||
upgraded: []exectest.Release{},
|
||||
upgraded: []exectest.Release{},
|
||||
deleted: []exectest.Release{
|
||||
{Name: "frontend-v1", Flags: []string{}},
|
||||
},
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: backend-v1
|
||||
3: chart: charts/backend
|
||||
4: installed: false
|
||||
5: - name: frontend-v1
|
||||
6: chart: charts/frontend
|
||||
7: needs:
|
||||
8: - backend-v1
|
||||
9:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: backend-v1
|
||||
3: chart: charts/backend
|
||||
4: installed: false
|
||||
5: - name: frontend-v1
|
||||
6: chart: charts/frontend
|
||||
7: needs:
|
||||
8: - backend-v1
|
||||
9:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default//frontend-v1
|
||||
2 default//backend-v1
|
||||
|
||||
processing releases in group 1/2: default//frontend-v1
|
||||
release "frontend-v1" processed
|
||||
processing releases in group 2/2: default//backend-v1
|
||||
release "backend-v1" processed
|
||||
|
||||
DELETED RELEASES:
|
||||
NAME DURATION
|
||||
frontend-v1 0s
|
||||
backend-v1 0s
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/helmfile/vals"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/exectest"
|
||||
|
|
@ -104,16 +103,16 @@ releases:
|
|||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
// noop on frontend-v2
|
||||
{Name: "frontend-v2", Chart: "charts/frontend", Flags: "--reset-values --detailed-exitcode"}: nil,
|
||||
{Name: "frontend-v2", Chart: "charts/frontend", Flags: "--detailed-exitcode--reset-values"}: nil,
|
||||
// install frontend-v3
|
||||
{Name: "frontend-v3", Chart: "charts/frontend", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "frontend-v3", Chart: "charts/frontend", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
// upgrades
|
||||
{Name: "logging", Chart: "charts/fluent-bit", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "front-proxy", Chart: "stable/envoy", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "servicemesh", Chart: "charts/istio", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "database", Chart: "charts/mysql", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "backend-v2", Chart: "charts/backend", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "anotherbackend", Chart: "charts/anotherbackend", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "logging", Chart: "charts/fluent-bit", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "front-proxy", Chart: "stable/envoy", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "servicemesh", Chart: "charts/istio", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "database", Chart: "charts/mysql", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "backend-v2", Chart: "charts/backend", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "anotherbackend", Chart: "charts/anotherbackend", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
// delete frontend-v1 and backend-v1
|
||||
|
|
@ -150,7 +149,7 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--reset-values --detailed-exitcode"}: nil,
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--detailed-exitcode--reset-values"}: nil,
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: helmV3ListFlagsWithoutKubeContext}: ``,
|
||||
|
|
@ -183,9 +182,9 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "baz", Chart: "mychart3", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "baz", Chart: "mychart3", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{},
|
||||
upgraded: []exectest.Release{},
|
||||
|
|
@ -212,8 +211,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -234,8 +233,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -257,8 +256,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--namespace testNamespace --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--namespace testNamespace --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--namespacetestNamespace--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--namespacetestNamespace--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -280,8 +279,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--namespace testNamespace --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--namespace testNamespace --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--namespacetestNamespace--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--namespacetestNamespace--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -304,8 +303,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--namespace ns2 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--namespace ns1 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--namespacens2--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--namespacens1--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -328,8 +327,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--namespace ns2 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--namespace ns1 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--namespacens2--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--namespacens1--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -352,8 +351,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--namespace ns2 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--namespace ns1 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--namespacens2--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--namespacens1--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
|
|
@ -381,8 +380,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: helmV3ListFlagsWithoutKubeContext}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -413,8 +412,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: helmV3ListFlagsWithoutKubeContext}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -447,8 +446,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: helmV3ListFlagsWithoutKubeContext}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -479,8 +478,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: `in ./helmfile.yaml: release "foo" depends on "bar" which does not match the selectors. Please add a selector like "--selector name=bar", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`,
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: helmV3ListFlagsWithoutKubeContext}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -514,8 +513,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: helmV3ListFlagsWithoutKubeContext}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -549,8 +548,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: helmV3ListFlagsWithoutKubeContext}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -581,8 +580,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: `in ./helmfile.yaml: release "bar" depends on "foo" which does not match the selectors. Please add a selector like "--selector name=foo", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`,
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: helmV3ListFlagsWithoutKubeContext}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -613,8 +612,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: helmV3ListFlagsWithoutKubeContext}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -636,7 +635,7 @@ bar 4 Fri Nov 1 08:40:07 2019 DEPLOYED mychart2-3.1.0 3.1.0 defau
|
|||
loc: location(),
|
||||
flags: flags{skipNeeds: true},
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -664,8 +663,8 @@ releases:
|
|||
selectors: []string{"app=test"},
|
||||
detailedExitcode: true,
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
|
|
@ -677,7 +676,7 @@ releases:
|
|||
loc: location(),
|
||||
flags: flags{skipNeeds: false},
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -705,20 +704,87 @@ releases:
|
|||
selectors: []string{"app=test"},
|
||||
detailedExitcode: true,
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
error: `in ./helmfile.yaml.gotmpl: release "default/external-secrets" depends on "kube-system/kubernetes-external-secrets" which does not match the selectors. Please add a selector like "--selector name=kubernetes-external-secrets", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`,
|
||||
error: `in ./helmfile.yaml: release "default/external-secrets" depends on "kube-system/kubernetes-external-secrets" which does not match the selectors. Please add a selector like "--selector name=kubernetes-external-secrets", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
err: release "default/external-secrets" depends on "kube-system/kubernetes-external-secrets" which does not match the selectors. Please add a selector like "--selector name=kubernetes-external-secrets", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
},
|
||||
{
|
||||
// see https://github.com/roboll/helmfile/issues/919#issuecomment-549831747
|
||||
name: "upgrades with bad selector",
|
||||
loc: location(),
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -750,6 +816,72 @@ releases:
|
|||
error: "err: no releases found that matches specified selector(app=test_non_existent) and environment(default), in any helmfile",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
0 release(s) matching app=test_non_existent found in helmfile.yaml
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
},
|
||||
//
|
||||
// error cases
|
||||
|
|
@ -771,14 +903,53 @@ releases:
|
|||
},
|
||||
detailedExitcode: true,
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "baz", Chart: "mychart3", Flags: "--namespace ns1 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "baz", Chart: "mychart3", Flags: "--namespacens1--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{},
|
||||
upgraded: []exectest.Release{},
|
||||
deleted: []exectest.Release{},
|
||||
concurrency: 1,
|
||||
error: `in ./helmfile.yaml: release(s) "foo" depend(s) on an undefined release "bar". Perhaps you made a typo in "needs" or forgot defining a release named "bar" with appropriate "namespace" and "kubeContext"?`,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: baz
|
||||
3: namespace: ns1
|
||||
4: chart: mychart3
|
||||
5: - name: foo
|
||||
6: chart: mychart1
|
||||
7: needs:
|
||||
8: - bar
|
||||
9:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: baz
|
||||
3: namespace: ns1
|
||||
4: chart: mychart3
|
||||
5: - name: foo
|
||||
6: chart: mychart1
|
||||
7: needs:
|
||||
8: - bar
|
||||
9:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
err: release(s) "foo" depend(s) on an undefined release "bar". Perhaps you made a typo in "needs" or forgot defining a release named "bar" with appropriate "namespace" and "kubeContext"?
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -878,7 +1049,10 @@ releases:
|
|||
if tc.log != "" {
|
||||
actual := bs.String()
|
||||
|
||||
assert.Equal(t, tc.log, actual)
|
||||
diff, exists := testhelper.Diff(tc.log, actual, 3)
|
||||
if exists {
|
||||
t.Errorf("unexpected log for data defined %s:\nDIFF\n%s\nEOD", tc.loc, diff)
|
||||
}
|
||||
} else {
|
||||
testhelper.RequireLog(t, "app_diff_test_2", bs)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/helmfile/vals"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/exectest"
|
||||
|
|
@ -16,47 +15,38 @@ import (
|
|||
)
|
||||
|
||||
type diffConfig struct {
|
||||
args string
|
||||
diffArgs string
|
||||
values []string
|
||||
retainValuesFiles bool
|
||||
set []string
|
||||
validate bool
|
||||
skipCRDs bool
|
||||
skipDeps bool
|
||||
skipRefresh bool
|
||||
includeTests bool
|
||||
skipNeeds bool
|
||||
includeNeeds bool
|
||||
includeTransitiveNeeds bool
|
||||
suppress []string
|
||||
suppressSecrets bool
|
||||
showSecrets bool
|
||||
noHooks bool
|
||||
suppressDiff bool
|
||||
suppressOutputLineRegex []string
|
||||
noColor bool
|
||||
context int
|
||||
diffOutput string
|
||||
concurrency int
|
||||
detailedExitcode bool
|
||||
stripTrailingCR bool
|
||||
interactive bool
|
||||
skipDiffOnInstall bool
|
||||
skipSchemaValidation bool
|
||||
reuseValues bool
|
||||
logger *zap.SugaredLogger
|
||||
takeOwnership bool
|
||||
args string
|
||||
values []string
|
||||
retainValuesFiles bool
|
||||
set []string
|
||||
validate bool
|
||||
skipCRDs bool
|
||||
skipDeps bool
|
||||
includeTests bool
|
||||
skipNeeds bool
|
||||
includeNeeds bool
|
||||
includeTransitiveNeeds bool
|
||||
suppress []string
|
||||
suppressSecrets bool
|
||||
showSecrets bool
|
||||
noHooks bool
|
||||
suppressDiff bool
|
||||
noColor bool
|
||||
context int
|
||||
diffOutput string
|
||||
concurrency int
|
||||
detailedExitcode bool
|
||||
stripTrailingCR bool
|
||||
interactive bool
|
||||
skipDiffOnInstall bool
|
||||
reuseValues bool
|
||||
logger *zap.SugaredLogger
|
||||
}
|
||||
|
||||
func (a diffConfig) Args() string {
|
||||
return a.args
|
||||
}
|
||||
|
||||
func (a diffConfig) DiffArgs() string {
|
||||
return a.diffArgs
|
||||
}
|
||||
|
||||
func (a diffConfig) Values() []string {
|
||||
return a.values
|
||||
}
|
||||
|
|
@ -77,10 +67,6 @@ func (a diffConfig) SkipDeps() bool {
|
|||
return a.skipDeps
|
||||
}
|
||||
|
||||
func (a diffConfig) SkipRefresh() bool {
|
||||
return a.skipRefresh
|
||||
}
|
||||
|
||||
func (a diffConfig) IncludeTests() bool {
|
||||
return a.includeTests
|
||||
}
|
||||
|
|
@ -173,21 +159,6 @@ func (a diffConfig) PostRenderer() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (a diffConfig) PostRendererArgs() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a diffConfig) SkipSchemaValidation() bool {
|
||||
return a.skipSchemaValidation
|
||||
}
|
||||
|
||||
func (a diffConfig) SuppressOutputLineRegex() []string {
|
||||
return a.suppressOutputLineRegex
|
||||
}
|
||||
func (a diffConfig) TakeOwnership() bool {
|
||||
return a.takeOwnership
|
||||
}
|
||||
|
||||
func TestDiff(t *testing.T) {
|
||||
type flags struct {
|
||||
skipNeeds bool
|
||||
|
|
@ -280,16 +251,16 @@ releases:
|
|||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
// noop on frontend-v2
|
||||
{Name: "frontend-v2", Chart: "charts/frontend", Flags: "--kube-context default --reset-values --detailed-exitcode"}: nil,
|
||||
{Name: "frontend-v2", Chart: "charts/frontend", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: nil,
|
||||
// install frontend-v3
|
||||
{Name: "frontend-v3", Chart: "charts/frontend", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "frontend-v3", Chart: "charts/frontend", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
// upgrades
|
||||
{Name: "logging", Chart: "charts/fluent-bit", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "front-proxy", Chart: "stable/envoy", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "servicemesh", Chart: "charts/istio", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "database", Chart: "charts/mysql", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "backend-v2", Chart: "charts/backend", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "anotherbackend", Chart: "charts/anotherbackend", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "logging", Chart: "charts/fluent-bit", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "front-proxy", Chart: "stable/envoy", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "servicemesh", Chart: "charts/istio", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "database", Chart: "charts/mysql", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "backend-v2", Chart: "charts/backend", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "anotherbackend", Chart: "charts/anotherbackend", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
// delete frontend-v1 and backend-v1
|
||||
|
|
@ -326,7 +297,7 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: nil,
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: nil,
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("", "default")}: ``,
|
||||
|
|
@ -359,9 +330,9 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "baz", Chart: "mychart3", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "baz", Chart: "mychart3", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{},
|
||||
upgraded: []exectest.Release{},
|
||||
|
|
@ -388,8 +359,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -413,8 +384,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context hello/world --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context hello/world --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contexthello/world--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contexthello/world--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -440,8 +411,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "releaseB", Chart: "mychart2", Flags: "--kube-context arn:aws:eks:us-east-1:1234567890:cluster/myekscluster --namespace namespaceA --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "releaseA", Chart: "mychart1", Flags: "--kube-context arn:aws:eks:us-east-1:1234567890:cluster/myekscluster --namespace namespaceA --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "releaseB", Chart: "mychart2", Flags: "--kube-contextarn:aws:eks:us-east-1:1234567890:cluster/myekscluster--namespacenamespaceA--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "releaseA", Chart: "mychart1", Flags: "--kube-contextarn:aws:eks:us-east-1:1234567890:cluster/myekscluster--namespacenamespaceA--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -462,8 +433,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -485,8 +456,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --namespace testNamespace --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --namespace testNamespace --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--namespacetestNamespace--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--namespacetestNamespace--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -508,8 +479,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --namespace testNamespace --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --namespace testNamespace --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--namespacetestNamespace--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--namespacetestNamespace--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -532,36 +503,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --namespace ns2 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --namespace ns1 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
{
|
||||
name: "upgrade when ns1/foo needs ns1/bar and ns2/bar is disabled",
|
||||
loc: location(),
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml": `
|
||||
releases:
|
||||
- name: bar
|
||||
chart: mychart2
|
||||
namespace: ns1
|
||||
- name: bar
|
||||
chart: mychart2
|
||||
namespace: ns2
|
||||
installed: false
|
||||
- name: foo
|
||||
chart: mychart1
|
||||
namespace: ns1
|
||||
needs:
|
||||
- ns1/bar
|
||||
`,
|
||||
},
|
||||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --namespace ns1 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --namespace ns1 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--namespacens2--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--namespacens1--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -585,8 +528,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --namespace ns2 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --namespace ns1 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--namespacens2--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--namespacens1--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
},
|
||||
|
|
@ -609,8 +552,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --namespace ns2 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --namespace ns1 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--namespacens2--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--namespacens1--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
|
|
@ -638,8 +581,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -670,8 +613,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -704,8 +647,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -736,8 +679,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: `in ./helmfile.yaml: release "default//foo" depends on "default//bar" which does not match the selectors. Please add a selector like "--selector name=bar", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`,
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -771,8 +714,8 @@ releases:
|
|||
},
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -806,8 +749,8 @@ releases:
|
|||
},
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -838,8 +781,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: `in ./helmfile.yaml: release "default//bar" depends on "default//foo" which does not match the selectors. Please add a selector like "--selector name=foo", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`,
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -873,8 +816,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -908,8 +851,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -940,8 +883,8 @@ releases:
|
|||
detailedExitcode: true,
|
||||
error: "Identified at least one change",
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{
|
||||
{Filter: "^foo$", Flags: listFlags("", "default")}: `NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
|
||||
|
|
@ -963,7 +906,7 @@ bar 4 Fri Nov 1 08:40:07 2019 DEPLOYED mychart2-3.1.0 3.1.0 defau
|
|||
loc: location(),
|
||||
flags: flags{skipNeeds: true},
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -991,8 +934,8 @@ releases:
|
|||
selectors: []string{"app=test"},
|
||||
detailedExitcode: true,
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
|
|
@ -1004,7 +947,7 @@ releases:
|
|||
loc: location(),
|
||||
flags: flags{skipNeeds: false},
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -1032,20 +975,87 @@ releases:
|
|||
selectors: []string{"app=test"},
|
||||
detailedExitcode: true,
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-context default --namespace default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "external-secrets", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "my-release", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
upgraded: []exectest.Release{},
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
error: `in ./helmfile.yaml.gotmpl: release "default/default/external-secrets" depends on "default/kube-system/kubernetes-external-secrets" which does not match the selectors. Please add a selector like "--selector name=kubernetes-external-secrets", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`,
|
||||
error: `in ./helmfile.yaml: release "default/default/external-secrets" depends on "default/kube-system/kubernetes-external-secrets" which does not match the selectors. Please add a selector like "--selector name=kubernetes-external-secrets", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
err: release "default/default/external-secrets" depends on "default/kube-system/kubernetes-external-secrets" which does not match the selectors. Please add a selector like "--selector name=kubernetes-external-secrets", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
},
|
||||
{
|
||||
// see https://github.com/roboll/helmfile/issues/919#issuecomment-549831747
|
||||
name: "upgrades with bad selector",
|
||||
loc: location(),
|
||||
files: map[string]string{
|
||||
"/path/to/helmfile.yaml.gotmpl": `
|
||||
"/path/to/helmfile.yaml": `
|
||||
{{ $mark := "a" }}
|
||||
|
||||
releases:
|
||||
|
|
@ -1077,6 +1087,72 @@ releases:
|
|||
error: "err: no releases found that matches specified selector(app=test_non_existent) and environment(default), in any helmfile",
|
||||
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
|
||||
concurrency: 1,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1:
|
||||
2:
|
||||
3: releases:
|
||||
4: - name: kubernetes-external-secrets
|
||||
5: chart: incubator/raw
|
||||
6: namespace: kube-system
|
||||
7:
|
||||
8: - name: external-secrets
|
||||
9: chart: incubator/raw
|
||||
10: namespace: default
|
||||
11: labels:
|
||||
12: app: test
|
||||
13: needs:
|
||||
14: - kube-system/kubernetes-external-secrets
|
||||
15:
|
||||
16: - name: my-release
|
||||
17: chart: incubator/raw
|
||||
18: namespace: default
|
||||
19: labels:
|
||||
20: app: test
|
||||
21: needs:
|
||||
22: - default/external-secrets
|
||||
23:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
0 release(s) matching app=test_non_existent found in helmfile.yaml
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
},
|
||||
//
|
||||
// error cases
|
||||
|
|
@ -1099,14 +1175,51 @@ releases:
|
|||
detailedExitcode: true,
|
||||
selectors: []string{"name=foo"},
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "bar", Chart: "mychart3", Flags: "--kube-context default --namespace ns1 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "bar", Chart: "mychart3", Flags: "--kube-contextdefault--namespacens1--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{},
|
||||
upgraded: []exectest.Release{},
|
||||
deleted: []exectest.Release{},
|
||||
concurrency: 1,
|
||||
error: `in ./helmfile.yaml: release "default//foo" depends on "default//bar" which does not match the selectors. Please add a selector like "--selector name=bar", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: bar
|
||||
3: chart: mychart3
|
||||
4: - name: foo
|
||||
5: chart: mychart1
|
||||
6: needs:
|
||||
7: - bar
|
||||
8:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: bar
|
||||
3: chart: mychart3
|
||||
4: - name: foo
|
||||
5: chart: mychart1
|
||||
6: needs:
|
||||
7: - bar
|
||||
8:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
1 release(s) matching name=foo found in helmfile.yaml
|
||||
|
||||
err: release "default//foo" depends on "default//bar" which does not match the selectors. Please add a selector like "--selector name=bar", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "non-existent release in needs",
|
||||
|
|
@ -1125,14 +1238,53 @@ releases:
|
|||
},
|
||||
detailedExitcode: true,
|
||||
diffs: map[exectest.DiffKey]error{
|
||||
{Name: "baz", Chart: "mychart3", Flags: "--kube-context default --namespace ns1 --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-context default --reset-values --detailed-exitcode"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "baz", Chart: "mychart3", Flags: "--kube-contextdefault--namespacens1--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--detailed-exitcode--reset-values"}: helmexec.ExitError{Code: 2},
|
||||
},
|
||||
lists: map[exectest.ListKey]string{},
|
||||
upgraded: []exectest.Release{},
|
||||
deleted: []exectest.Release{},
|
||||
concurrency: 1,
|
||||
error: `in ./helmfile.yaml: release(s) "default//foo" depend(s) on an undefined release "default//bar". Perhaps you made a typo in "needs" or forgot defining a release named "bar" with appropriate "namespace" and "kubeContext"?`,
|
||||
log: `processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: baz
|
||||
3: namespace: ns1
|
||||
4: chart: mychart3
|
||||
5: - name: foo
|
||||
6: chart: mychart1
|
||||
7: needs:
|
||||
8: - bar
|
||||
9:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: baz
|
||||
3: namespace: ns1
|
||||
4: chart: mychart3
|
||||
5: - name: foo
|
||||
6: chart: mychart1
|
||||
7: needs:
|
||||
8: - bar
|
||||
9:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
err: release(s) "default//foo" depend(s) on an undefined release "default//bar". Perhaps you made a typo in "needs" or forgot defining a release named "bar" with appropriate "namespace" and "kubeContext"?
|
||||
changing working directory back to "/path/to"
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -1238,7 +1390,10 @@ releases:
|
|||
if tc.log != "" {
|
||||
actual := bs.String()
|
||||
|
||||
assert.Equal(t, tc.log, actual, 3)
|
||||
diff, exists := testhelper.Diff(tc.log, actual, 3)
|
||||
if exists {
|
||||
t.Errorf("unexpected log for data defined %s:\nDIFF\n%s\nEOD", tc.loc, diff)
|
||||
}
|
||||
} else {
|
||||
testhelper.RequireLog(t, "app_diff_test_1", bs)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
HelmRequiredVersion = "v3.18.6"
|
||||
HelmDiffRecommendedVersion = "v3.13.1"
|
||||
HelmRecommendedVersion = "v3.19.0"
|
||||
HelmSecretsRecommendedVersion = "v4.6.5"
|
||||
HelmGitRecommendedVersion = "v1.3.0"
|
||||
HelmS3RecommendedVersion = "v0.16.3"
|
||||
HelmRequiredVersion = "v3.10.3"
|
||||
HelmRecommendedVersion = "v3.12.1"
|
||||
HelmDiffRecommendedVersion = "v3.8.1"
|
||||
HelmSecretsRecommendedVersion = "v4.1.1"
|
||||
HelmGitRecommendedVersion = "v0.12.0"
|
||||
HelmS3RecommendedVersion = "v0.14.0"
|
||||
HelmInstallCommand = "https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3"
|
||||
)
|
||||
|
||||
|
|
@ -163,10 +163,7 @@ func (h *HelmfileInit) WhetherContinue(ask string) error {
|
|||
|
||||
func (h *HelmfileInit) CheckHelmPlugins() error {
|
||||
settings := cli.New()
|
||||
helm, err := helmexec.New(h.helmBinary, helmexec.HelmExecOptions{}, h.logger, "", "", h.runner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
helm := helmexec.New(h.helmBinary, helmexec.HelmExecOptions{}, h.logger, "", h.runner)
|
||||
for _, p := range helmPlugins {
|
||||
pluginVersion, err := helmexec.GetPluginVersion(p.name, settings.PluginsDirectory)
|
||||
if err != nil {
|
||||
|
|
@ -174,7 +171,7 @@ func (h *HelmfileInit) CheckHelmPlugins() error {
|
|||
return err
|
||||
}
|
||||
|
||||
err = h.WhetherContinue(fmt.Sprintf("The helm plugin %q is not installed, do you want to install it?", p.name))
|
||||
err = h.WhetherContinue(fmt.Sprintf("The helm plugin %s is not installed, do you need to install it", p.name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -187,7 +184,7 @@ func (h *HelmfileInit) CheckHelmPlugins() error {
|
|||
}
|
||||
requiredVersion, _ := semver.NewVersion(p.version)
|
||||
if pluginVersion.LessThan(requiredVersion) {
|
||||
err = h.WhetherContinue(fmt.Sprintf("The helm plugin %q version is too low, do you want to update it?", p.name))
|
||||
err = h.WhetherContinue(fmt.Sprintf("The helm plugin %s version is too low, do you need to update it", p.name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,31 +5,30 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"path"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDownloadfile(t *testing.T) {
|
||||
var ts *httptest.Server
|
||||
cases := []struct {
|
||||
name string
|
||||
handler func(http.ResponseWriter, *http.Request)
|
||||
url string
|
||||
filepath string
|
||||
wantContent string
|
||||
wantError string
|
||||
}{
|
||||
{
|
||||
name: "successful download of file content",
|
||||
name: "download success",
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprint(w, "helmfile")
|
||||
},
|
||||
wantContent: "helmfile",
|
||||
},
|
||||
{
|
||||
name: "404 error when file not found",
|
||||
name: "download 404",
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
fmt.Fprint(w, "not found")
|
||||
|
|
@ -37,7 +36,7 @@ func TestDownloadfile(t *testing.T) {
|
|||
wantError: "download .*? error, code: 404",
|
||||
},
|
||||
{
|
||||
name: "500 error on server failure",
|
||||
name: "download 500",
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprint(w, "server error")
|
||||
|
|
@ -45,42 +44,46 @@ func TestDownloadfile(t *testing.T) {
|
|||
wantError: "download .*? error, code: 500",
|
||||
},
|
||||
{
|
||||
name: "error due to invalid file path",
|
||||
name: "download path error",
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprint(w, "helmfile")
|
||||
},
|
||||
filepath: "abc/down.txt",
|
||||
wantError: "open .*? no such file or directory",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
downfile := filepath.Join(dir, "down.txt")
|
||||
downfile := path.Join(dir, "down.txt")
|
||||
if c.filepath != "" {
|
||||
downfile = filepath.Join(dir, c.filepath)
|
||||
downfile = path.Join(dir, c.filepath)
|
||||
}
|
||||
|
||||
ts := httptest.NewServer(http.HandlerFunc(c.handler))
|
||||
ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
c.handler(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
err := downloadfile(downfile, ts.URL)
|
||||
|
||||
url := ts.URL
|
||||
if c.url != "" {
|
||||
url = c.url
|
||||
}
|
||||
err := downloadfile(downfile, url)
|
||||
if c.wantError != "" {
|
||||
assert.Error(t, err)
|
||||
if err != nil {
|
||||
matched, regexErr := regexp.MatchString(c.wantError, err.Error())
|
||||
assert.NoError(t, regexErr)
|
||||
assert.True(t, matched, "expected error message to match regex: %s", c.wantError)
|
||||
if err == nil {
|
||||
t.Errorf("download got no error, want error: %v", c.wantError)
|
||||
} else if matched, regexErr := regexp.MatchString(c.wantError, err.Error()); regexErr != nil || !matched {
|
||||
t.Errorf("download got error: %v, want error: %v", err, c.wantError)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
content, err := os.ReadFile(downfile)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c.wantContent, string(content), "unexpected content in downloaded file")
|
||||
if err != nil {
|
||||
t.Errorf("read download file error: %v", err)
|
||||
}
|
||||
if string(content) != c.wantContent {
|
||||
t.Errorf("download file content got: %v, want content: %v", string(content), c.wantContent)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,10 @@ package app
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/argparser"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/state"
|
||||
)
|
||||
|
|
@ -42,21 +40,6 @@ func (r *Run) askForConfirmation(msg string) bool {
|
|||
return AskForConfirmation(msg)
|
||||
}
|
||||
|
||||
func (r *Run) prepareChartsIfNeeded(helmfileCommand string, dir string, concurrency int, opts state.ChartPrepareOptions) (map[state.PrepareChartKey]string, error) {
|
||||
// Skip chart preparation for certain commands
|
||||
skipCommands := []string{"write-values", "list"}
|
||||
if slices.Contains(skipCommands, strings.ToLower(helmfileCommand)) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
releaseToChart, errs := r.state.PrepareCharts(r.helm, dir, concurrency, helmfileCommand, opts)
|
||||
if len(errs) > 0 {
|
||||
return nil, fmt.Errorf("%v", errs)
|
||||
}
|
||||
|
||||
return releaseToChart, nil
|
||||
}
|
||||
|
||||
func (r *Run) withPreparedCharts(helmfileCommand string, opts state.ChartPrepareOptions, f func()) error {
|
||||
if r.ReleaseToChart != nil {
|
||||
panic("Run.PrepareCharts can be called only once")
|
||||
|
|
@ -89,9 +72,12 @@ func (r *Run) withPreparedCharts(helmfileCommand string, opts state.ChartPrepare
|
|||
return err
|
||||
}
|
||||
|
||||
releaseToChart, err := r.prepareChartsIfNeeded(helmfileCommand, dir, opts.Concurrency, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
concurrency := opts.Concurrency
|
||||
|
||||
releaseToChart, errs := r.state.PrepareCharts(r.helm, dir, concurrency, helmfileCommand, opts)
|
||||
|
||||
if len(errs) > 0 {
|
||||
return fmt.Errorf("%v", errs)
|
||||
}
|
||||
|
||||
for i := range r.state.Releases {
|
||||
|
|
@ -102,11 +88,9 @@ func (r *Run) withPreparedCharts(helmfileCommand string, opts state.ChartPrepare
|
|||
KubeContext: rel.KubeContext,
|
||||
}
|
||||
if chart := releaseToChart[key]; chart != rel.Chart {
|
||||
// The chart has been downloaded and modified by Helmfile (and chartify under the hood).
|
||||
// We let the later step use the modified version of the chart, located under the `chart` variable,
|
||||
// instead of the original chart path.
|
||||
// This way, the later step can use the modified chart without knowing
|
||||
// if it has been modified or not.
|
||||
// In this case we assume that the chart is downloaded and modified by Helmfile and chartify.
|
||||
// So we take note of the local filesystem path to the modified version of the chart
|
||||
// and use it later via the Release.ChartPathOrName() func.
|
||||
rel.ChartPath = chart
|
||||
}
|
||||
}
|
||||
|
|
@ -115,28 +99,34 @@ func (r *Run) withPreparedCharts(helmfileCommand string, opts state.ChartPrepare
|
|||
|
||||
f()
|
||||
|
||||
_, err = r.state.TriggerGlobalCleanupEvent(helmfileCommand)
|
||||
_, err := r.state.TriggerGlobalCleanupEvent(helmfileCommand)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Run) Deps(c DepsConfigProvider) []error {
|
||||
if !c.SkipRepos() {
|
||||
if err := r.ctx.SyncReposOnce(r.state, r.helm); err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
}
|
||||
|
||||
r.helm.SetExtraArgs(GetArgs(c.Args(), r.state)...)
|
||||
r.helm.SetExtraArgs(argparser.GetArgs(c.Args(), r.state)...)
|
||||
|
||||
return r.state.UpdateDeps(r.helm, c.IncludeTransitiveNeeds())
|
||||
}
|
||||
|
||||
func (r *Run) Repos(c ReposConfigProvider) error {
|
||||
r.helm.SetExtraArgs(GetArgs(c.Args(), r.state)...)
|
||||
r.helm.SetExtraArgs(argparser.GetArgs(c.Args(), r.state)...)
|
||||
|
||||
return r.ctx.SyncReposOnce(r.state, r.helm)
|
||||
}
|
||||
|
||||
// TODO: Remove this function once Helmfile v0.x
|
||||
func (r *Run) DeprecatedSyncCharts(c DeprecatedChartsConfigProvider) []error {
|
||||
st := r.state
|
||||
helm := r.helm
|
||||
|
||||
affectedReleases := state.AffectedReleases{}
|
||||
errs := st.SyncReleases(&affectedReleases, helm, c.Values(), c.Concurrency())
|
||||
affectedReleases.DisplayAffectedReleases(c.Logger())
|
||||
return errs
|
||||
}
|
||||
|
||||
func (r *Run) diff(triggerCleanupEvent bool, detailedExitCode bool, c DiffConfigProvider, diffOpts *state.DiffOpts) (*string, map[string]state.ReleaseSpec, map[string]state.ReleaseSpec, []error) {
|
||||
st := r.state
|
||||
helm := r.helm
|
||||
|
|
@ -207,11 +197,7 @@ func (r *Run) diff(triggerCleanupEvent bool, detailedExitCode bool, c DiffConfig
|
|||
names = append(names, fmt.Sprintf(" %s (%s) UPDATED", r.Name, r.Chart))
|
||||
}
|
||||
for _, r := range releasesToBeDeleted {
|
||||
releaseToBeDeleted := fmt.Sprintf(" %s (%s) DELETED", r.Name, r.Chart)
|
||||
if c.Color() {
|
||||
releaseToBeDeleted = color.RedString(releaseToBeDeleted)
|
||||
}
|
||||
names = append(names, releaseToBeDeleted)
|
||||
names = append(names, fmt.Sprintf(" %s (%s) DELETED", r.Name, r.Chart))
|
||||
}
|
||||
// Make the output deterministic for testing purpose
|
||||
sort.Strings(names)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,107 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
0 release(s) matching app=test_non_existent found in helmfile.yaml
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,107 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
err: release "default/default/external-secrets" depends on "default/kube-system/kubernetes-external-secrets" which does not match the selectors. Please add a selector like "--selector name=kubernetes-external-secrets", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies
|
||||
|
|
|
|||
|
|
@ -1,7 +1,107 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
processing 4 groups of releases in this order:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
1 release(s) matching name=test2 found in helmfile.yaml
|
||||
|
||||
err: release "default//test2" depends on "default/kube-system/disabled" which does not match the selectors. Please add a selector like "--selector name=disabled", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies
|
||||
changing working directory back to "/path/to"
|
||||
108
pkg/app/testdata/app_diff_test/include-needs_fail_on_disabled_transitive_need
vendored
Normal file
108
pkg/app/testdata/app_diff_test/include-needs_fail_on_disabled_transitive_need
vendored
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
1 release(s) matching name=test3 found in helmfile.yaml
|
||||
|
||||
err: release "default//test2" depends on "default/kube-system/disabled" which does not match the selectors. Please add a selector like "--selector name=disabled", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies
|
||||
changing working directory back to "/path/to"
|
||||
|
|
@ -1,7 +1,107 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
1 release(s) matching name=test2 found in helmfile.yaml
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
|
|
@ -11,7 +111,6 @@ GROUP RELEASES
|
|||
|
||||
processing releases in group 1/2: default/kube-system/disabled
|
||||
processing releases in group 2/2: default//test2
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
Affected releases are:
|
||||
disabled (incubator/raw) DELETED
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,107 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
1 release(s) matching name=test3 found in helmfile.yaml
|
||||
|
||||
processing 3 groups of releases in this order:
|
||||
|
|
@ -13,7 +113,6 @@ GROUP RELEASES
|
|||
processing releases in group 1/3: default/kube-system/disabled
|
||||
processing releases in group 2/3: default//test2
|
||||
processing releases in group 3/3: default//test3
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
Affected releases are:
|
||||
disabled (incubator/raw) DELETED
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) matching name=test2 found in helmfile.yaml
|
||||
|
||||
err: release "default//test2" depends on "default/kube-system/disabled" which does not match the selectors. Please add a selector like "--selector name=disabled", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies
|
||||
changing working directory back to "/path/to"
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
3 release(s) matching name=test3 found in helmfile.yaml
|
||||
|
||||
err: release "default//test2" depends on "default/kube-system/disabled" which does not match the selectors. Please add a selector like "--selector name=disabled", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies
|
||||
changing working directory back to "/path/to"
|
||||
|
|
@ -1,7 +1,107 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
1 release(s) matching name=test2 found in helmfile.yaml
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
|
|
@ -11,7 +111,6 @@ GROUP RELEASES
|
|||
|
||||
processing releases in group 1/2: default/kube-system/disabled
|
||||
processing releases in group 2/2: default//test2
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
Affected releases are:
|
||||
disabled (incubator/raw) DELETED
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,107 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
1 release(s) matching name=test3 found in helmfile.yaml
|
||||
|
||||
processing 3 groups of releases in this order:
|
||||
|
|
@ -13,7 +113,6 @@ GROUP RELEASES
|
|||
processing releases in group 1/3: default/kube-system/disabled
|
||||
processing releases in group 2/3: default//test2
|
||||
processing releases in group 3/3: default//test3
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
Affected releases are:
|
||||
disabled (incubator/raw) DELETED
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,107 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
processing 4 groups of releases in this order:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,107 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
1 release(s) matching name=test3 found in helmfile.yaml
|
||||
|
||||
processing 3 groups of releases in this order:
|
||||
|
|
@ -13,7 +113,6 @@ GROUP RELEASES
|
|||
processing releases in group 1/3: default/kube-system/disabled
|
||||
processing releases in group 2/3: default//test2
|
||||
processing releases in group 3/3: default//test3
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
Affected releases are:
|
||||
disabled (incubator/raw) DELETED
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,107 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,34 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: a
|
||||
3: chart: incubator/raw
|
||||
4: namespace: default
|
||||
5: - name: b
|
||||
6: chart: incubator/raw
|
||||
7: namespace: default
|
||||
8:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: a
|
||||
3: chart: incubator/raw
|
||||
4: namespace: default
|
||||
5: - name: b
|
||||
6: chart: incubator/raw
|
||||
7: namespace: default
|
||||
8:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
1 release(s) matching name=a found in helmfile.yaml
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
merged environment: &{default map[] map[]}
|
||||
1 release(s) matching name=a found in helmfile.yaml
|
||||
|
||||
processing 1 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default/default/a
|
||||
|
||||
processing releases in group 1/1: default/default/a
|
||||
changing working directory back to "/path/to"
|
||||
|
|
@ -1,5 +1,36 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: a
|
||||
3: chart: incubator/raw
|
||||
4: installed: false
|
||||
5: namespace: default
|
||||
6: - name: b
|
||||
7: chart: incubator/raw
|
||||
8: namespace: default
|
||||
9:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: a
|
||||
3: chart: incubator/raw
|
||||
4: installed: false
|
||||
5: namespace: default
|
||||
6: - name: b
|
||||
7: chart: incubator/raw
|
||||
8: namespace: default
|
||||
9:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
1 release(s) matching name=a found in helmfile.yaml
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,107 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,38 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: foo
|
||||
3: chart: mychart1
|
||||
4: namespace: ns1
|
||||
5: needs:
|
||||
6: - ns2/bar
|
||||
7: - name: bar
|
||||
8: chart: mychart2
|
||||
9: namespace: ns2
|
||||
10:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: foo
|
||||
3: chart: mychart1
|
||||
4: namespace: ns1
|
||||
5: needs:
|
||||
6: - ns2/bar
|
||||
7: - name: bar
|
||||
8: chart: mychart2
|
||||
9: namespace: ns2
|
||||
10:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
merged environment: &{default map[] map[]}
|
||||
3 release(s) found in helmfile.yaml
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default/ns1/bar
|
||||
2 default/ns1/foo
|
||||
|
||||
processing releases in group 1/2: default/ns1/bar
|
||||
processing releases in group 2/2: default/ns1/foo
|
||||
Affected releases are:
|
||||
bar (mychart2) DELETED
|
||||
bar (mychart2) UPDATED
|
||||
foo (mychart1) UPDATED
|
||||
|
||||
changing working directory back to "/path/to"
|
||||
|
|
@ -1,5 +1,36 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: foo
|
||||
3: chart: mychart1
|
||||
4: - name: bar
|
||||
5: chart: mychart2
|
||||
6: installed: false
|
||||
7: needs:
|
||||
8: - foo
|
||||
9:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: foo
|
||||
3: chart: mychart1
|
||||
4: - name: bar
|
||||
5: chart: mychart2
|
||||
6: installed: false
|
||||
7: needs:
|
||||
8: - foo
|
||||
9:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,37 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: bar
|
||||
3: chart: mychart2
|
||||
4: installed: false
|
||||
5: - name: foo
|
||||
6: chart: mychart1
|
||||
7: needs:
|
||||
8: - bar
|
||||
9:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: bar
|
||||
3: chart: mychart2
|
||||
4: installed: false
|
||||
5: - name: foo
|
||||
6: chart: mychart1
|
||||
7: needs:
|
||||
8: - bar
|
||||
9:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release foo needs bar, but bar is not installed due to installed: false. Either mark bar as installed or remove bar from foo's needs
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
err: release "default//foo" depends on "default//bar" which does not match the selectors. Please add a selector like "--selector name=bar", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies
|
||||
|
|
|
|||
|
|
@ -1,7 +1,37 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: bar
|
||||
3: chart: mychart2
|
||||
4: installed: false
|
||||
5: - name: foo
|
||||
6: chart: mychart1
|
||||
7: needs:
|
||||
8: - bar
|
||||
9:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: bar
|
||||
3: chart: mychart2
|
||||
4: installed: false
|
||||
5: - name: foo
|
||||
6: chart: mychart1
|
||||
7: needs:
|
||||
8: - bar
|
||||
9:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release foo needs bar, but bar is not installed due to installed: false. Either mark bar as installed or remove bar from foo's needs
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
|
|
@ -11,7 +41,6 @@ GROUP RELEASES
|
|||
|
||||
processing releases in group 1/2: default//bar
|
||||
processing releases in group 2/2: default//foo
|
||||
WARNING: release foo needs bar, but bar is not installed due to installed: false. Either mark bar as installed or remove bar from foo's needs
|
||||
Affected releases are:
|
||||
bar (mychart2) DELETED
|
||||
foo (mychart1) UPDATED
|
||||
|
|
|
|||
|
|
@ -1,7 +1,37 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: bar
|
||||
3: chart: mychart2
|
||||
4: installed: false
|
||||
5: - name: foo
|
||||
6: chart: mychart1
|
||||
7: needs:
|
||||
8: - bar
|
||||
9:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: bar
|
||||
3: chart: mychart2
|
||||
4: installed: false
|
||||
5: - name: foo
|
||||
6: chart: mychart1
|
||||
7: needs:
|
||||
8: - bar
|
||||
9:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
WARNING: release foo needs bar, but bar is not installed due to installed: false. Either mark bar as installed or remove bar from foo's needs
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
processing 1 groups of releases in this order:
|
||||
|
|
@ -9,7 +39,6 @@ GROUP RELEASES
|
|||
1 default//foo
|
||||
|
||||
processing releases in group 1/1: default//foo
|
||||
WARNING: release foo needs bar, but bar is not installed due to installed: false. Either mark bar as installed or remove bar from foo's needs
|
||||
Affected releases are:
|
||||
bar (mychart2) DELETED
|
||||
foo (mychart1) UPDATED
|
||||
|
|
|
|||
|
|
@ -1,5 +1,38 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: bar
|
||||
3: chart: mychart2
|
||||
4: installed: false
|
||||
5: needs:
|
||||
6: - foo
|
||||
7: - name: foo
|
||||
8: chart: mychart1
|
||||
9: installed: false
|
||||
10:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: bar
|
||||
3: chart: mychart2
|
||||
4: installed: false
|
||||
5: needs:
|
||||
6: - foo
|
||||
7: - name: foo
|
||||
8: chart: mychart1
|
||||
9: installed: false
|
||||
10:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,38 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
|
||||
first-pass uses: &{default map[] map[]}
|
||||
first-pass rendering output of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: bar
|
||||
3: chart: mychart2
|
||||
4: installed: false
|
||||
5: - name: foo
|
||||
6: chart: mychart1
|
||||
7: installed: false
|
||||
8: needs:
|
||||
9: - bar
|
||||
10:
|
||||
|
||||
first-pass produced: &{default map[] map[]}
|
||||
first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]}
|
||||
vals:
|
||||
map[]
|
||||
defaultVals:[]
|
||||
second-pass rendering result of "helmfile.yaml.part.0":
|
||||
0:
|
||||
1: releases:
|
||||
2: - name: bar
|
||||
3: chart: mychart2
|
||||
4: installed: false
|
||||
5: - name: foo
|
||||
6: chart: mychart1
|
||||
7: installed: false
|
||||
8: needs:
|
||||
9: - bar
|
||||
10:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) found in helmfile.yaml
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue