diff --git a/.gitignore b/.gitignore index 53b95349..350c33cc 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,12 @@ go.work # macOS .DS_Store + +# Helm Chart generated directory +# The .gitignore inside helm/ controls specific ignored files +helm/Chart.yaml +helm/values.yaml +helm/templates/ +helm/crds/ +helm/charts/ +helm/*.tgz diff --git a/Makefile b/Makefile index 7b51c14a..80c78d35 100644 --- a/Makefile +++ b/Makefile @@ -75,18 +75,48 @@ vet: ## Run go vet against code. go vet ./... .PHONY: test -test: manifests generate fmt vet envtest ## Run tests. +test: manifests generate fmt vet envtest helm-tool ## Run tests. ENVTEST_K8S_VERSION=$(ENVTEST_K8S_VERSION) \ - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test -v $$(go list ./... | grep -v /e2e) -coverprofile cover.out + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" \ + PATH="$(LOCALBIN):$(PATH)" \ + go test -v $$(go list ./... | grep -v /e2e) -coverprofile cover.out + @echo "==> Validating Helm Chart generation..." + $(MAKE) helm + @echo "==> Running Helm lint..." + $(HELM) lint helm/ + @echo "==> Testing Helm template rendering..." + $(HELM) template test helm/ > /dev/null + @echo "✅ All tests passed including Helm validation!" # TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'. # The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally. # Prometheus and CertManager are installed by default; skip with: # - PROMETHEUS_INSTALL_SKIP=true # - CERT_MANAGER_INSTALL_SKIP=true +# +# DEPLOY_METHOD controls the deployment method for E2E tests: +# - all (default): Test both deployment methods sequentially +# - kustomize: Deploy using Kustomize only +# - helm: Deploy using Helm Chart only +DEPLOY_METHOD ?= all + .PHONY: test-e2e -test-e2e: generate fmt vet kind ## Run the e2e tests. Expected an isolated environment using Kind. - ETCD_VERSION="$(E2E_ETCD_VERSION)" PATH="$(LOCALBIN):$(PATH)" go test ./test/e2e/ -v +test-e2e: generate fmt vet kind helm-tool ## Run the e2e tests. Expected an isolated environment using Kind. + @if [ "$(DEPLOY_METHOD)" = "all" ]; then \ + echo "==> Testing all deployment methods..."; \ + echo ""; \ + echo "==> [1/2] Testing Kustomize deployment"; \ + DEPLOY_METHOD=kustomize ETCD_VERSION="$(E2E_ETCD_VERSION)" PATH="$(LOCALBIN):$(PATH)" go test ./test/e2e/ -v || exit 1; \ + echo ""; \ + echo "==> [2/2] Testing Helm deployment"; \ + $(MAKE) helm; \ + DEPLOY_METHOD=helm ETCD_VERSION="$(E2E_ETCD_VERSION)" PATH="$(LOCALBIN):$(PATH)" go test ./test/e2e/ -v || exit 1; \ + echo ""; \ + echo "✅ All deployment methods tested successfully!"; \ + else \ + echo "==> Testing with DEPLOY_METHOD=$(DEPLOY_METHOD)"; \ + ETCD_VERSION="$(E2E_ETCD_VERSION)" PATH="$(LOCALBIN):$(PATH)" go test ./test/e2e/ -v; \ + fi .PHONY: lint lint: golangci-lint ## Run golangci-lint linter @@ -157,6 +187,27 @@ build-installer: manifests generate kustomize ## Generate a consolidated YAML wi cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} $(KUSTOMIZE) build config/default > dist/install$(VERSION_SUFFIX).yaml +##@ Helm + +.PHONY: helm +helm: manifests kustomize helmify yq helm-tool ## Generate Helm Chart from Kustomize manifests. + @echo "==> Generating Helm Chart..." + @mkdir -p helm + $(KUSTOMIZE) build config/default | $(HELMIFY) -crd-dir -image-pull-secrets helm + @echo "==> Updating Chart metadata..." + $(YQ) -i '.name = "etcd-operator"' helm/Chart.yaml + $(YQ) -i '.description = "Official Kubernetes operator for etcd"' helm/Chart.yaml + $(YQ) -i '.home = "https://github.com/etcd-io/etcd-operator"' helm/Chart.yaml + @echo "==> Validating generated Chart..." + @$(HELM) lint helm/ || (echo "❌ Helm Chart validation failed!" && exit 1) + @echo "✅ Helm Chart generated and validated at helm/" + +.PHONY: helm-lint +helm-lint: helm ## Lint the generated Helm Chart. + @echo "==> Linting Helm Chart..." + @$(HELM) lint helm/ + @echo "✅ Helm Chart validation passed!" + ##@ Deployment ifndef ignore-not-found @@ -206,6 +257,9 @@ ENVTEST ?= $(LOCALBIN)/setup-envtest GOLANGCI_LINT = $(LOCALBIN)/golangci-lint CRD_REF_DOCS ?= $(LOCALBIN)/crd-ref-docs KIND ?= $(LOCALBIN)/kind +HELMIFY ?= $(LOCALBIN)/helmify +YQ ?= $(LOCALBIN)/yq +HELM ?= $(LOCALBIN)/helm ## Tool Versions KUSTOMIZE_VERSION = $(shell cd tools/mod && go list -m -f {{.Version}} sigs.k8s.io/kustomize/kustomize/v5) @@ -214,6 +268,10 @@ ENVTEST_VERSION = $(shell cd tools/mod && go list -m -f {{.Version}} sigs.k8s.io GOLANGCI_LINT_VERSION = $(shell cd tools/mod && go list -m -f {{.Version}} github.com/golangci/golangci-lint/v2) CRD_REF_DOCS_VERSION = $(shell cd tools/mod && go list -m -f {{.Version}} github.com/elastic/crd-ref-docs) KIND_VERSION = $(shell cd tools/mod && go list -m -f {{.Version}} sigs.k8s.io/kind) +HELMIFY_VERSION = $(shell cd tools/mod && go list -m -f {{.Version}} github.com/arttor/helmify) +YQ_VERSION = $(shell cd tools/mod && go list -m -f {{.Version}} github.com/mikefarah/yq/v4) +# Helm is not a Go module, must specify version directly +HELM_VERSION ?= v3.17.0 .PHONY: kustomize kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. @@ -245,6 +303,35 @@ golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary. $(GOLANGCI_LINT): $(LOCALBIN) curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(LOCALBIN) $(GOLANGCI_LINT_VERSION) +.PHONY: helmify +helmify: $(HELMIFY) ## Download helmify locally if necessary. +$(HELMIFY): $(LOCALBIN) + $(call go-install-tool,$(HELMIFY),github.com/arttor/helmify/cmd/helmify,$(HELMIFY_VERSION)) + +.PHONY: yq +yq: $(YQ) ## Download yq locally if necessary. +$(YQ): $(LOCALBIN) + $(call go-install-tool,$(YQ),github.com/mikefarah/yq/v4,$(YQ_VERSION)) + +.PHONY: helm-tool +helm-tool: $(HELM) ## Download helm locally if necessary. +$(HELM): $(LOCALBIN) + @[ -f "$(HELM)-$(HELM_VERSION)" ] || { \ + set -e; \ + echo "Downloading Helm $(HELM_VERSION)"; \ + rm -f $(HELM) || true; \ + OS=$$(uname -s | tr '[:upper:]' '[:lower:]'); \ + ARCH=$$(uname -m); \ + case $$ARCH in \ + x86_64) ARCH=amd64 ;; \ + aarch64) ARCH=arm64 ;; \ + esac; \ + curl -sSL https://get.helm.sh/helm-$(HELM_VERSION)-$${OS}-$${ARCH}.tar.gz | \ + tar xz -C $(LOCALBIN) --strip-components=1 $${OS}-$${ARCH}/helm; \ + mv $(HELM) $(HELM)-$(HELM_VERSION); \ + } + @ln -sf $(HELM)-$(HELM_VERSION) $(HELM) + # go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist # $1 - target path with name of binary # $2 - package url which can be installed diff --git a/README.md b/README.md index bac1320f..2b9e1cea 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,25 @@ Participation in the Kubernetes community is governed by the [Kubernetes Code of - kubectl version v1.11.3+. - Access to a Kubernetes v1.11.3+ cluster. -### To Deploy on the cluster +### Deployment Methods + +The etcd-operator supports two deployment methods: + +- **Helm**: Package management with easy configuration via values files +- **Kustomize**: Simple, GitOps-friendly deployment + +📦 **For Helm deployment**, see the [Helm Chart Documentation](helm/README.md) for: +- Quick start guide +- How the Chart is auto-generated from Kustomize +- Customizing values and configuration +- Example configurations (HA, minimal resources) +- Upgrade and troubleshooting guides + +The instructions below use **Kustomize** for deployment. + +--- + +### To Deploy on the cluster (Kustomize) **Build and push your image to the location specified by `IMG`:** diff --git a/go.mod b/go.mod index 26ea2a03..a86365b7 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( go.etcd.io/etcd/client/v3 v3.6.5 go.etcd.io/etcd/server/v3 v3.6.5 go.uber.org/zap v1.27.0 + gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.34.1 k8s.io/apimachinery v0.34.1 k8s.io/client-go v0.34.1 @@ -118,7 +119,6 @@ require ( gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.34.1 k8s.io/apiserver v0.34.1 // indirect k8s.io/component-base v0.34.1 // indirect diff --git a/helm/.gitignore b/helm/.gitignore new file mode 100644 index 00000000..e6435ac3 --- /dev/null +++ b/helm/.gitignore @@ -0,0 +1,12 @@ +# Helm Chart generated files (created by helmify) - do not commit to Git +# These files are generated by the `make helm` command +Chart.yaml +values.yaml +templates/ +crds/ +charts/ +*.tgz + +# Keep manually created example configs and documentation +!examples/ +!README.md diff --git a/helm/.helmignore b/helm/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/helm/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/README.md b/helm/README.md new file mode 100644 index 00000000..19551cd1 --- /dev/null +++ b/helm/README.md @@ -0,0 +1,414 @@ +# Helm Chart for etcd-operator + +This directory contains the Helm Chart for deploying the etcd-operator on Kubernetes. + +## Overview + +The Helm Chart is **automatically generated** from the Kustomize manifests (located in `config/default/`) using [helmify](https://github.com/arttor/helmify). This ensures that the Helm Chart and Kustomize deployment remain in sync. + +**Single Source of Truth**: All configuration changes should be made in the Kustomize manifests. The Helm Chart is regenerated automatically during build and test processes. + +## Quick Start + +### Prerequisites + +- Kubernetes cluster 1.30+ +- Helm 3.x +- cert-manager v1.16+ installed ([Installation Guide](https://cert-manager.io/docs/installation/)) + +### Installation + +```bash +# 1. Install cert-manager using Helm (recommended) +helm repo add jetstack https://charts.jetstack.io +helm repo update +helm install cert-manager jetstack/cert-manager \ + --namespace cert-manager \ + --create-namespace \ + --version v1.19.1 \ + --set crds.enabled=true + +# Wait for cert-manager to be ready +kubectl wait --for=condition=Available deployment/cert-manager -n cert-manager --timeout=2m +kubectl wait --for=condition=Available deployment/cert-manager-webhook -n cert-manager --timeout=2m + +# 2. Build and push your operator image +make docker-build docker-push IMG=/etcd-operator:v0.1.0 + +# 3. Generate the Helm Chart (helmify and yq will be auto-installed if needed) +make helm + +# 4. Install the operator +helm install etcd-operator ./helm/ \ + --create-namespace \ + --namespace etcd-operator-system \ + --set controllerManager.manager.image.repository=/etcd-operator \ + --set controllerManager.manager.image.tag=v0.1.0 + +# 5. Create an etcd cluster +kubectl apply -f - </etcd-operator \ + --set controllerManager.manager.image.tag=v0.1.0 +``` + +Features: +- 3 controller replicas for redundancy +- Leader election enabled (only one replica actively reconciles) +- Higher resource limits (1 CPU, 512Mi memory) +- Kubernetes scheduler automatically distributes pods across nodes + +**Note**: The operator uses leader election, so only one replica is active at a time. The other replicas are in standby mode and will take over if the leader fails. + +#### Minimal Resources (Development/Testing) + +```bash +helm install etcd-operator ./helm/ \ + -f ./helm/examples/values-minimal.yaml \ + --set controllerManager.manager.image.repository=/etcd-operator \ + --set controllerManager.manager.image.tag=v0.1.0 +``` + +Features: +- 1 controller replica +- Minimal resource limits (200m CPU, 128Mi memory) +- Suitable for resource-constrained environments + +### Custom Values File + +Create your own `my-values.yaml`: + +```yaml +# Controller configuration +controllerManager: + replicas: 2 + + manager: + image: + repository: ghcr.io/my-org/etcd-operator + tag: v0.1.0 + + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 100m + memory: 128Mi + +# Kubernetes cluster domain (if different) +kubernetesClusterDomain: cluster.local +``` + +Install with custom values: + +```bash +helm install etcd-operator ./helm/ -f my-values.yaml +``` + +### Key Configuration Options + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `controllerManager.replicas` | Number of controller replicas | `1` | +| `controllerManager.manager.image.repository` | Controller image repository | `controller` | +| `controllerManager.manager.image.tag` | Controller image tag | `latest` | +| `controllerManager.manager.resources.limits.cpu` | CPU limit | `500m` | +| `controllerManager.manager.resources.limits.memory` | Memory limit | `128Mi` | +| `kubernetesClusterDomain` | Kubernetes cluster domain | `cluster.local` | + +**Important**: The default `values.yaml` contains placeholder image values. You **must** override them with your actual image using `--set` flags or a custom values file. + +## Upgrading + +```bash +# Regenerate Chart if Kustomize configs changed +make helm + +# Upgrade the release +helm upgrade etcd-operator ./helm/ \ + --namespace etcd-operator-system \ + --reuse-values +``` + +**Note**: Helm does not automatically update CRDs during upgrades. If CRDs have changed, manually apply them: + +```bash +kubectl apply -f helm/crds/ +``` + +## Uninstalling + +```bash +# Uninstall the operator +helm uninstall etcd-operator --namespace etcd-operator-system + +# Optionally remove CRDs (this will delete all EtcdCluster resources!) +kubectl delete crd etcdclusters.operator.etcd.io + +# Optionally remove namespace +kubectl delete namespace etcd-operator-system + +# Optionally uninstall cert-manager (if no other apps are using it) +helm uninstall cert-manager --namespace cert-manager +kubectl delete namespace cert-manager +``` + +## Development Workflow + +### Modifying the Chart + +To make changes to the Helm Chart: + +1. **Modify Kustomize manifests** in `config/default/` (not the Helm Chart directly) +2. **Regenerate the Chart**: `make helm` +3. **Test the changes**: `DEPLOY_METHOD=helm make test-e2e` +4. **Validate**: `helm lint helm/` + +### Testing Both Deployment Methods + +The project supports testing both Kustomize and Helm deployments: + +```bash +# Test Kustomize only +DEPLOY_METHOD=kustomize make test-e2e + +# Test Helm only +DEPLOY_METHOD=helm make test-e2e + +# Test both (default) +make test-e2e +``` + +## Troubleshooting + +### Chart Generation Fails + +```bash +# Check Kustomize configuration +kustomize build config/default/ + +# Ensure tools are installed +make helmify yq + +# Regenerate with verbose output +make helm +``` + +### Helm Lint Errors + +The `make helm` command automatically runs `helm lint`. If it fails: + +1. Check the Kustomize manifests for invalid YAML +2. Ensure all required fields are present in `config/manager/manager.yaml` +3. Review the lint output for specific issues + +### Image Pull Errors + +If you see `ImagePullBackOff`: + +1. Ensure the operator image is built and available: + ```bash + make docker-build IMG= + ``` + +2. For Kind clusters, load the operator image: + ```bash + kind load docker-image + ``` + +3. Verify image is specified correctly in Helm values: + ```bash + helm get values etcd-operator -n etcd-operator-system + ``` + +**Note**: The operator uses `gcr.io/etcd-development/etcd` as the default registry for etcd pods. If you need to use a different registry, specify it in your EtcdCluster CR: + +```yaml +spec: + imageRegistry: "your-registry/etcd" + version: "v3.6.5" +``` + +### CRDs Not Found + +CRDs in `helm/crds/` are automatically installed during `helm install`. If you see CRD-related errors: + +```bash +# Verify CRDs are installed +kubectl get crd etcdclusters.operator.etcd.io + +# Manually install if needed +kubectl apply -f helm/crds/ +``` + +## Additional Resources + +- [Kustomize Configuration](../config/default/) - Source of truth for all manifests +- [Installation Guide](../docs/install.md) - Detailed installation instructions +- [Contributing Guide](../CONTRIBUTING.md) - How to test deployment methods +- [Helm Documentation](https://helm.sh/docs/) - Official Helm documentation + +## Architecture + +### Why Auto-Generate? + +**Benefits**: +- ✅ Single source of truth (Kustomize) +- ✅ No manual synchronization needed +- ✅ Consistent manifests across deployment methods +- ✅ Automated validation in CI/CD + +**Trade-offs**: +- ⚠️ Chart must be regenerated after Kustomize changes +- ⚠️ Custom Chart modifications will be overwritten +- ⚠️ Customizations should be done via `values.yaml` or `examples/` + +### Helm vs Kustomize + +Both deployment methods are supported and tested: + +| Feature | Kustomize | Helm | +|---------|-----------|------| +| **Configuration** | Patches and overlays | Values files | +| **Templating** | Limited | Full Go templates | +| **Package Management** | No | Yes (Helm repos) | +| **Versioning** | Manual | Built-in | +| **Rollback** | Manual | Built-in | +| **Use Case** | GitOps, simple deploys | Package distribution, upgrades | + +Choose based on your needs: +- **Kustomize**: Direct, simple, GitOps-friendly +- **Helm**: Package management, templating, easier upgrades + +Both methods deploy the same operator with identical functionality. diff --git a/helm/examples/values-ha.yaml b/helm/examples/values-ha.yaml new file mode 100644 index 00000000..ca3018d8 --- /dev/null +++ b/helm/examples/values-ha.yaml @@ -0,0 +1,74 @@ +# Helm Values - High Availability Configuration Example +# +# This configuration provides high availability for the operator with: +# - 3 replicas for redundancy +# - Leader election enabled (only one replica actively reconciles at a time) +# - Higher resource limits for production workloads +# +# Note: The Kubernetes scheduler will automatically distribute pods across nodes. +# For more advanced placement (affinity, topology spread), you need to manually +# edit the generated Helm templates in helm/templates/deployment.yaml. +# +# Usage: +# helm install etcd-operator ./helm -f helm/examples/values-ha.yaml +# Or in E2E tests: +# DEPLOY_METHOD=helm HELM_VALUES=helm/examples/values-ha.yaml make test-e2e + +# Controller Manager Configuration +controllerManager: + # Replica count - HA configuration uses 3 replicas for redundancy + # Only one replica will be active (leader) at a time due to leader election + replicas: 3 + + # Pod security context + podSecurityContext: + runAsNonRoot: true + + # ServiceAccount configuration + serviceAccount: + annotations: {} + + # Manager container configuration + manager: + # Image configuration + image: + repository: controller + tag: latest + + # Container arguments + args: + - --metrics-bind-address=:8443 + - --leader-elect + - --health-probe-bind-address=:8081 + + # Resource configuration - HA environment uses higher resource limits + resources: + limits: + cpu: 1000m # 1 CPU + memory: 512Mi # 512 MB + requests: + cpu: 200m # 0.2 CPU + memory: 128Mi # 128 MB + + # Container security context + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + +# Metrics Service Configuration +metricsService: + type: ClusterIP + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: 8443 + +# Kubernetes cluster domain +kubernetesClusterDomain: cluster.local + +# Image pull secrets (if using private image registry) +imagePullSecrets: [] + diff --git a/helm/examples/values-minimal.yaml b/helm/examples/values-minimal.yaml new file mode 100644 index 00000000..b8220c87 --- /dev/null +++ b/helm/examples/values-minimal.yaml @@ -0,0 +1,72 @@ +# Helm Values - Minimal Resource Configuration Example +# +# This configuration is suitable for development/test environments or resource-constrained scenarios +# Uses minimal resource configuration to reduce resource consumption +# +# Usage: +# helm install etcd-operator ./helm -f helm/examples/values-minimal.yaml +# Or in E2E tests: +# DEPLOY_METHOD=helm HELM_VALUES=helm/examples/values-minimal.yaml make test-e2e + +# Controller Manager Configuration +controllerManager: + # Replica count - Minimal configuration uses single replica + replicas: 1 + + # Pod security context + podSecurityContext: + runAsNonRoot: true + + # ServiceAccount configuration + serviceAccount: + annotations: {} + + # Manager container configuration + manager: + # Image configuration + image: + repository: controller + tag: latest + + # Container arguments + args: + - --metrics-bind-address=:8443 + - --leader-elect + - --health-probe-bind-address=:8081 + + # Resource configuration - Minimal resource limits + resources: + limits: + cpu: 200m # 0.2 CPU + memory: 128Mi # 128 MB + requests: + cpu: 50m # 0.05 CPU + memory: 32Mi # 32 MB + + # Container security context + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + +# Metrics Service Configuration +metricsService: + type: ClusterIP + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: 8443 + +# Kubernetes cluster domain +kubernetesClusterDomain: cluster.local + +# Image pull secrets (if using private image registry) +imagePullSecrets: [] + +# Notes: +# - This configuration uses only a single replica and does not provide high availability +# - Resource limits are low, suitable for development and testing +# - Not suitable for production environments +# - For production deployment, please use values-ha.yaml diff --git a/internal/helm/generation_test.go b/internal/helm/generation_test.go new file mode 100644 index 00000000..93fcd086 --- /dev/null +++ b/internal/helm/generation_test.go @@ -0,0 +1,173 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package helm + +import ( + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v3" +) + +// TestHelmGeneration validates that the make helm command generates a correct Helm Chart structure +// This is an integration test that needs to actually call the make helm command +func TestHelmGeneration(t *testing.T) { + if testing.Short() { + t.Skip("Skipping integration test in short mode") + } + + // Get project root directory + rootDir, err := findProjectRoot() + require.NoError(t, err, "Failed to find project root") + + helmDir := filepath.Join(rootDir, "helm") + + // Clean up existing helm directory to test idempotency + t.Cleanup(func() { + // Keep generated files after test for subsequent tests + }) + + // Execute make helm + cmd := exec.Command("make", "helm") + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + require.NoError(t, err, "make helm failed: %s", string(output)) + + t.Run("Chart.yaml exists and has correct metadata", func(t *testing.T) { + chartPath := filepath.Join(helmDir, "Chart.yaml") + require.FileExists(t, chartPath, "Chart.yaml should be generated") + + data, err := os.ReadFile(chartPath) + require.NoError(t, err, "Failed to read Chart.yaml") + + var chart map[string]interface{} + err = yaml.Unmarshal(data, &chart) + require.NoError(t, err, "Failed to parse Chart.yaml") + + // Verify required fields + assert.Equal(t, "etcd-operator", chart["name"], "Chart name should be etcd-operator") + assert.Equal(t, "Official Kubernetes operator for etcd", chart["description"], "Chart description should match") + assert.Equal(t, "https://github.com/etcd-io/etcd-operator", chart["home"], "Chart home should match") + assert.Equal(t, "application", chart["type"], "Chart type should be application") + assert.NotEmpty(t, chart["version"], "Chart version should not be empty") + assert.Equal(t, "v2", chart["apiVersion"], "Chart apiVersion should be v2") + }) + + t.Run("values.yaml exists and has reasonable structure", func(t *testing.T) { + valuesPath := filepath.Join(helmDir, "values.yaml") + require.FileExists(t, valuesPath, "values.yaml should be generated") + + data, err := os.ReadFile(valuesPath) + require.NoError(t, err, "Failed to read values.yaml") + + var values map[string]interface{} + err = yaml.Unmarshal(data, &values) + require.NoError(t, err, "Failed to parse values.yaml") + + // values.yaml should contain configurable items + // helmify-generated structure typically contains top-level keys like controllerManager + assert.NotEmpty(t, values, "values.yaml should not be empty") + }) + + t.Run("templates directory exists with required files", func(t *testing.T) { + templatesDir := filepath.Join(helmDir, "templates") + require.DirExists(t, templatesDir, "templates/ directory should be generated") + + // Check if key template files are included + entries, err := os.ReadDir(templatesDir) + require.NoError(t, err, "Failed to read templates directory") + assert.NotEmpty(t, entries, "templates/ should contain files") + + // Verify at least contains deployment.yaml + foundDeployment := false + for _, entry := range entries { + if entry.Name() == "deployment.yaml" { + foundDeployment = true + break + } + } + assert.True(t, foundDeployment, "templates/ should contain deployment.yaml") + }) + + t.Run("crds directory exists with CRD files", func(t *testing.T) { + crdsDir := filepath.Join(helmDir, "crds") + require.DirExists(t, crdsDir, "crds/ directory should be generated") + + entries, err := os.ReadDir(crdsDir) + require.NoError(t, err, "Failed to read crds directory") + assert.NotEmpty(t, entries, "crds/ should contain CRD files") + + // Verify contains etcdcluster CRD + foundEtcdClusterCRD := false + for _, entry := range entries { + if filepath.Ext(entry.Name()) == ".yaml" || filepath.Ext(entry.Name()) == ".yml" { + foundEtcdClusterCRD = true + break + } + } + assert.True(t, foundEtcdClusterCRD, "crds/ should contain etcdcluster CRD") + }) + + t.Run("Helm Chart is idempotent", func(t *testing.T) { + // First generation + cmd1 := exec.Command("make", "helm") + cmd1.Dir = rootDir + output1, err := cmd1.CombinedOutput() + require.NoError(t, err, "First make helm failed: %s", string(output1)) + + chartPath := filepath.Join(helmDir, "Chart.yaml") + data1, err := os.ReadFile(chartPath) + require.NoError(t, err, "Failed to read Chart.yaml after first generation") + + // Second generation + cmd2 := exec.Command("make", "helm") + cmd2.Dir = rootDir + output2, err := cmd2.CombinedOutput() + require.NoError(t, err, "Second make helm failed: %s", string(output2)) + + data2, err := os.ReadFile(chartPath) + require.NoError(t, err, "Failed to read Chart.yaml after second generation") + + // Verify content is identical + assert.Equal(t, data1, data2, "Multiple runs of make helm should produce identical Chart.yaml") + }) +} + +// findProjectRoot finds the project root directory (directory containing go.mod) +func findProjectRoot() (string, error) { + dir, err := os.Getwd() + if err != nil { + return "", err + } + + // Search upward until finding go.mod + for { + if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { + return dir, nil + } + + parent := filepath.Dir(dir) + if parent == dir { + return "", os.ErrNotExist + } + dir = parent + } +} diff --git a/internal/helm/validation_test.go b/internal/helm/validation_test.go new file mode 100644 index 00000000..285b8caf --- /dev/null +++ b/internal/helm/validation_test.go @@ -0,0 +1,144 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package helm + +import ( + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestHelmLint validates that the generated Helm Chart passes helm lint checks +func TestHelmLint(t *testing.T) { + if testing.Short() { + t.Skip("Skipping integration test in short mode") + } + + rootDir, err := findProjectRoot() + require.NoError(t, err, "Failed to find project root") + + helmDir := filepath.Join(rootDir, "helm") + + // Ensure Helm Chart is generated + cmd := exec.Command("make", "helm") + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + require.NoError(t, err, "make helm failed: %s", string(output)) + + t.Run("helm lint passes", func(t *testing.T) { + cmd := exec.Command("helm", "lint", helmDir) + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + + outputStr := string(output) + t.Logf("helm lint output:\n%s", outputStr) + + require.NoError(t, err, "helm lint should pass: %s", outputStr) + + // Verify output contains success messages + assert.Contains(t, outputStr, "1 chart(s) linted", "Should report 1 chart linted") + assert.Contains(t, outputStr, "0 chart(s) failed", "Should report 0 charts failed") + }) + + t.Run("helm lint detects no errors", func(t *testing.T) { + cmd := exec.Command("helm", "lint", helmDir) + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + + outputStr := string(output) + + // helm lint returns 0 even with warnings, only errors return non-zero + require.NoError(t, err, "helm lint should not error") + + // Verify no [ERROR] marks + assert.NotContains(t, strings.ToUpper(outputStr), "[ERROR]", "Should not contain ERROR messages") + }) +} + +// TestHelmTemplate validates that the generated Helm Chart can be rendered successfully +func TestHelmTemplate(t *testing.T) { + if testing.Short() { + t.Skip("Skipping integration test in short mode") + } + + rootDir, err := findProjectRoot() + require.NoError(t, err, "Failed to find project root") + + helmDir := filepath.Join(rootDir, "helm") + + // Ensure Helm Chart is generated + cmd := exec.Command("make", "helm") + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + require.NoError(t, err, "make helm failed: %s", string(output)) + + t.Run("helm template renders successfully", func(t *testing.T) { + cmd := exec.Command("helm", "template", "test", helmDir) + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + + outputStr := string(output) + + require.NoError(t, err, "helm template should succeed: %s", outputStr) + assert.NotEmpty(t, outputStr, "helm template should produce output") + }) + + t.Run("helm template output contains expected resources", func(t *testing.T) { + cmd := exec.Command("helm", "template", "test", helmDir) + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + + outputStr := string(output) + require.NoError(t, err, "helm template should succeed") + + // Verify output contains key resource types + assert.Contains(t, outputStr, "kind: Deployment", "Should contain Deployment") + assert.Contains(t, outputStr, "kind: ServiceAccount", "Should contain ServiceAccount") + assert.Contains(t, outputStr, "kind: Role", "Should contain Role or ClusterRole") + assert.Contains(t, outputStr, "apiVersion:", "Should contain apiVersion fields") + assert.Contains(t, outputStr, "metadata:", "Should contain metadata fields") + }) + + t.Run("helm template with custom values renders successfully", func(t *testing.T) { + // Test rendering with custom values + // Create a simple temporary values file + customValues := ` +controllerManager: + replicas: 2 +` + tmpValuesPath := filepath.Join(t.TempDir(), "custom-values.yaml") + err := writeFile(tmpValuesPath, []byte(customValues)) + require.NoError(t, err, "Failed to write custom values file") + + cmd := exec.Command("helm", "template", "test", helmDir, "-f", tmpValuesPath) + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + + outputStr := string(output) + + require.NoError(t, err, "helm template with custom values should succeed: %s", outputStr) + assert.NotEmpty(t, outputStr, "helm template should produce output") + }) +} +func writeFile(path string, data []byte) error { + return os.WriteFile(path, data, 0644) +} diff --git a/internal/helm/values_test.go b/internal/helm/values_test.go new file mode 100644 index 00000000..5215d6eb --- /dev/null +++ b/internal/helm/values_test.go @@ -0,0 +1,231 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package helm + +import ( + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v3" +) + +// TestHelmValuesApplication validates that different values configurations are correctly applied to rendered templates +func TestHelmValuesApplication(t *testing.T) { + if testing.Short() { + t.Skip("Skipping integration test in short mode") + } + + rootDir, err := findProjectRoot() + require.NoError(t, err, "Failed to find project root") + + helmDir := filepath.Join(rootDir, "helm") + + // Ensure Helm Chart is generated + cmd := exec.Command("make", "helm") + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + require.NoError(t, err, "make helm failed: %s", string(output)) + + t.Run("Default values.yaml structure", func(t *testing.T) { + valuesPath := filepath.Join(helmDir, "values.yaml") + data, err := os.ReadFile(valuesPath) + require.NoError(t, err, "Failed to read values.yaml") + + var values map[string]interface{} + err = yaml.Unmarshal(data, &values) + require.NoError(t, err, "Failed to parse values.yaml") + + // Verify values.yaml has reasonable structure + // helmify-generated structure is typically controllerManager.manager.image etc. + assert.NotEmpty(t, values, "values.yaml should not be empty") + + // Log actual structure for debugging + t.Logf("Values structure keys: %v", getKeys(values)) + }) + + t.Run("Custom replicas value is applied", func(t *testing.T) { + // Create custom values file + customValues := ` +controllerManager: + replicas: 2 +` + tmpValuesPath := filepath.Join(t.TempDir(), "custom-replicas.yaml") + err := os.WriteFile(tmpValuesPath, []byte(customValues), 0644) + require.NoError(t, err, "Failed to write custom values file") + + // Render with custom values + cmd := exec.Command("helm", "template", "test", helmDir, "-f", tmpValuesPath) + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + require.NoError(t, err, "helm template should succeed") + + outputStr := string(output) + + // Verify replicas is applied (may be in Deployment) + // Note: Specific field location depends on helmify-generated template structure + if strings.Contains(outputStr, "kind: Deployment") { + // Check if it contains replicas: 2 + // Need flexible matching due to YAML format + assert.Contains(t, outputStr, "replicas:", "Deployment should have replicas field") + t.Logf("Custom replicas value appears to be applied") + } + }) + + t.Run("Custom image values are applied", func(t *testing.T) { + customValues := ` +controllerManager: + manager: + image: + repository: custom-registry.io/etcd-operator + tag: v0.2.0 +` + tmpValuesPath := filepath.Join(t.TempDir(), "custom-image.yaml") + err := os.WriteFile(tmpValuesPath, []byte(customValues), 0644) + require.NoError(t, err, "Failed to write custom values file") + + cmd := exec.Command("helm", "template", "test", helmDir, "-f", tmpValuesPath) + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + require.NoError(t, err, "helm template should succeed") + + outputStr := string(output) + + // Verify custom image is applied + assert.Contains(t, outputStr, "custom-registry.io/etcd-operator", + "Custom image repository should be applied") + assert.Contains(t, outputStr, "v0.2.0", + "Custom image tag should be applied") + }) + + t.Run("Custom resource limits are applied", func(t *testing.T) { + customValues := ` +controllerManager: + manager: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 100m + memory: 64Mi +` + tmpValuesPath := filepath.Join(t.TempDir(), "custom-resources.yaml") + err := os.WriteFile(tmpValuesPath, []byte(customValues), 0644) + require.NoError(t, err, "Failed to write custom values file") + + cmd := exec.Command("helm", "template", "test", helmDir, "-f", tmpValuesPath) + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + require.NoError(t, err, "helm template should succeed") + + outputStr := string(output) + + // Verify resource configuration is applied + if strings.Contains(outputStr, "resources:") { + assert.Contains(t, outputStr, "cpu: 500m", "CPU limit should be applied") + assert.Contains(t, outputStr, "memory: 256Mi", "Memory limit should be applied") + assert.Contains(t, outputStr, "cpu: 100m", "CPU request should be applied") + assert.Contains(t, outputStr, "memory: 64Mi", "Memory request should be applied") + } + }) + + t.Run("Multiple custom values files can be merged", func(t *testing.T) { + // First values file - modify replicas + values1 := ` +controllerManager: + replicas: 3 +` + tmpValues1Path := filepath.Join(t.TempDir(), "values1.yaml") + err := os.WriteFile(tmpValues1Path, []byte(values1), 0644) + require.NoError(t, err, "Failed to write values1 file") + + // Second values file - modify image + values2 := ` +controllerManager: + manager: + image: + tag: v0.3.0 +` + tmpValues2Path := filepath.Join(t.TempDir(), "values2.yaml") + err = os.WriteFile(tmpValues2Path, []byte(values2), 0644) + require.NoError(t, err, "Failed to write values2 file") + + // Render with multiple values files + cmd := exec.Command("helm", "template", "test", helmDir, + "-f", tmpValues1Path, + "-f", tmpValues2Path) + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + require.NoError(t, err, "helm template with multiple values should succeed") + + outputStr := string(output) + + // Verify both configurations are applied + assert.Contains(t, outputStr, "v0.3.0", "Image tag from values2 should be applied") + // replicas verification (if visible in output) + t.Logf("Multiple values files merged successfully") + }) + + t.Run("CLI --set flags override values file", func(t *testing.T) { + // Create a values file setting tag to v0.1.0 + customValues := ` +controllerManager: + manager: + image: + tag: v0.1.0 +` + tmpValuesPath := filepath.Join(t.TempDir(), "base-values.yaml") + err := os.WriteFile(tmpValuesPath, []byte(customValues), 0644) + require.NoError(t, err, "Failed to write values file") + + // Override with --set + cmd := exec.Command("helm", "template", "test", helmDir, + "-f", tmpValuesPath, + "--set", "controllerManager.manager.image.tag=v0.2.0-override") + cmd.Dir = rootDir + output, err := cmd.CombinedOutput() + require.NoError(t, err, "helm template with --set should succeed") + + outputStr := string(output) + + // Verify --set value overrides values file + assert.Contains(t, outputStr, "v0.2.0-override", + "--set value should override values file") + assert.NotContains(t, outputStr, "v0.1.0", + "Original value from file should be overridden") + }) +} + +// getKeys recursively gets all key paths from map +func getKeys(m map[string]interface{}) []string { + keys := []string{} + for k, v := range m { + keys = append(keys, k) + if subMap, ok := v.(map[string]interface{}); ok { + subKeys := getKeys(subMap) + for _, sk := range subKeys { + keys = append(keys, k+"."+sk) + } + } + } + return keys +} diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index fb36eae5..8a05d880 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -44,6 +44,7 @@ var ( imageName = "etcd-operator:v0.1" namespace = "etcd-operator-system" containerTool = os.Getenv("CONTAINER_TOOL") + deployMethod = getDeployMethod() ) func TestMain(m *testing.M) { @@ -123,14 +124,10 @@ func TestMain(m *testing.M) { // Deploy components log.Println("Deploying components...") - log.Println("Deploying controller-manager resources...") - cmd = exec.Command("make", "deploy", fmt.Sprintf("IMG=%s", imageName)) - if _, err := test_utils.Run(cmd); err != nil { - log.Printf("Failed to deploy resource configurations: %s", err) + if err := deployOperator(deployMethod, imageName, namespace); err != nil { + log.Printf("Failed to deploy operator: %s", err) return ctx, err - } - - // wait for controller to get ready + } // wait for controller to get ready client := cfg.Client() log.Println("Waiting for controller-manager deployment to be available...") @@ -161,14 +158,11 @@ func TestMain(m *testing.M) { // undeploy etcd operator log.Println("Undeploy etcd controller...") - cmd := exec.Command("make", "undeploy", "ignore-not-found=true") - if _, err := test_utils.Run(cmd); err != nil { + if err := undeployOperator(deployMethod, namespace); err != nil { log.Printf("Warning: Failed to undeploy controller: %s", err) - } - - // uninstall crd + } // uninstall crd log.Println("Uninstalling crd...") - cmd = exec.Command("make", "uninstall", "ignore-not-found=true") + cmd := exec.Command("make", "uninstall", "ignore-not-found=true") if _, err := test_utils.Run(cmd); err != nil { log.Printf("Warning: Failed to install crd: %s", err) } diff --git a/test/e2e/helpers_test.go b/test/e2e/helpers_test.go index f8941c88..9deaf116 100644 --- a/test/e2e/helpers_test.go +++ b/test/e2e/helpers_test.go @@ -21,7 +21,9 @@ import ( "context" "encoding/json" "fmt" + "log" "os" + "os/exec" "strings" "testing" "time" @@ -35,9 +37,15 @@ import ( "sigs.k8s.io/e2e-framework/pkg/envconf" ecv1alpha1 "go.etcd.io/etcd-operator/api/v1alpha1" + test_utils "go.etcd.io/etcd-operator/test/utils" "go.etcd.io/etcd/api/v3/etcdserverpb" ) +const ( + deployMethodKustomize = "kustomize" + deployMethodHelm = "helm" +) + // getAvailableStorageClass returns an available StorageClass name func getAvailableStorageClass(ctx context.Context, t *testing.T, c *envconf.Config) string { t.Helper() @@ -294,3 +302,144 @@ func verifyDataOperations(t *testing.T, c *envconf.Config, etcdClusterName, test t.Errorf("Expected key-value pair [%s=%s], but got output: %s", testKey, testValue, stdout) } } + +// getDeployMethod retrieves the deployment method from environment variable, +// defaults to "kustomize" if not set. +func getDeployMethod() string { + method := os.Getenv("DEPLOY_METHOD") + if method == "" { + return deployMethodKustomize + } + return method +} + +// deployOperator deploys the operator based on the deployment method. +// It supports both Kustomize and Helm deployment methods. +func deployOperator(deployMethod, imageName, namespace string) error { + log.Printf("Deploying operator using method: %s", deployMethod) + + switch deployMethod { + case deployMethodHelm: + return deployWithHelm(imageName, namespace) + case deployMethodKustomize: + return deployWithKustomize(imageName) + default: + return fmt.Errorf("unknown DEPLOY_METHOD: %s (supported: %s, %s)", + deployMethod, deployMethodKustomize, deployMethodHelm) + } +} + +// deployWithKustomize deploys the operator using Kustomize. +func deployWithKustomize(imageName string) error { + log.Println("Deploying controller-manager resources with Kustomize...") + cmd := exec.Command("make", "deploy", fmt.Sprintf("IMG=%s", imageName)) + if _, err := test_utils.Run(cmd); err != nil { + return fmt.Errorf("failed to deploy with Kustomize: %w", err) + } + return nil +} + +// deployWithHelm deploys the operator using Helm Chart. +func deployWithHelm(imageName, namespace string) error { + log.Println("Generating Helm Chart...") + cmd := exec.Command("make", "helm") + if _, err := test_utils.Run(cmd); err != nil { + return fmt.Errorf("failed to generate Helm Chart: %w", err) + } + + // Check for custom values file + helmValues := os.Getenv("HELM_VALUES") + if helmValues == "" { + helmValues = "helm/values.yaml" + } else { + log.Printf("Using custom values file: %s", helmValues) + } + + // Verify values file exists + if _, err := os.Stat(helmValues); os.IsNotExist(err) { + return fmt.Errorf("specified HELM_VALUES file does not exist: %s", helmValues) + } + + log.Println("Installing operator with Helm...") + args := []string{ + "install", "etcd-operator", "./helm", + "-f", helmValues, + "-n", namespace, + "--wait", + "--timeout", "5m", + "--set", fmt.Sprintf("controllerManager.manager.image.repository=%s", getImageRepository(imageName)), + "--set", fmt.Sprintf("controllerManager.manager.image.tag=%s", getImageTag(imageName)), + } + + cmd = exec.Command("helm", args...) + if output, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("helm install failed: %w\nOutput: %s", err, string(output)) + } + + log.Println("Helm Chart installed successfully") + return nil +} + +// undeployOperator undeploys the operator based on the deployment method. +func undeployOperator(deployMethod, namespace string) error { + log.Printf("Undeploying operator using method: %s", deployMethod) + + switch deployMethod { + case deployMethodHelm: + return undeployWithHelm(namespace) + case deployMethodKustomize: + return undeployWithKustomize() + default: + return fmt.Errorf("unknown DEPLOY_METHOD: %s", deployMethod) + } +} + +// undeployWithKustomize undeploys the operator using Kustomize. +func undeployWithKustomize() error { + cmd := exec.Command("make", "undeploy", "ignore-not-found=true") + if _, err := test_utils.Run(cmd); err != nil { + return fmt.Errorf("failed to undeploy with Kustomize: %w", err) + } + return nil +} + +// undeployWithHelm undeploys the operator using Helm. +func undeployWithHelm(namespace string) error { + log.Println("Uninstalling operator with Helm...") + cmd := exec.Command("helm", "uninstall", "etcd-operator", "-n", namespace) + if output, err := cmd.CombinedOutput(); err != nil { + // Helm uninstall failures should only be logged as warnings during cleanup + log.Printf("Warning: helm uninstall failed: %v\nOutput: %s", err, string(output)) + } + return nil +} + +// getImageRepository extracts the repository part from a full image name. +// Examples: +// - "etcd-operator:v0.1" -> "etcd-operator" +// - "ghcr.io/etcd-io/etcd-operator:v0.1" -> "ghcr.io/etcd-io/etcd-operator" +func getImageRepository(imageName string) string { + parts := splitImageNameTag(imageName) + return parts[0] +} + +// getImageTag extracts the tag from a full image name. +// Examples: +// - "etcd-operator:v0.1" -> "v0.1" +// - "etcd-operator" -> "latest" +func getImageTag(imageName string) string { + parts := splitImageNameTag(imageName) + if len(parts) > 1 { + return parts[1] + } + return "latest" +} + +// splitImageNameTag splits an image name into repository and tag parts. +func splitImageNameTag(imageName string) []string { + idx := strings.LastIndex(imageName, ":") + if idx != -1 { + return []string{imageName[:idx], imageName[idx+1:]} + } + return []string{imageName} +} diff --git a/tools/mod/go.mod b/tools/mod/go.mod index 110bc957..39cec69f 100644 --- a/tools/mod/go.mod +++ b/tools/mod/go.mod @@ -13,11 +13,17 @@ require ( sigs.k8s.io/kustomize/kustomize/v5 v5.7.1 ) +require ( + github.com/arttor/helmify v0.4.18 + github.com/mikefarah/yq/v4 v4.48.1 +) + require ( 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect 4d63.com/gochecknoglobals v0.2.2 // indirect al.essio.dev/pkg/shellescape v1.5.1 // indirect codeberg.org/chavacava/garif v0.2.0 // indirect + dario.cat/mergo v1.0.0 // indirect dev.gaijin.team/go/exhaustruct/v4 v4.0.0 // indirect dev.gaijin.team/go/golib v0.6.0 // indirect github.com/4meepo/tagalign v1.4.3 // indirect @@ -35,8 +41,10 @@ require ( github.com/Masterminds/sprig v2.22.0+incompatible // indirect github.com/MirrexOne/unqueryvet v1.2.1 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect + github.com/a8m/envsubst v1.4.3 // indirect github.com/alecthomas/chroma/v2 v2.20.0 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect + github.com/alecthomas/participle/v2 v2.1.4 // indirect github.com/alexkohler/nakedret/v2 v2.0.6 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect github.com/alfatraining/structtag v1.0.0 // indirect @@ -70,7 +78,9 @@ require ( github.com/dave/dst v0.27.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/denis-tingaikin/go-header v0.5.0 // indirect + github.com/dimchansky/utfbom v1.1.1 // indirect github.com/dlclark/regexp2 v1.11.5 // indirect + github.com/elliotchance/orderedmap v1.8.0 // indirect github.com/ettle/strcase v0.2.0 // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fatih/color v1.18.0 // indirect @@ -82,6 +92,7 @@ require ( github.com/ghostiam/protogetter v0.3.16 // indirect github.com/go-critic/go-critic v0.13.0 // indirect github.com/go-errors/errors v1.4.2 // indirect + github.com/go-ini/ini v1.67.0 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect @@ -98,6 +109,7 @@ require ( github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobuffalo/flect v1.0.3 // indirect github.com/gobwas/glob v0.2.3 // indirect + github.com/goccy/go-json v0.10.5 // indirect github.com/goccy/go-yaml v1.18.0 // indirect github.com/godoc-lint/godoc-lint v0.10.0 // indirect github.com/gofrs/flock v0.12.1 // indirect @@ -125,11 +137,13 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect - github.com/huandu/xstrings v1.3.3 // indirect - github.com/imdario/mergo v0.3.11 // indirect + github.com/huandu/xstrings v1.4.0 // indirect + github.com/iancoleman/strcase v0.2.0 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jgautheron/goconst v1.8.2 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect + github.com/jinzhu/copier v0.4.0 // indirect github.com/jjti/go-spancheck v0.6.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -148,7 +162,7 @@ require ( github.com/leonklingele/grouper v1.1.2 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/macabu/inamedparam v0.2.0 // indirect - github.com/magiconair/properties v1.8.6 // indirect + github.com/magiconair/properties v1.8.10 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/manuelarte/embeddedstructfieldcheck v0.4.0 // indirect github.com/manuelarte/funcorder v0.5.0 // indirect @@ -229,6 +243,7 @@ require ( github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.3.0 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect + github.com/yuin/gopher-lua v1.1.1 // indirect gitlab.com/bosi/decorder v0.4.2 // indirect go-simpler.org/musttag v0.14.0 // indirect go-simpler.org/sloglint v0.11.1 // indirect @@ -239,13 +254,13 @@ require ( go.uber.org/zap v1.27.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.42.0 // indirect + golang.org/x/crypto v0.43.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250911091902-df9299821621 // indirect golang.org/x/mod v0.28.0 // indirect - golang.org/x/net v0.44.0 // indirect + golang.org/x/net v0.46.0 // indirect golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.36.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/tools v0.37.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 // indirect @@ -253,6 +268,7 @@ require ( gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/tools v0.6.1 // indirect diff --git a/tools/mod/go.sum b/tools/mod/go.sum index 2cc87e1d..028f6580 100644 --- a/tools/mod/go.sum +++ b/tools/mod/go.sum @@ -8,6 +8,8 @@ cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY= codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dev.gaijin.team/go/exhaustruct/v4 v4.0.0 h1:873r7aNneqoBB3IaFIzhvt2RFYTuHgmMjoKfwODoI1Y= dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88YdiB0Ai4fXOzPI= dev.gaijin.team/go/golib v0.6.0 h1:v6nnznFTs4bppib/NyU1PQxobwDHwCXXl15P7DV5Zgo= @@ -26,10 +28,14 @@ github.com/Antonboom/nilnil v1.1.1 h1:9Mdr6BYd8WHCDngQnNVV0b554xyisFioEKi30sksuf github.com/Antonboom/nilnil v1.1.1/go.mod h1:yCyAmSw3doopbOWhJlVci+HuyNRuHJKIv6V2oYQa8II= github.com/Antonboom/testifylint v1.6.4 h1:gs9fUEy+egzxkEbq9P4cpcMB6/G0DYdMeiFS87UiqmQ= github.com/Antonboom/testifylint v1.6.4/go.mod h1:YO33FROXX2OoUfwjz8g+gUxQXio5i9qpVy7nXGbxDD4= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao4g= github.com/Djarvur/go-err113 v0.1.1/go.mod h1:IaWJdYFLg76t2ihfflPZnM1LIQszWOsFDh2hhhAVF6k= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= @@ -38,18 +44,26 @@ github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7r github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc= +github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/MirrexOne/unqueryvet v1.2.1 h1:M+zdXMq84g+E1YOLa7g7ExN3dWfZQrdDSTCM7gC+m/A= github.com/MirrexOne/unqueryvet v1.2.1/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= +github.com/a8m/envsubst v1.4.3 h1:kDF7paGK8QACWYaQo6KtyYBozY2jhQrTuNNuUxQkhJY= +github.com/a8m/envsubst v1.4.3/go.mod h1:4jjHWQlZoaXPoLQUb7H2qT4iLkZDdmEQiOUogdUmqVU= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw= github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= -github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg= -github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alecthomas/participle/v2 v2.1.4 h1:W/H79S8Sat/krZ3el6sQMvMaahJ+XcM9WSI2naI7w2U= +github.com/alecthomas/participle/v2 v2.1.4/go.mod h1:8tqVbpTX20Ru4NfYQgZf4mP18eXPTBViyMWiArNEgGI= +github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= +github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ= github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= @@ -62,6 +76,10 @@ github.com/alingse/nilnesserr v0.2.0 h1:raLem5KG7EFVb4UIDAXgrv3N2JIaffeKNtcEXkEW github.com/alingse/nilnesserr v0.2.0/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/arttor/helmify v0.4.18 h1:LyvgBNUTIUBohrKVVYgPWS//3S0KhXPXZcsuc2cA07I= +github.com/arttor/helmify v0.4.18/go.mod h1:jHLtbiOoxmUIIZYLGtGnZWAzjhR6NkMPED/WA2loCVc= +github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY= +github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/ashanbrown/forbidigo/v2 v2.1.0 h1:NAxZrWqNUQiDz19FKScQ/xvwzmij6BiOw3S0+QUQ+Hs= github.com/ashanbrown/forbidigo/v2 v2.1.0/go.mod h1:0zZfdNAuZIL7rSComLGthgc/9/n2FqspBOH90xlCHdA= github.com/ashanbrown/makezero/v2 v2.0.1 h1:r8GtKetWOgoJ4sLyUx97UTwyt2dO7WkGFHizn/Lo8TY= @@ -96,6 +114,8 @@ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK3 github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= +github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= @@ -110,10 +130,14 @@ github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQ github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/ckaznocha/intrange v0.3.1 h1:j1onQyXvHUsPWujDH6WIjhyH26gkRt/txNlV7LspvJs= github.com/ckaznocha/intrange v0.3.1/go.mod h1:QVepyz1AkUoFQkpEqksSYpNpUo3c5W7nWh/s6SHIJJk= +github.com/containerd/containerd v1.6.15 h1:4wWexxzLNHNE46aIETc6ge4TofO550v+BlLoANrbses= +github.com/containerd/containerd v1.6.15/go.mod h1:U2NnBPIhzJDm59xF7xB2MMHnKtggpZ+phKg8o2TKj2c= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs= github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88= +github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/daixiang0/gci v0.13.7 h1:+0bG5eK9vlI08J+J/NWGbWPTNiXPG4WhNLJOkSxWITQ= github.com/daixiang0/gci v0.13.7/go.mod h1:812WVN6JLFY9S6Tv76twqmNqevN0pa3SX3nih0brVzQ= github.com/dave/dst v0.27.3 h1:P1HPoMza3cMEquVf9kKy8yXsFirry4zEnWOdYPOoIzY= @@ -126,14 +150,38 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= +github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= +github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/docker/cli v20.10.21+incompatible h1:qVkgyYUnOLQ98LtXBrwd/duVqPT2X4SHndOuGsfwyhU= +github.com/docker/cli v20.10.21+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v20.10.21+incompatible h1:UTLdBmHk3bEY+w8qeO5KttOhy6OmXWsl/FEet9Uswog= +github.com/docker/docker v20.10.21+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/elastic/crd-ref-docs v0.2.0 h1:U17MyGX71j4qfKTvYxbR4qZGoA1hc2thy7kseGYmP+o= github.com/elastic/crd-ref-docs v0.2.0/go.mod h1:0bklkJhTG7nC6AVsdDi0wt5bGoqvzdZSzMMQkilZ6XM= +github.com/elliotchance/orderedmap v1.8.0 h1:TrOREecvh3JbS+NCgwposXG5ZTFHtEsQiCGOhPElnMw= +github.com/elliotchance/orderedmap v1.8.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= +github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= +github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= @@ -156,6 +204,10 @@ github.com/go-critic/go-critic v0.13.0 h1:kJzM7wzltQasSUXtYyTl6UaPVySO6GkaR1thFn github.com/go-critic/go-critic v0.13.0/go.mod h1:M/YeuJ3vOCQDnP2SU+ZhjgRzwzcBW87JqLpMJLrZDLI= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-gorp/gorp/v3 v3.0.5 h1:PUjzYdYu3HBOh8LE+UUmRG2P0IRDak9XMeGNvaeq4Ow= +github.com/go-gorp/gorp/v3 v3.0.5/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= +github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -201,6 +253,8 @@ github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4 github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godoc-lint/godoc-lint v0.10.0 h1:OcyrziBi18sQSEpib6NesVHEJ/Xcng97NunePBA48g4= @@ -209,6 +263,8 @@ github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golangci/asciicheck v0.5.0 h1:jczN/BorERZwK8oiFBOGvlGPknhvq0bjnysTj4nUfo0= github.com/golangci/asciicheck v0.5.0/go.mod h1:5RMNAInbNFw2krqN6ibBxN/zfRFa9S6tA1nPdM0l8qQ= github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 h1:WUvBfQL6EW/40l6OmeSBYQJNSif4O11+bmWEz+C7FYw= @@ -233,8 +289,12 @@ github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e h1:ai0EfmVYE2b github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e/go.mod h1:Vrn4B5oR9qRwM+f54koyeH3yzphlecwERs0el27Fr/s= github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM= github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e/go.mod h1:h+wZwLjUTJnm/P2rwlbJdRPZXOzaT36/FwnPnY2inzc= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= +github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -251,6 +311,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gordonklaus/ineffassign v0.2.0 h1:Uths4KnmwxNJNzq87fwQQDDnbNb7De00VOk9Nu0TySs= github.com/gordonklaus/ineffassign v0.2.0/go.mod h1:TIpymnagPSexySzs7F9FnO1XFTy8IT3a59vmZp5Y9Lw= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= @@ -261,6 +325,10 @@ github.com/gostaticanalysis/forcetypeassert v0.2.0/go.mod h1:M5iPavzE9pPqWyeiVXS github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8= github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs= +github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo= @@ -276,10 +344,12 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= -github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -287,8 +357,12 @@ github.com/jgautheron/goconst v1.8.2 h1:y0XF7X8CikZ93fSNT6WBTb/NElBu9IjaY7CCYQrC github.com/jgautheron/goconst v1.8.2/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= +github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= +github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8= github.com/jjti/go-spancheck v0.6.5/go.mod h1:aEogkeatBrbYsyW6y5TgDfihCulDYciL1B7rG2vSsrU= +github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -303,6 +377,8 @@ github.com/kisielk/errcheck v1.9.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkHAIKE/contextcheck v1.1.6 h1:7HIyRcnyzxL9Lz06NGhiKvenXq7Zw6Q0UQu/ttjfJCE= github.com/kkHAIKE/contextcheck v1.1.6/go.mod h1:3dDbMRNBFaq8HFXWC1JyvDSPm43CmE6IuHam8Wr0rkg= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -315,6 +391,10 @@ github.com/kulti/thelper v0.7.1 h1:fI8QITAoFVLx+y+vSyuLBP+rcVIB8jKooNSCT2EiI98= github.com/kulti/thelper v0.7.1/go.mod h1:NsMjfQEy6sd+9Kfw8kCP61W1I0nerGSYSFnGaxQkcbs= github.com/kunwardeep/paralleltest v1.0.14 h1:wAkMoMeGX/kGfhQBPODT/BL8XhK23ol/nuQ3SwFaUw8= github.com/kunwardeep/paralleltest v1.0.14/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= github.com/ldez/exptostd v0.4.4 h1:58AtQjnLcT/tI5W/1KU7xE/O7zW9RAWB6c/ScQAnfus= @@ -329,12 +409,16 @@ github.com/ldez/usetesting v0.5.0 h1:3/QtzZObBKLy1F4F8jLuKJiKBjjVFi1IavpoWbmqLwc github.com/ldez/usetesting v0.5.0/go.mod h1:Spnb4Qppf8JTuRgblLrEWb7IE6rDmUpGvxY3iRrzvDQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE= github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= -github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= -github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/manuelarte/embeddedstructfieldcheck v0.4.0 h1:3mAIyaGRtjK6EO9E73JlXLtiy7ha80b2ZVGyacxgfww= @@ -357,14 +441,24 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mgechev/revive v1.12.0 h1:Q+/kkbbwerrVYPv9d9efaPGmAO/NsxwW/nE6ahpQaCU= github.com/mgechev/revive v1.12.0/go.mod h1:VXsY2LsTigk8XU9BpZauVLjVrhICMOV3k1lpB3CXrp8= +github.com/mikefarah/yq/v4 v4.48.1 h1:xfw9oDxur6z+friOtMAuzSvQ9LPLb0LRDsl1e36DGCo= +github.com/mikefarah/yq/v4 v4.48.1/go.mod h1:NbCTmYAY+KjwCZemVDqLxSAeZKjXFK04lgIiSx13tD0= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= +github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -375,10 +469,14 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg= @@ -395,6 +493,10 @@ github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= github.com/onsi/gomega v1.38.1 h1:FaLA8GlcpXDwsb7m0h2A9ew2aTk3vnZMlzFgg5tz/pk= github.com/onsi/gomega v1.38.1/go.mod h1:LfcV8wZLvwcYRwPiJysphKAEsmcFnLMK/9c+PjvlX8g= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= @@ -406,6 +508,10 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -441,6 +547,9 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rubenv/sql-migrate v1.3.1 h1:Vx+n4Du8X8VTYuXbhNxdEUoh6wiJERA0GlWocR5FrbA= +github.com/rubenv/sql-migrate v1.3.1/go.mod h1:YzG/Vh82CwyhTFXy+Mf5ahAiiEOpAlHurg+23VEzcsk= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.4.1 h1:eWC8eUMNZ/wM/PWuZBv7JxxqT5fiIKSIyTvjb7Elr+g= github.com/ryancurrah/gomodguard v1.4.1/go.mod h1:qnMJwV1hX9m+YJseXEBhd2s90+1Xn6x9dLz11ualI1I= @@ -458,6 +567,8 @@ github.com/securego/gosec/v2 v2.22.8 h1:3NMpmfXO8wAVFZPNsd3EscOTa32Jyo6FLLlW53be github.com/securego/gosec/v2 v2.22.8/go.mod h1:ZAw8K2ikuH9qDlfdV87JmNghnVfKB1XC7+TVzk6Utto= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= @@ -528,6 +639,12 @@ github.com/uudashr/iface v1.4.1 h1:J16Xl1wyNX9ofhpHmQ9h9gk5rnv2A6lX/2+APLTo0zU= github.com/uudashr/iface v1.4.1/go.mod h1:pbeBPlbuU2qkNDn0mmfrxP2X+wjPMIQAy+r1MBXSXtg= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xen0n/gosmopolitan v1.3.0 h1:zAZI1zefvo7gcpbCOrPSHJZJYA9ZgLfJqtKzZ5pHqQM= github.com/xen0n/gosmopolitan v1.3.0/go.mod h1:rckfr5T6o4lBtM1ga7mLGKZmLxswUoH1zxHgNXOsEt4= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= @@ -547,6 +664,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= +github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= @@ -595,8 +714,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= -golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= @@ -627,8 +746,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -662,16 +781,16 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= -golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -680,8 +799,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -726,16 +845,19 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE= +gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +helm.sh/helm/v3 v3.11.2 h1:P3cLaFxfoxaGLGJVnoPrhf1j86LC5EDINSpYSpMUkkA= +helm.sh/helm/v3 v3.11.2/go.mod h1:Hw+09mfpDiRRKAgAIZlFkPSeOkvv7Acl5McBvQyNPVw= honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= k8s.io/api v0.34.0 h1:L+JtP2wDbEYPUeNGbeSa/5GwFtIA662EmT2YSLOkAVE= @@ -746,6 +868,8 @@ k8s.io/apimachinery v0.34.0 h1:eR1WO5fo0HyoQZt1wdISpFDffnWOvFLOOeJ7MgIv4z0= k8s.io/apimachinery v0.34.0/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= k8s.io/apiserver v0.34.0 h1:Z51fw1iGMqN7uJ1kEaynf2Aec1Y774PqU+FVWCFV3Jg= k8s.io/apiserver v0.34.0/go.mod h1:52ti5YhxAvewmmpVRqlASvaqxt0gKJxvCeW7ZrwgazQ= +k8s.io/cli-runtime v0.26.0 h1:aQHa1SyUhpqxAw1fY21x2z2OS5RLtMJOCj7tN4oq8mw= +k8s.io/cli-runtime v0.26.0/go.mod h1:o+4KmwHzO/UK0wepE1qpRk6l3o60/txUZ1fEXWGIKTY= k8s.io/client-go v0.34.0 h1:YoWv5r7bsBfb0Hs2jh8SOvFbKzzxyNo0nSb0zC19KZo= k8s.io/client-go v0.34.0/go.mod h1:ozgMnEKXkRjeMvBZdV1AijMHLTh3pbACPvK7zFR+QQY= k8s.io/code-generator v0.34.0 h1:Ze2i1QsvUprIlX3oHiGv09BFQRLCz+StA8qKwwFzees= @@ -758,12 +882,16 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= +k8s.io/kubectl v0.26.0 h1:xmrzoKR9CyNdzxBmXV7jW9Ln8WMrwRK6hGbbf69o4T0= +k8s.io/kubectl v0.26.0/go.mod h1:eInP0b+U9XUJWSYeU9XZnTA+cVYuWyl3iYPGtru0qhQ= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= mvdan.cc/gofumpt v0.9.1 h1:p5YT2NfFWsYyTieYgwcQ8aKV3xRvFH4uuN/zB2gBbMQ= mvdan.cc/gofumpt v0.9.1/go.mod h1:3xYtNemnKiXaTh6R4VtlqDATFwBbdXI8lJvH/4qk7mw= mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8= mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4/go.mod h1:rthT7OuvRbaGcd5ginj6dA2oLE7YNlta9qhBNNdCaLE= +oras.land/oras-go v1.2.2 h1:0E9tOHUfrNH7TCDk5KU0jVBEzCqbfdyuVfGmJ7ZeRPE= +oras.land/oras-go v1.2.2/go.mod h1:Apa81sKoZPpP7CDciE006tSZ0x3Q3+dOoBcMZ/aNxvw= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20250106171007-7436275c4311 h1:5lENIqqUDxxmMgQHItUPnqw6XaIG0sAluD4M+Foz30E= diff --git a/tools/mod/tools.go b/tools/mod/tools.go index 50fb2d85..a7d13d14 100644 --- a/tools/mod/tools.go +++ b/tools/mod/tools.go @@ -21,8 +21,10 @@ package mod import ( + _ "github.com/arttor/helmify/cmd/helmify" _ "github.com/elastic/crd-ref-docs" _ "github.com/golangci/golangci-lint/v2/cmd/golangci-lint" + _ "github.com/mikefarah/yq/v4" _ "sigs.k8s.io/controller-runtime/tools/setup-envtest" _ "sigs.k8s.io/controller-tools/cmd/controller-gen" _ "sigs.k8s.io/kind"