Skip to content

Commit d91a7ca

Browse files
tookyclaudejumboduckclaude[bot]dependabot[bot]
authored
Introduce fakes and contract tests for AWS Lambda integration (#763)
* refactor: extract LambdaAPI interface from concrete *lambda.Client Define a narrow LambdaAPI interface scoped to the two SDK methods we actually use (ListFunctions, GetFunctionConfiguration). Refactor getFilteredLambdaFuncs, getAndProcessOneLambdaFunc, and the new getLambdaPackageDataFromClient to accept the interface instead of *lambda.Client. The public GetLambdaPackageData creates the real client and delegates — command layer is untouched. This is Slice 1 of the fakes & contract tests work (#758). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add LambdaAPI contract test suite against real AWS Shared runLambdaContractTests function exercises the behaviours we depend on: listing functions, marker-based pagination, getting function config, and error on missing function. Wired to real *lambda.Client in TestLambdaContract_RealAWS, env-gated behind AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY. This establishes the contract grounded in real AWS behaviour — the fake (next slice) must pass the same suite. Slice 2 of fakes & contract tests work (#758). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add FakeLambdaClient that passes the LambdaAPI contract FakeLambdaClient is an in-memory implementation of LambdaAPI with marker-based pagination and error responses for missing functions. It passes the same runLambdaContractTests suite that validates the real *lambda.Client, proving it is a trustworthy stand-in. Slice 3 of fakes & contract tests work (#758). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add fake-backed unit tests for Lambda filtering and pagination Tests getFilteredLambdaFuncs with the FakeLambdaClient covering: IncludeNames, IncludeNamesRegex, ExcludeNames, ExcludeNamesRegex, combined exclude filters, multi-page pagination with filtering, empty function lists, and invalid regex error handling. These tests run without AWS credentials and complete in milliseconds. Slice 4 of fakes & contract tests work (#758). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add fake-backed unit tests for Lambda orchestration Tests getLambdaPackageDataFromClient with the FakeLambdaClient covering: Zip fingerprint decoding, Image raw CodeSha256, concurrent multi-function processing, empty function list, and error propagation from GetFunctionConfiguration. Also adds GetFunctionConfigurationErr field to FakeLambdaClient for error injection in tests. Slice 5 of fakes & contract tests work (#758). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: trim Lambda integration tests to focused smoke tests Remove filtering-focused integration test cases (IncludeNamesRegex, ExcludeNames, ExcludeNamesRegex, combined filters, wrong region, invalid regex) — these are now covered by fake-backed unit tests in TestGetFilteredLambdaFuncs and TestGetLambdaPackageDataFromClient. Keep three smoke tests: invalid credentials error, one Zip function happy path, and one Image function happy path. These prove real AWS SDK wiring works without duplicating logic tests. Reduces Lambda integration tests from 8 cases to 3. Slice 6 of fakes & contract tests work (#758). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: mark all Lambda fakes & contract slices complete in TODO Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: inject FakeLambdaClient into command tests via factory Add NewLambdaClientFunc package-level factory to internal/aws. GetLambdaPackageData uses the factory instead of creating a client directly. Tests replace the factory to inject a FakeLambdaClient. snapshotLambda_test.go now injects the fake in SetupTest and resets in TearDownTest. All test cases run without AWS credentials — the requireAuthToBeSet/SkipIfEnvVarUnset pattern is removed entirely. Also adds make test_smoke_aws target for running contract and smoke tests against real AWS before release. Slice 7 of fakes & contract tests work (#758). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: mark Slice 7 complete in TODO Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: add TODO checklist for remaining cloud provider fakes Lists the next steps for ECS, S3, Azure Apps, Docker, and Kubernetes following the pattern established by the Lambda work: interface → contract tests (real first) → fake → unit tests → factory injection into command tests → trim integration tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Apply suggestions from code review Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * test: skip pagination contract test when account has only 1 Lambda function Replace hard require.NotNil on NextMarker with a t.Skip guard so the real-AWS contract test skips cleanly instead of failing with a confusing nil-pointer message if the account ever has only one function. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Remove latest_activity from repo list and get commands (#770) The field always returns null in production and is being removed from the API response (kosli-dev/server#5180). Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(deps): bump the go-dependencies group across 1 directory with 10 updates (#769) Bumps the go-dependencies group with 8 updates in the / directory: | Package | From | To | | --- | --- | --- | | [github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://github.com/Azure/azure-sdk-for-go) | `1.10.1` | `1.13.1` | | [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) | `1.32.13` | `1.32.14` | | [github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager](https://github.com/aws/aws-sdk-go-v2) | `0.1.13` | `0.1.15` | | [github.com/aws/aws-sdk-go-v2/service/ecs](https://github.com/aws/aws-sdk-go-v2) | `1.75.0` | `1.77.0` | | [github.com/aws/aws-sdk-go-v2/service/lambda](https://github.com/aws/aws-sdk-go-v2) | `1.88.5` | `1.89.0` | | [github.com/aws/smithy-go](https://github.com/aws/smithy-go) | `1.24.2` | `1.24.3` | | [github.com/docker/docker](https://github.com/docker/docker) | `28.3.2+incompatible` | `28.5.2+incompatible` | | [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) | `1.15.1` | `1.15.2` | Updates `github.com/Azure/azure-sdk-for-go/sdk/azidentity` from 1.10.1 to 1.13.1 - [Release notes](https://github.com/Azure/azure-sdk-for-go/releases) - [Commits](Azure/azure-sdk-for-go@sdk/azidentity/v1.10.1...sdk/azidentity/v1.13.1) Updates `github.com/aws/aws-sdk-go-v2/config` from 1.32.13 to 1.32.14 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Commits](aws/aws-sdk-go-v2@config/v1.32.13...config/v1.32.14) Updates `github.com/aws/aws-sdk-go-v2/credentials` from 1.19.13 to 1.19.14 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Commits](aws/aws-sdk-go-v2@credentials/v1.19.13...credentials/v1.19.14) Updates `github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager` from 0.1.13 to 0.1.15 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Commits](aws/aws-sdk-go-v2@feature/s3/transfermanager/v0.1.13...feature/s3/transfermanager/v0.1.15) Updates `github.com/aws/aws-sdk-go-v2/service/ecs` from 1.75.0 to 1.77.0 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Commits](aws/aws-sdk-go-v2@service/s3/v1.75.0...service/s3/v1.77.0) Updates `github.com/aws/aws-sdk-go-v2/service/lambda` from 1.88.5 to 1.89.0 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Commits](aws/aws-sdk-go-v2@service/s3/v1.88.5...service/s3/v1.89.0) Updates `github.com/aws/aws-sdk-go-v2/service/s3` from 1.98.0 to 1.99.0 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Commits](aws/aws-sdk-go-v2@service/s3/v1.98.0...service/s3/v1.99.0) Updates `github.com/aws/smithy-go` from 1.24.2 to 1.24.3 - [Release notes](https://github.com/aws/smithy-go/releases) - [Changelog](https://github.com/aws/smithy-go/blob/main/CHANGELOG.md) - [Commits](aws/smithy-go@v1.24.2...v1.24.3) Updates `github.com/docker/docker` from 28.3.2+incompatible to 28.5.2+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](moby/moby@v28.3.2...v28.5.2) Updates `github.com/open-policy-agent/opa` from 1.15.1 to 1.15.2 - [Release notes](https://github.com/open-policy-agent/opa/releases) - [Changelog](https://github.com/open-policy-agent/opa/blob/v1.15.2/CHANGELOG.md) - [Commits](open-policy-agent/opa@v1.15.1...v1.15.2) --- updated-dependencies: - dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azidentity dependency-version: 1.13.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: github.com/aws/aws-sdk-go-v2/config dependency-version: 1.32.14 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: github.com/aws/aws-sdk-go-v2/credentials dependency-version: 1.19.14 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager dependency-version: 0.1.15 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: github.com/aws/aws-sdk-go-v2/service/ecs dependency-version: 1.77.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: github.com/aws/aws-sdk-go-v2/service/lambda dependency-version: 1.89.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: github.com/aws/aws-sdk-go-v2/service/s3 dependency-version: 1.99.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: github.com/aws/smithy-go dependency-version: 1.24.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: github.com/docker/docker dependency-version: 28.5.2+incompatible dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: github.com/open-policy-agent/opa dependency-version: 1.15.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump actions/download-artifact from 7 to 8 (#765) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7 to 8. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](actions/download-artifact@v7...v8) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump go.opentelemetry.io/otel/sdk from 1.41.0 to 1.43.0 (#771) Bumps [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) from 1.41.0 to 1.43.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.41.0...v1.43.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/sdk dependency-version: 1.43.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump golang.org/x/term in the go-dependencies group (#772) Bumps the go-dependencies group with 1 update: [golang.org/x/term](https://github.com/golang/term). Updates `golang.org/x/term` from 0.41.0 to 0.42.0 - [Commits](golang/term@v0.41.0...v0.42.0) --- updated-dependencies: - dependency-name: golang.org/x/term dependency-version: 0.42.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump github.com/aws/aws-sdk-go-v2/service/ecs (#773) Bumps the go-dependencies group with 1 update: [github.com/aws/aws-sdk-go-v2/service/ecs](https://github.com/aws/aws-sdk-go-v2). Updates `github.com/aws/aws-sdk-go-v2/service/ecs` from 1.77.0 to 1.78.0 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Commits](aws/aws-sdk-go-v2@service/s3/v1.77.0...service/s3/v1.78.0) --- updated-dependencies: - dependency-name: github.com/aws/aws-sdk-go-v2/service/ecs dependency-version: 1.78.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump step-security/harden-runner (#774) Bumps the github-actions-dependencies group with 1 update: [step-security/harden-runner](https://github.com/step-security/harden-runner). Updates `step-security/harden-runner` from 2.16.1 to 2.17.0 - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](step-security/harden-runner@fe10465...f808768) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-version: 2.17.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump github.com/mattn/go-shellwords (#775) Bumps the go-dependencies group with 1 update: [github.com/mattn/go-shellwords](https://github.com/mattn/go-shellwords). Updates `github.com/mattn/go-shellwords` from 1.0.12 to 1.0.13 - [Commits](mattn/go-shellwords@v1.0.12...v1.0.13) --- updated-dependencies: - dependency-name: github.com/mattn/go-shellwords dependency-version: 1.0.13 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: skip legacy_ref self-references in checklinks plugin (#778) * fix: skip legacy_ref self-references in checklinks plugin Hugo renders the navigation menu with absolute URLs to docs.kosli.com. Newly added legacy_ref versions cause checklinks to fail because the self-referencing links 404 against the live production site until the deploy succeeds (chicken-and-egg). Add https://docs.kosli.com/legacy_ref/ to skipPatterns so any future legacy_ref version addition does not block the deploy. * fix: add trailing newline to netlify.toml * feat(k8s-reporter): add extraVolumes, extraVolumeMounts, extraEnvVars, customCA (#777) * feat(k8s-reporter): add extraVolumes, extraVolumeMounts, extraEnvVars, customCA Adds two layers of support for customers running the k8s-reporter behind a TLS-inspecting proxy that requires a corporate CA bundle: 1. Generic escape hatch — extraVolumes, extraVolumeMounts, extraEnvVars following Bitnami / prometheus-community naming conventions. 2. customCA convenience wrapper — single config block that mounts the CA via subPath into /etc/ssl/certs/ so Go's stdlib picks it up additively alongside the system bundle (avoids the SSL_CERT_FILE footgun that would otherwise replace the system CAs). The Kosli CLI is Go and uses net/http's default transport; no CLI changes are needed because crypto/x509 reads /etc/ssl/certs/ automatically. Refs #776 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * review fixes: defaultMode, x509 keyword, value-table cleanup, env deprecation Addresses parallel review feedback on PR #777: - Add explicit defaultMode: 0644 to customCA Secret volume so the permission posture is self-documenting for auditors. - Tighten the docs description of Go's cert-pool loading: it's two independent passes (cert file + dir scan), not one unified scan. - Add the literal "x509: certificate signed by unknown authority" string to the docs section so customers searching the error message find it. - Replace the SSL_CERT_FILE example in the extraEnvVars block with HTTPS_PROXY — SSL_CERT_FILE is the documented footgun and shouldn't be the first thing copy-pasters see. - Shorten the customCA parent comment so the helm-docs values table reads cleanly; defer detail to the README section. - Mark the existing `env:` map as DEPRECATED in favour of extraEnvVars to remove cross-reference confusion. Both still work. Refs #776 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * revert env deprecation; document env and extraEnvVars as siblings Backing out the env-map deprecation from the previous commit — that was scope creep beyond the customCA feature, made without auditing who relies on env: today or whether the team wants to phase it out. Instead: surface env: in the helm-docs values table (it was previously invisible because the values.yaml entry was fully commented out) and describe env: vs extraEnvVars as sibling options. Behaviour unchanged — env: {} is functionally identical to the previous fully-commented form. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * address Claude bot review on PR #777 - Add `required` guard on customCA.key to prevent the silent empty-subPath footgun (an empty subPath causes K8s to mount the whole Secret as a directory at the mountPath, which would break Go trying to read it as a cert file). - Tighten the env range loop with `{{- end }}` so the rendered env block doesn't carry a trailing blank line before extraEnvVars. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * restore env: comment as instruction (not example) Reverting the editorial framing in the env: comment. The original comment was a directive for single-tenant Kosli instances, not an example. Also dropping the extraEnvVars cross-reference — that was scope creep added without justification. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Apply suggestions from code review Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * address remaining Claude bot review on PR #777 Picking up safe-to-fix nits regardless of strict scope: - Quote customCA.secretName and subPath, matching the pattern used for cronSchedule and image fields. mbevc1 also asked for this. - Quote $value in the env range so user-supplied values containing YAML special chars (colons, brackets) render safely. - Tighten the podLabels range with `{{- end }}` for consistency with the env-range fix in commit b44df21. Pre-existing whitespace nit, not introduced by this PR, but cheap to fix while I'm here. - Collapse the env: helm-docs comment to a single line so it reads cleanly in the rendered values table (the multi-line YAML example collapsed badly after helm-docs concatenation). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * quote podLabels values; fix double-space typo in range loops Same fix as the env value quoting in f2af5bf, applied to podLabels for consistency. Also fixes the double-space typo (`:= .Values.`) in both range loops — harmless cosmetic carry-over from the original template. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Marko Bevc <marko@kosli.com> Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * Remove dead Pipedrive chat widget from docs footer (#783) We moved off Pipedrive to HubSpot almost a year ago, but the LeadBooster loader script was still embedded on every docs page — silently pinging an abandoned Pipedrive workspace (companyId 7960593) on every visit and rendering nothing. Also blocking Netlify deploys: the link checker times out on leadbooster-chat.pipedrive.com from Netlify's build infra. Removing the script tag fixes the deploy as a side effect. * 5348 sonar qube pr problem (#780) * Added hard coded test for sonarqube PR scan to reproduce error server/#5348 * Fixed problem and change to use kosli attest sonar for test * Added sonar test data * green: add --sonar-ce-task-url flag for CI environments without report-task.txt access Allows users to pass the SonarQube CE task URL directly, bypassing the need for the .scannerwork/report-task.txt file. This solves the case where the scanner and the Kosli CLI run in different containers (e.g. Jenkins with Kubernetes pod agents) and don't share a filesystem. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Updated docmentation * fix: check error before using http.NewRequest result in GetCETaskData Reorder the error check to come before taskRequest.Header.Add() to prevent a nil pointer dereference if NewRequest fails. Pre-existing bug, but now more reachable via the new --sonar-ce-task-url flag. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: check error before using http.NewRequest result in all sonar functions Same nil pointer dereference pattern as fixed in GetCETaskData, now fixed in GetProjectAnalysisFromRevision, GetProjectAnalysisFromAnalysisID, GetQualityGate, and GetTaskID. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: handle error return from Body.Close to satisfy errcheck linter Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: add PR fixture update instructions and fix inaccurate comment Add instructions for updating the PR scan test fixture to update-sonarqube-test-data.txt. Fix comment on readFile that incorrectly claimed it extracts the project key. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add missing defer Body.Close in GetProjectAnalysisFromAnalysisID Response body was never closed, leaking connections. Also moved the error check before the loop for consistency with GetPRAnalysisData. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: use appVersion as a default CLI version (#785) * feat: use appVersion as a default CLI version * feat: use appVersion as a default CLI version - add tag comment * feat: use appVersion as a default CLI version - bump Chart version * Enable retrieving sonarqube scan results for PRs (#784) * Enable retrieving sonarqube scan results for PRs * Fix failing test * Resolve merge conflicts and update docs for --pull-request flag Merge both --pull-request and --sonar-ce-task-url flags, update long description to document method 2 supporting PR scans, add key+PR example, fix test golden output, and renumber tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * improve PR support and fix resource leaks in sonar attestation --------- Co-authored-by: Tore Martin Hagen <tore@kosli.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Update helm docs (#786) Co-authored-by: ci-signed-commit-bot[bot] <247774526+ci-signed-commit-bot[bot]@users.noreply.github.com> * Guard against lightweight tags in release workflow (#787) Add a fail-fast check in the release workflow pre-build job that rejects lightweight tags with a clear error message pointing to 'make release'. Also document the correct release process in CLAUDE.md. Discovered during the v2.16.0 release when 'gh release create' was used instead of 'make release', causing never-alone-trail failures. * docs: clarify OpenShift runAsUser must be set to null, not omitted (#789) Helm deep-merges values overrides with chart defaults, so simply omitting runAsUser from a values file does not remove it from the rendered spec. The default of 1000 always survives. For OpenShift environments with SCC, users must explicitly set runAsUser: null. Updated values.yaml comments with a concrete example and explanation. Regenerated README.md and docs site via helm-docs. * Sonar qube pr test now uses the lastest sonar-qube-pr scan and not a hard coded value server/#5354 (#792) * Dynamically fetch PR scan test data from GitHub artifact Test 21 was hardcoded to a specific SonarCloud PR scan that would break when SonarCloud housekeeping deletes old data. Instead, download the report-task.txt from a GitHub Actions artifact uploaded by the sonar-pr-trigger workflow in cyber-dojo/differ. Resolves kosli-dev/server#5354 (test 21) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Use dynamic PR scan data for tests 18, 20, and 26 Parse the downloaded report-task.txt to extract the PR key and CE task URL, replacing the hardcoded PR 359 references in tests that use --pull-request and --sonar-ce-task-url flags. Resolves kosli-dev/server#5354 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Add GH_TOKEN to test workflow for sonar PR scan tests Sonar tests download a report-task.txt artifact from cyber-dojo/differ, which requires a GitHub token with actions:read scope on that repo. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: check for latest version (#781) * feat: check for latest version * feat: check for latest version - fix issues * feat: check for latest version - address feedback * feat: check for latest version - address feedback2 * feat: check for latest version - add version flag and don't check versions for internal commands * feat: check for latest version - minor fixes * Update internal/version/update_check_test.go Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * feat: check for latest version - minor improvements * feat: check for latest version - minor nits * feat: check for latest version - add comment * feat: check for latest version - add more comments * feat: check for latest version - add more tests --------- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * chore: helm-docs GHA and use more modern version (#793) * chore: helm-docs GHA and use more modern version * Update .github/workflows/helm-chart.yml Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * chore: helm-docs GHA and use more modern version - ping action --------- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * chore: re-trigger helm-docs (#795) * Update helm docs (#796) Co-authored-by: ci-signed-commit-bot[bot] <247774526+ci-signed-commit-bot[bot]@users.noreply.github.com> * 4808 fix attestation name check (#794) * Don't allow empty strings on either side of the dot in attestation name * Add tests for attestation name check * Add tests for name check to all attest commands * Fix PR tests * Make slack failure webhook trigger on main instead of master (#797) * chore(deps): bump github.com/moby/spdystream from 0.5.0 to 0.5.1 (#798) Bumps [github.com/moby/spdystream](https://github.com/moby/spdystream) from 0.5.0 to 0.5.1. - [Release notes](https://github.com/moby/spdystream/releases) - [Commits](moby/spdystream@v0.5.0...v0.5.1) --- updated-dependencies: - dependency-name: github.com/moby/spdystream dependency-version: 0.5.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump the go-dependencies group with 6 updates (#800) Bumps the go-dependencies group with 6 updates: | Package | From | To | | --- | --- | --- | | [github.com/Azure/azure-sdk-for-go/sdk/azcore](https://github.com/Azure/azure-sdk-for-go) | `1.21.0` | `1.21.1` | | [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) | `1.32.14` | `1.32.15` | | [github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager](https://github.com/aws/aws-sdk-go-v2) | `0.1.15` | `0.1.16` | | [github.com/aws/smithy-go](https://github.com/aws/smithy-go) | `1.24.3` | `1.25.0` | | [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) | `5.17.2` | `5.18.0` | | [k8s.io/kubernetes](https://github.com/kubernetes/kubernetes) | `1.35.3` | `1.35.4` | Updates `github.com/Azure/azure-sdk-for-go/sdk/azcore` from 1.21.0 to 1.21.1 - [Release notes](https://github.com/Azure/azure-sdk-for-go/releases) - [Commits](Azure/azure-sdk-for-go@sdk/azcore/v1.21.0...sdk/azcore/v1.21.1) Updates `github.com/aws/aws-sdk-go-v2/config` from 1.32.14 to 1.32.15 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Commits](aws/aws-sdk-go-v2@config/v1.32.14...config/v1.32.15) Updates `github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager` from 0.1.15 to 0.1.16 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Commits](aws/aws-sdk-go-v2@feature/s3/transfermanager/v0.1.15...feature/s3/transfermanager/v0.1.16) Updates `github.com/aws/smithy-go` from 1.24.3 to 1.25.0 - [Release notes](https://github.com/aws/smithy-go/releases) - [Changelog](https://github.com/aws/smithy-go/blob/main/CHANGELOG.md) - [Commits](aws/smithy-go@v1.24.3...v1.25.0) Updates `github.com/go-git/go-git/v5` from 5.17.2 to 5.18.0 - [Release notes](https://github.com/go-git/go-git/releases) - [Commits](go-git/go-git@v5.17.2...v5.18.0) Updates `k8s.io/kubernetes` from 1.35.3 to 1.35.4 - [Release notes](https://github.com/kubernetes/kubernetes/releases) - [Commits](kubernetes/kubernetes@v1.35.3...v1.35.4) --- updated-dependencies: - dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azcore dependency-version: 1.21.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: github.com/aws/aws-sdk-go-v2/config dependency-version: 1.32.15 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager dependency-version: 0.1.16 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: github.com/aws/smithy-go dependency-version: 1.25.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: github.com/go-git/go-git/v5 dependency-version: 5.18.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: k8s.io/kubernetes dependency-version: 1.35.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump step-security/harden-runner (#801) Bumps the github-actions-dependencies group with 1 update: [step-security/harden-runner](https://github.com/step-security/harden-runner). Updates `step-security/harden-runner` from 2.17.0 to 2.18.0 - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](step-security/harden-runner@f808768...6c3c2f2) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-version: 2.18.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: remove duplicate/orphaned line in FakeLambdaClient.ListFunctions A stray `pageSize = int(*params.MaxItems)` and closing brace outside the if-block caused a syntax error. Remove the dangling lines. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * address review comments: add error-type comment and rename skipOrSetCreds - fake_lambda.go: note that real AWS returns *types.ResourceNotFoundException - aws_test.go: rename skipOrSetCreds -> skipIfCredsUnset (it only skips) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: SimonC <sd.castagna@gmail.com> Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: Simon Castagna <simon@kosli.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: AlexKantor87 <alex@kosli.com> Co-authored-by: Marko Bevc <marko@kosli.com> Co-authored-by: Tore Martin Hagen <93583343+ToreMerkely@users.noreply.github.com> Co-authored-by: Faye <108031168+FayeSGW@users.noreply.github.com> Co-authored-by: Tore Martin Hagen <tore@kosli.com> Co-authored-by: ci-signed-commit-bot[bot] <247774526+ci-signed-commit-bot[bot]@users.noreply.github.com>
1 parent d76c084 commit d91a7ca

7 files changed

Lines changed: 574 additions & 144 deletions

File tree

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ test_integration_restart_server: test_setup_restart_server
144144
test_integration_single: test_setup
145145
@export KOSLI_TESTS=true $(FAKE_CI_ENV) && $(GOTESTSUM) -- -p=1 ./... -run "${TARGET}"
146146

147+
test_smoke_aws: ## Run AWS contract and smoke tests against real AWS (requires AWS creds)
148+
@echo "Running AWS contract and smoke tests against real AWS..."
149+
@echo "Requires AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to be set"
150+
@$(GOTESTSUM) -- -v -p=1 -run "LambdaContract_RealAWS|AWSTestSuite/TestGetLambdaPackageData|AWSTestSuite/TestGetEcsTasksData|AWSTestSuite/TestGetS3Data" ./internal/aws/
151+
147152

148153
test_docs: deps vet ensure_network test_setup ## Test docs
149154
./bin/test_docs_cmds.sh docs.kosli.com/content/use_cases/simulating_a_devops_system/_index.md

TODO.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,63 @@
5454
- [x] Slice 2: Add `--params` flag across all three commands
5555
- [x] Slice 3: Show params in `--show-input` output
5656
- [x] Slice 4: Update help text and examples
57+
58+
## Fakes & contract tests for cloud provider integrations (#758)
59+
60+
### Lambda (done — this PR)
61+
62+
- [x] Slice 1: Define `LambdaAPI` interface and refactor signatures
63+
- [x] Slice 2: Contract test suite against real AWS
64+
- [x] Slice 3: Build `FakeLambdaClient` that passes the contract
65+
- [x] Slice 4: Fake-backed unit tests for filtering and pagination
66+
- [x] Slice 5: Fake-backed unit tests for orchestration
67+
- [x] Slice 6: Trim existing integration tests
68+
- [x] Slice 7: Package-level factory + fake-backed command tests
69+
70+
### ECS (next)
71+
72+
- [ ] Define `ECSAPI` interface (`ListClusters`, `DescribeClusters`, `ListServices`, `ListTasks`, `DescribeTasks`) and refactor signatures
73+
- [ ] Contract test suite against real AWS (env-gated)
74+
- [ ] Build `FakeECSClient` that passes the contract (nested pagination: clusters → services → tasks)
75+
- [ ] Fake-backed unit tests for filtering (cluster names, service names, regex, exclude patterns)
76+
- [ ] Fake-backed unit tests for orchestration (concurrent cluster/service/task fetching, error propagation)
77+
- [ ] `NewECSClientFunc` factory + inject fake into `snapshotECS_test.go` command tests
78+
- [ ] Trim existing ECS integration tests to smoke tests
79+
- [ ] Add ECS to `make test_smoke_aws`
80+
81+
### S3
82+
83+
- [ ] Define `S3API` interface (decide: fake at paginator level or raw `ListObjectsV2` level)
84+
- [ ] Contract test suite against real AWS (env-gated)
85+
- [ ] Build `FakeS3Client` that passes the contract
86+
- [ ] Fake-backed unit tests for path include/exclude filtering and digest computation
87+
- [ ] `NewS3ClientFunc` factory + inject fake into `snapshotS3_test.go` command tests
88+
- [ ] Trim existing S3 integration tests to smoke tests
89+
- [ ] Add S3 to `make test_smoke_aws`
90+
91+
### Azure Apps
92+
93+
- [ ] Define interfaces for ARM AppService + Azure Container Registry clients
94+
- [ ] Contract test suite against real Azure (env-gated)
95+
- [ ] Build fakes that pass the contracts
96+
- [ ] Fake-backed unit tests for app listing, image fingerprinting, error propagation
97+
- [ ] Factory + inject fakes into `snapshotAzureApps_test.go` command tests
98+
- [ ] Trim existing Azure integration tests to smoke tests
99+
100+
### Docker
101+
102+
- [ ] Define `DockerAPI` interface (Pull, Push, Tag, Remove, Run, container operations)
103+
- [ ] Contract test suite against real Docker daemon
104+
- [ ] Build `FakeDockerClient` that passes the contract
105+
- [ ] Fake-backed unit tests
106+
- [ ] Factory + inject fake into `snapshotDocker_test.go` command tests
107+
- [ ] Trim existing Docker integration tests to smoke tests
108+
109+
### Kubernetes
110+
111+
- [ ] Define interface for Kubernetes clientset operations (pod listing, namespace listing)
112+
- [ ] Contract test suite against real cluster (KIND, env-gated)
113+
- [ ] Build fake that passes the contract (semaphore pattern, namespace filtering)
114+
- [ ] Fake-backed unit tests for filtering, large-scale concurrency, error propagation
115+
- [ ] Factory + inject fake into `snapshotK8S_test.go` command tests
116+
- [ ] Trim existing Kube integration tests to smoke tests

cmd/kosli/snapshotLambda_test.go

Lines changed: 47 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import (
44
"fmt"
55
"testing"
66

7-
"github.com/kosli-dev/cli/internal/testHelpers"
7+
"github.com/aws/aws-sdk-go-v2/service/lambda/types"
8+
"github.com/kosli-dev/cli/internal/aws"
89
"github.com/stretchr/testify/suite"
910
)
1011

@@ -19,10 +20,6 @@ type SnapshotLambdaTestSuite struct {
1920
imageFunctionName string
2021
}
2122

22-
type snapshotLambdaTestConfig struct {
23-
requireAuthToBeSet bool
24-
}
25-
2623
func (suite *SnapshotLambdaTestSuite) SetupTest() {
2724
suite.envName = "snapshot-lambda-env"
2825
suite.zipFunctionName = "cli-tests"
@@ -35,67 +32,75 @@ func (suite *SnapshotLambdaTestSuite) SetupTest() {
3532
suite.defaultKosliArguments = fmt.Sprintf(" --host %s --org %s --api-token %s", global.Host, global.Org, global.ApiToken)
3633

3734
CreateEnv(global.Org, suite.envName, "lambda", suite.T())
35+
36+
// Inject fake Lambda client so tests run without AWS credentials.
37+
// The fake is seeded with two functions matching the names used in test cases.
38+
zipCodeSha256 := "Mh48OOkSYuXHLfS9QF6bF3tvTXUOGvC3jKLiuF1vkbQ="
39+
imageCodeSha256 := "e908950659e56bb886acbb0ecf9b8f38bf6e0382ede71095e166269ee4db601e"
40+
lastModified := "2024-01-15T10:30:00.000+0000"
41+
zipName := suite.zipFunctionName
42+
imageName := suite.imageFunctionName
43+
aws.NewLambdaClientFunc = func(_ *aws.AWSStaticCreds) (aws.LambdaAPI, error) {
44+
return &aws.FakeLambdaClient{
45+
Functions: []types.FunctionConfiguration{
46+
{
47+
FunctionName: &zipName,
48+
CodeSha256: &zipCodeSha256,
49+
LastModified: &lastModified,
50+
PackageType: types.PackageTypeZip,
51+
},
52+
{
53+
FunctionName: &imageName,
54+
CodeSha256: &imageCodeSha256,
55+
LastModified: &lastModified,
56+
PackageType: types.PackageTypeImage,
57+
},
58+
},
59+
}, nil
60+
}
61+
}
62+
63+
func (suite *SnapshotLambdaTestSuite) TearDownTest() {
64+
aws.ResetLambdaClientFactory()
3865
}
3966

4067
func (suite *SnapshotLambdaTestSuite) TestSnapshotLambdaCmd() {
4168
tests := []cmdTestCase{
4269
{
43-
name: "snapshot lambda works with deprecated --function-name for Zip package type",
44-
cmd: fmt.Sprintf(`snapshot lambda %s %s --function-name %s`, suite.envName, suite.defaultKosliArguments, suite.zipFunctionName),
45-
additionalConfig: snapshotLambdaTestConfig{
46-
requireAuthToBeSet: true,
47-
},
70+
name: "snapshot lambda works with deprecated --function-name for Zip package type",
71+
cmd: fmt.Sprintf(`snapshot lambda %s %s --function-name %s`, suite.envName, suite.defaultKosliArguments, suite.zipFunctionName),
4872
golden: fmt.Sprintf("Flag --function-name has been deprecated, use --function-names instead\n1 lambda functions were reported to environment %s\n", suite.envName),
4973
},
5074
{
51-
name: "snapshot lambda works with --function-names for Zip package type",
52-
cmd: fmt.Sprintf(`snapshot lambda %s %s --function-names %s`, suite.envName, suite.defaultKosliArguments, suite.zipFunctionName),
53-
additionalConfig: snapshotLambdaTestConfig{
54-
requireAuthToBeSet: true,
55-
},
75+
name: "snapshot lambda works with --function-names for Zip package type",
76+
cmd: fmt.Sprintf(`snapshot lambda %s %s --function-names %s`, suite.envName, suite.defaultKosliArguments, suite.zipFunctionName),
5677
golden: fmt.Sprintf("1 lambda functions were reported to environment %s\n", suite.envName),
5778
},
5879
{
59-
name: "snapshot lambda works with --function-names taking a list of functions",
60-
cmd: fmt.Sprintf(`snapshot lambda %s %s --function-names %s,%s`, suite.envName, suite.defaultKosliArguments, suite.zipFunctionName, suite.imageFunctionName),
61-
additionalConfig: snapshotLambdaTestConfig{
62-
requireAuthToBeSet: true,
63-
},
80+
name: "snapshot lambda works with --function-names taking a list of functions",
81+
cmd: fmt.Sprintf(`snapshot lambda %s %s --function-names %s,%s`, suite.envName, suite.defaultKosliArguments, suite.zipFunctionName, suite.imageFunctionName),
6482
golden: fmt.Sprintf("2 lambda functions were reported to environment %s\n", suite.envName),
6583
},
6684
{
67-
name: "snapshot lambda works with --function-names for Image package type",
68-
cmd: fmt.Sprintf(`snapshot lambda %s %s --function-names %s`, suite.envName, suite.defaultKosliArguments, suite.imageFunctionName),
69-
additionalConfig: snapshotLambdaTestConfig{
70-
requireAuthToBeSet: true,
71-
},
85+
name: "snapshot lambda works with --function-names for Image package type",
86+
cmd: fmt.Sprintf(`snapshot lambda %s %s --function-names %s`, suite.envName, suite.defaultKosliArguments, suite.imageFunctionName),
7287
golden: fmt.Sprintf("1 lambda functions were reported to environment %s\n", suite.envName),
7388
},
7489
{
75-
name: "snapshot lambda works with --function-names and deprecated --function-version which is ignored",
76-
cmd: fmt.Sprintf(`snapshot lambda %s %s --function-names %s --function-version 317`, suite.envName, suite.defaultKosliArguments, suite.zipFunctionName),
77-
additionalConfig: snapshotLambdaTestConfig{
78-
requireAuthToBeSet: true,
79-
},
90+
name: "snapshot lambda works with --function-names and deprecated --function-version which is ignored",
91+
cmd: fmt.Sprintf(`snapshot lambda %s %s --function-names %s --function-version 317`, suite.envName, suite.defaultKosliArguments, suite.zipFunctionName),
8092
golden: fmt.Sprintf("Flag --function-version has been deprecated, --function-version is no longer supported. It will be removed in a future release.\n1 lambda functions were reported to environment %s\n", suite.envName),
8193
},
8294
{
83-
wantError: false,
84-
name: "snapshot lambda without --function-names will report all lambdas in the AWS account",
85-
cmd: fmt.Sprintf(`snapshot lambda %s %s`, suite.envName, suite.defaultKosliArguments),
86-
additionalConfig: snapshotLambdaTestConfig{
87-
requireAuthToBeSet: true,
88-
},
95+
name: "snapshot lambda without --function-names will report all lambdas",
96+
cmd: fmt.Sprintf(`snapshot lambda %s %s`, suite.envName, suite.defaultKosliArguments),
8997
goldenRegex: fmt.Sprintf("[0-9]+ lambda functions were reported to environment %s\n", suite.envName),
9098
},
9199
{
92100
wantError: true,
93101
name: "snapshot lambda fails when both of --function-name and --function-names are set",
94102
cmd: fmt.Sprintf(`snapshot lambda %s --function-name foo --function-names foo %s`, suite.envName, suite.defaultKosliArguments),
95-
additionalConfig: snapshotLambdaTestConfig{
96-
requireAuthToBeSet: true,
97-
},
98-
golden: "Flag --function-name has been deprecated, use --function-names instead\nError: only one of --function-name, --function-names, --exclude is allowed\n",
103+
golden: "Flag --function-name has been deprecated, use --function-names instead\nError: only one of --function-name, --function-names, --exclude is allowed\n",
99104
},
100105
{
101106
wantError: true,
@@ -122,19 +127,13 @@ func (suite *SnapshotLambdaTestSuite) TestSnapshotLambdaCmd() {
122127
golden: "Error: only one of --function-name, --function-names, --exclude-regex is allowed\n",
123128
},
124129
{
125-
name: "snapshot lambda works if both --exclude and --exclude-regex are set",
126-
cmd: fmt.Sprintf(`snapshot lambda %s %s --exclude %s --exclude-regex function1`, suite.envName, suite.defaultKosliArguments, suite.zipFunctionName),
127-
additionalConfig: snapshotLambdaTestConfig{
128-
requireAuthToBeSet: true,
129-
},
130+
name: "snapshot lambda works if both --exclude and --exclude-regex are set",
131+
cmd: fmt.Sprintf(`snapshot lambda %s %s --exclude %s --exclude-regex function1`, suite.envName, suite.defaultKosliArguments, suite.zipFunctionName),
130132
goldenRegex: fmt.Sprintf("[0-9]+ lambda functions were reported to environment %s\n", suite.envName),
131133
},
132134
}
133135

134136
for _, t := range tests {
135-
if t.additionalConfig != nil && t.additionalConfig.(snapshotLambdaTestConfig).requireAuthToBeSet {
136-
testHelpers.SkipIfEnvVarUnset(suite.T(), []string{"AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"})
137-
}
138137
runTestCmd(suite.T(), []cmdTestCase{t})
139138
}
140139
}

internal/aws/aws.go

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,27 @@ func (staticCreds *AWSStaticCreds) NewLambdaClient() (*lambda.Client, error) {
139139
return lambda.NewFromConfig(cfg), nil
140140
}
141141

142+
// LambdaAPI is the interface for AWS Lambda operations used by this package.
143+
// The real *lambda.Client satisfies this implicitly.
144+
type LambdaAPI interface {
145+
ListFunctions(ctx context.Context, params *lambda.ListFunctionsInput, optFns ...func(*lambda.Options)) (*lambda.ListFunctionsOutput, error)
146+
GetFunctionConfiguration(ctx context.Context, params *lambda.GetFunctionConfigurationInput, optFns ...func(*lambda.Options)) (*lambda.GetFunctionConfigurationOutput, error)
147+
}
148+
149+
// defaultNewLambdaClient creates a real Lambda client from credentials.
150+
func defaultNewLambdaClient(creds *AWSStaticCreds) (LambdaAPI, error) {
151+
return creds.NewLambdaClient()
152+
}
153+
154+
// NewLambdaClientFunc is the factory used by GetLambdaPackageData to create a
155+
// LambdaAPI client. Tests can replace this to inject a FakeLambdaClient.
156+
var NewLambdaClientFunc = defaultNewLambdaClient
157+
158+
// ResetLambdaClientFactory restores the default (real AWS) client factory.
159+
func ResetLambdaClientFactory() {
160+
NewLambdaClientFunc = defaultNewLambdaClient
161+
}
162+
142163
// NewECSClient returns a new ECS API client
143164
func (staticCreds *AWSStaticCreds) NewECSClient() (*ecs.Client, error) {
144165
cfg, err := staticCreds.NewAWSConfigFromEnvOrFlags()
@@ -149,7 +170,7 @@ func (staticCreds *AWSStaticCreds) NewECSClient() (*ecs.Client, error) {
149170
}
150171

151172
// getFilteredLambdaFuncs fetches a filtered set of lambda functions recursively (50 at a time) and returns a list of FunctionConfiguration
152-
func getFilteredLambdaFuncs(client *lambda.Client, nextMarker *string, allFunctions *[]types.FunctionConfiguration,
173+
func getFilteredLambdaFuncs(client LambdaAPI, nextMarker *string, allFunctions *[]types.FunctionConfiguration,
153174
filter *filters.ResourceFilterOptions) (*[]types.FunctionConfiguration, error) {
154175
params := &lambda.ListFunctionsInput{}
155176
if nextMarker != nil {
@@ -187,11 +208,16 @@ func getFilteredLambdaFuncs(client *lambda.Client, nextMarker *string, allFuncti
187208

188209
// GetLambdaPackageData returns a digest and metadata of a Lambda function package
189210
func (staticCreds *AWSStaticCreds) GetLambdaPackageData(filter *filters.ResourceFilterOptions) ([]*LambdaData, error) {
190-
lambdaData := []*LambdaData{}
191-
client, err := staticCreds.NewLambdaClient()
211+
client, err := NewLambdaClientFunc(staticCreds)
192212
if err != nil {
193-
return lambdaData, err
213+
return []*LambdaData{}, err
194214
}
215+
return getLambdaPackageDataFromClient(client, filter)
216+
}
217+
218+
// getLambdaPackageDataFromClient fetches Lambda function data using the provided LambdaAPI client.
219+
func getLambdaPackageDataFromClient(client LambdaAPI, filter *filters.ResourceFilterOptions) ([]*LambdaData, error) {
220+
lambdaData := []*LambdaData{}
195221

196222
filteredFunctions, err := getFilteredLambdaFuncs(client, nil, &[]types.FunctionConfiguration{}, filter)
197223
if err != nil {
@@ -247,7 +273,7 @@ func (staticCreds *AWSStaticCreds) GetLambdaPackageData(filter *filters.Resource
247273
}
248274

249275
// getAndProcessOneLambdaFunc get a lambda function by its name and return a LambdaData object from it
250-
func getAndProcessOneLambdaFunc(client *lambda.Client, functionName string) (*LambdaData, error) {
276+
func getAndProcessOneLambdaFunc(client LambdaAPI, functionName string) (*LambdaData, error) {
251277
params := &lambda.GetFunctionConfigurationInput{
252278
FunctionName: aws.String(functionName),
253279
}

0 commit comments

Comments
 (0)