Compare commits

...

384 Commits
v1.1.0 ... main

Author SHA1 Message Date
Matheus Pimenta d7cba67d48
Merge pull request #1160 from abhijith-darshan/feat/gh_app_tls
Add support for mTLS to GitHub App transport
2025-08-18 10:16:40 +01:00
abhijith-darshan 4eae0d34da
Add support for mTLS to GitHub App transport
This commit ensures that if GitHub app secret data contains ca.crt then a TLS config with user provided custom ca is used in the underlying HTTP transports. The ca.crt in GitHub App secretRef is ignored if certSecretRef is also provided.

Signed-off-by: abhijith-darshan <abhijith.darshan@hotmail.com>

(chore): keep Makefile in sync with other controllers

Signed-off-by: abhijith-darshan <abhijith.darshan@hotmail.com>

(chore): use proper func naming format

Signed-off-by: abhijith-darshan <abhijith.darshan@hotmail.com>

(chore): revert Makefile changes

Signed-off-by: abhijith-darshan <abhijith.darshan@hotmail.com>

(chore): add get secret helper

This commit creates a getSecret helper func which can be used to resolve secret. createNotifier re-uses this helper func to extract and pass secrets down to other methods

Signed-off-by: abhijith-darshan <abhijith.darshan@hotmail.com>

(chore): adds tls test cases

Signed-off-by: abhijith-darshan <abhijith.darshan@hotmail.com>

(chore): remove debug logs

Signed-off-by: abhijith-darshan <abhijith.darshan@hotmail.com>

(chore): adds documentation

Signed-off-by: abhijith-darshan <abhijith.darshan@hotmail.com>

(chore): update docs with mTLS info

Signed-off-by: abhijith-darshan <abhijith.darshan@hotmail.com>
2025-08-18 11:03:43 +02:00
Matheus Pimenta c2a0355a85
Merge pull request #1161 from cappyzawa/feat/default-service-account-flag
[RFC-0010] Add default-service-account for lockdown
2025-08-17 17:54:24 +01:00
cappyzawa 10a6172536
[RFC-0010] Add default-service-account for lockdown
Add --default-service-account flag for multi-tenant workload identity
lockdown support. This flag sets the default service account name to
be used when .spec.serviceAccountName is not specified in resources.

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-08-18 01:44:25 +09:00
Matheus Pimenta 5bd63a94e4
Merge pull request #1158 from cappyzawa/remove-tlsconfig-servername-pinning
Remove TLS ServerName pinning in TLS config creation
2025-08-14 19:12:31 +01:00
cappyzawa 5be0d2b66c
Remove TLS ServerName pinning in TLS config creation
Updates pkg/runtime dependency to v0.80.0 which removes the need for
the insecure parameter in TLSConfigFromSecretRef. This change removes
the forced ServerName pinning behavior that was causing TLS verification
issues, allowing for more flexible certificate validation.

The TLS config creation now relies on the standard Go TLS verification
process without forcing specific ServerName values, improving
compatibility with various certificate configurations.

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-08-15 02:44:18 +09:00
Stefan Prodan 81c25cf90e
Merge pull request #1157 from fluxcd/remove-v1beta1-api
Remove deprecated APIs in group `notification.toolkit.fluxcd.io/v1beta1`
2025-08-11 17:54:48 +03:00
Stefan Prodan 660e7d2aea
Remove deprecated APIs in group `notification.toolkit.fluxcd.io/v1beta1`
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2025-08-08 15:11:48 +03:00
Matheus Pimenta 4d1c5032d1
Merge pull request #1154 from cappyzawa/feat/google-pubsub-workload-identity
[RFC-0010] Add object-level workload identity support to Google Pub/Sub notifier
2025-08-02 23:42:24 +01:00
cappyzawa 039cd81a6f
docs: enhance workload identity documentation for providers
Add comprehensive workload identity documentation for both Google Pub/Sub and Azure DevOps providers.
Include controller-level and object-level authentication patterns with feature gate requirements
and setup instructions for multi-tenant environments.

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-08-03 07:35:37 +09:00
cappyzawa 43b3104555
Add object-level workload identity support to Google Pub/Sub notifier
Add support for object-level GCP workload identity authentication to enable
individual Providers to authenticate using their own ServiceAccount without
needing to manage JSON credentials. This extends beyond the existing
controller-level workload identity that is automatically handled by
Google libraries.

The implementation maintains backward compatibility by prioritizing
JSON credentials when both authentication methods are available.
Proxy support is also added following the Azure DevOps pattern
for consistency across notifiers.

This change is part of the broader effort to support multi-tenant
workload identity across Flux controllers (RFC-0010).

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-08-03 07:35:37 +09:00
Matheus Pimenta eddaf14754
Merge pull request #1150 from cappyzawa/docs/mtls-documentation-unification
docs: improve mTLS documentation structure and visibility
2025-07-29 15:45:53 +01:00
cappyzawa c2d0f5ec98
docs: improve mTLS documentation structure and visibility
Reorganize Certificate secret reference section to prioritize mutual TLS
authentication discovery and reduce user friction. The previous structure
buried mTLS information within generic certificate documentation, causing
users to miss this important security feature.

Move provider compatibility validation before configuration examples to
prevent wasted effort with unsupported providers. Create dedicated sections
for mTLS and CA-only authentication with complete examples and clear
explanations of field requirements.

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-07-29 23:28:34 +09:00
Matheus Pimenta 4cc3f62a26
Merge pull request #1152 from fluxcd/am-basic-auth
Introduce proper basic auth support for Alertmanager Provider
2025-07-28 11:43:38 +01:00
Matheus Pimenta 3e69e745a3
Introduce proper basic auth support for Alertmanager Provider
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-07-28 11:32:41 +01:00
Matheus Pimenta 5d49b42544
Merge pull request #1151 from fluxcd/watch-label
Introduce label selector for watching Secrets referenced in Receivers
2025-07-27 23:11:38 +01:00
Matheus Pimenta fd7385ba15
Introduce label selector for watching Secrets referenced in Receivers
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-07-27 20:08:00 +01:00
Matheus Pimenta 8f4c7b2ccf
Merge pull request #1148 from cappyzawa/feat/datadog-sentry-runtime-secrets-integration
Add mTLS support for DataDog and Sentry notifiers
2025-07-22 11:41:02 +01:00
cappyzawa 67c049d3c7
Add mTLS support for DataDog and Sentry notifiers
These notifiers were using x509.CertPool which only supports CA
certificates for server authentication. By migrating to tls.Config,
they now support mutual TLS authentication with client certificates.

This enables secure communication in enterprise environments that
require client certificate authentication, completing the runtime/secrets
migration for these remaining notifiers.

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-07-22 14:23:12 +09:00
Matheus Pimenta 326c6bcf6e
Merge pull request #1147 from cappyzawa/pkg-runtime-v0.75.0-migration
Fix missing TLS ServerName in Provider notifications
2025-07-22 04:51:33 +01:00
cappyzawa f333296240
Fix missing TLS ServerName in Provider notifications
Updates pkg/runtime/secrets to v0.75.0 which adds targetURL and insecure
parameters to TLS functions. This resolves ServerName regression that
caused TLS handshake failures in virtual hosting environments.

The Provider API has no insecure field, so certificates are always
verified (insecure=false). This maintains secure-by-default behavior
and is consistent with the original pre-pkg/runtime/secrets implementation.

All 17+ notification providers automatically benefit from proper ServerName
setting through the centralized TLS configuration in createNotifier().

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-07-22 12:41:05 +09:00
Matheus Pimenta 4496c6e0f2
Merge pull request #1146 from cappyzawa/feat/git-notifiers-runtime-secrets-integration
Add mTLS support for git-based notifiers
2025-07-19 13:51:36 +01:00
cappyzawa 0c1801906a
Add mTLS support for git-based notifiers
Replace x509.CertPool with tls.Config across all Git-based notifiers
(GitHub, GitLab, Gitea, Bitbucket, Azure DevOps, GitHub Dispatch) to
enable mutual TLS authentication for enterprise environments.

Adopt runtime/secrets AuthMethodsFromSecret for standardized handling
of Bearer tokens, basic auth, and token auth while maintaining full
backward compatibility with existing Secret formats.

This unifies authentication processing across Git-based providers and
adds mTLS capability without changing API surface or breaking existing
deployments.

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-07-19 08:31:47 +09:00
Matheus Pimenta 888412e8c5
Merge pull request #1145 from dipti-pai/ado-oidc-support
[RFC-0010] Azure OIDC integration updates for Azure DevOps and Azure EventHub
2025-07-18 16:16:09 +01:00
Dipti Pai dc8e92c119 Azure OIDC integration updates:
- Azure DevOps commit status update using Managed Identity.
- Migrate Azure Event Hubs to new ProducerClient (azeventhubs) sdk
- Unit Tests and doc update

Signed-off-by: Dipti Pai <diptipai89@outlook.com>
2025-07-18 07:58:13 -07:00
Matheus Pimenta a22d67edbb
Merge pull request #1141 from cappyzawa/feat/optional-address-field
Make address field optional for providers that generate URLs internally
2025-07-15 16:32:09 +01:00
cappyzawa 955d24142c
Make address field optional for providers that generate URLs internally
This change removes the generic address validation from event_handlers.go
that was preventing address-optional providers from functioning without
specifying a dummy address value. Some providers generate URLs internally
and don't require external address configuration.

This allows providers that generate URLs internally to work without
requiring dummy address values in the provider configuration.

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-07-16 00:13:29 +09:00
Matheus Pimenta e8a909fac7
Merge pull request #1143 from fluxcd/upgrade-auth
Upgrade Kubernetes to 1.33.2
2025-07-14 17:06:13 +01:00
Matheus Pimenta febff88be7
Upgrade Kubernetes to 1.33.2
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-07-14 16:45:44 +01:00
Matheus Pimenta 5bea87e16b
Merge pull request #1142 from cappyzawa/fix/double-secret-fetch
Fix double secret fetching in BasicAuth processing
2025-07-10 11:50:12 +01:00
cappyzawa a8c2fc0759
Fix double secret fetching in BasicAuth processing
This commit addresses the performance issue where spec.secretRef
was being fetched twice - once in extractAuthFromSecret and again
in secrets.BasicAuthFromSecret. The fix moves BasicAuth processing
directly into extractAuthFromSecret using the already-fetched
secret data, eliminating the redundant API call.

This aligns with the special nature of spec.secretRef that contains
multiple authentication methods and follows the advice to not use
runtime/secrets for special requirements as discussed in flux2#5433.

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-07-10 19:38:33 +09:00
Stefan Prodan 6e18c487d7
Merge pull request #1139 from cappyzawa/feat/basicauth-runtime-secrets
Unify BasicAuth processing using pkg/runtime/secrets
2025-07-10 11:05:01 +03:00
cappyzawa d1c85df902
Unify BasicAuth processing using pkg/runtime/secrets
This commit refactors the createNotifier function to use
pkg/runtime/secrets.BasicAuthFromSecret for standardized BasicAuth
handling while maintaining token-first authentication precedence.

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-07-10 16:56:33 +09:00
Stefan Prodan 9e150256c7
Merge pull request #1140 from cappyzawa/feat/telegram-proxy-support
Add proxy support to Telegram notifier
2025-07-08 16:31:38 +03:00
cappyzawa e4160c509c
fixup! Add proxy support to Telegram notifier
Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-07-08 21:42:27 +09:00
cappyzawa fc4adfd030
Add proxy support to Telegram notifier
Replace shoutrrr with direct Telegram Bot API calls to enable proxy
configuration through postMessage function.

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-07-08 00:15:02 +09:00
Matheus Pimenta 3f4e962c83
Merge pull request #1137 from cappyzawa/feat/mtls-postmessage-notifiers
Add mTLS support for postMessage-based notifiers
2025-07-06 12:26:54 +01:00
cappyzawa 98ecf2de79
Add mTLS support for postMessage-based notifiers
- Implement mTLS support for 10 postMessage notifiers
- Unify constructor signatures with tlsConfig parameter
- Make TLSConfig field public for consistency
- Update factory functions and fuzz tests
- Add mTLS test cases
- Replace CertPool with TLSConfig using runtime/secrets

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-07-03 21:39:16 +09:00
Matheus Pimenta a3e6dd6a10
Merge pull request #1133 from cappyzawa/feat/proxy-secret-ref
Add ProxySecretRef field to Provider API
2025-06-27 15:57:40 +01:00
cappyzawa 8858332c27
Add ProxySecretRef field to Provider API
Introduce spec.proxySecretRef to enable secure proxy configuration
through dedicated Secrets. This provides a more secure alternative
to the deprecated spec.proxy field and secret proxy key.

The new field integrates with runtime/secrets for unified proxy
handling and maintains backward compatibility. Deprecation warnings
are implemented for existing proxy configuration methods.

Proxy priority: ProxySecretRef > secret proxy key > spec.proxy

Signed-off-by: cappyzawa <cappyzawa@gmail.com>
2025-06-27 23:31:02 +09:00
Stefan Prodan 2503bda903
Merge pull request #1128 from fluxcd/fix-docs-markdown
Fix links in provider API doc
2025-05-29 17:17:07 +03:00
Stefan Prodan fc126284ab
Fix links in provider API doc
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2025-05-29 17:09:54 +03:00
Stefan Prodan 8f207d65db
Merge pull request #1127 from fluxcd/dependabot-up
Update dependabot config
2025-05-28 16:17:48 +03:00
Stefan Prodan 61f24e3376
Update dependabot config
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2025-05-28 16:04:13 +03:00
Matheus Pimenta 3f4ba79594
Merge pull request #1123 from fluxcd/update-labels
Add 1.6.x release label
2025-05-28 08:30:32 +01:00
Matheus Pimenta d65c81d035
Add 1.6.x release label
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-05-28 08:23:38 +01:00
Matheus Pimenta 47b95d86a3
Merge pull request #1122 from fluxcd/release/v1.6.x
Release/v1.6.x
2025-05-27 17:29:48 +01:00
Matheus Pimenta 3a6de1fcef
Merge pull request #1121 from fluxcd/release-v1.6.0
Release v1.6.0
2025-05-27 15:26:44 +01:00
Matheus Pimenta a52f071bb9
Release v1.6.0
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-05-27 15:13:55 +01:00
Matheus Pimenta 0e0e912182
Add changelog entry for v1.6.0
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-05-27 15:12:52 +01:00
Matheus Pimenta 7383fe8be5
Merge pull request #1108 from larhauga/fix-crossnamespaceobjectref-maxlength
CrossNamespaceObjectReference: Fix MaxLength validation to k8s max 253 char
2025-05-27 10:44:16 +01:00
Lars Haugan 2284a0db5a
CrossNamespaceObjectReference: Fix MaxLength validation to kubernetes max size of 253
Signed-off-by: Lars Haugan <lars.haugan@sparebank1.no>
2025-05-27 10:34:25 +01:00
Stefan Prodan d32f5e26cc
Merge pull request #1101 from fluxcd/dependabot/github_actions/ci-4c7c75f92f
build(deps): bump the ci group across 1 directory with 14 updates
2025-05-27 12:22:33 +03:00
dependabot[bot] b416d68479
build(deps): bump the ci group across 1 directory with 14 updates
Bumps the ci group with 14 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [korthout/backport-action](https://github.com/korthout/backport-action) | `3.1.0` | `3.2.0` |
| [actions/setup-go](https://github.com/actions/setup-go) | `5.3.0` | `5.4.0` |
| [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `3.4.0` | `3.6.0` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3.9.0` | `3.10.0` |
| [actions/cache](https://github.com/actions/cache) | `4.2.0` | `4.2.3` |
| [docker/login-action](https://github.com/docker/login-action) | `3.3.0` | `3.4.0` |
| [docker/metadata-action](https://github.com/docker/metadata-action) | `5.6.1` | `5.7.0` |
| [docker/build-push-action](https://github.com/docker/build-push-action) | `6.13.0` | `6.16.0` |
| [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) | `3.8.0` | `3.8.2` |
| [anchore/sbom-action](https://github.com/anchore/sbom-action) | `0.18.0` | `0.19.0` |
| [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) | `6.1.0` | `6.3.0` |
| [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator) | `2.0.0` | `2.1.0` |
| [fossa-contrib/fossa-action](https://github.com/fossa-contrib/fossa-action) | `3.0.0` | `3.0.1` |
| [github/codeql-action](https://github.com/github/codeql-action) | `3.28.8` | `3.28.16` |



Updates `korthout/backport-action` from 3.1.0 to 3.2.0
- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](be567af183...436145e922)

Updates `actions/setup-go` from 5.3.0 to 5.4.0
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](f111f3307d...0aaccfd150)

Updates `docker/setup-qemu-action` from 3.4.0 to 3.6.0
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](4574d27a47...29109295f8)

Updates `docker/setup-buildx-action` from 3.9.0 to 3.10.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](f7ce87c1d6...b5ca514318)

Updates `actions/cache` from 4.2.0 to 4.2.3
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](1bd1e32a3b...5a3ec84eff)

Updates `docker/login-action` from 3.3.0 to 3.4.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](9780b0c442...74a5d14239)

Updates `docker/metadata-action` from 5.6.1 to 5.7.0
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](369eb591f4...902fa8ec7d)

Updates `docker/build-push-action` from 6.13.0 to 6.16.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](ca877d9245...14487ce63c)

Updates `sigstore/cosign-installer` from 3.8.0 to 3.8.2
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](c56c2d3e59...3454372f43)

Updates `anchore/sbom-action` from 0.18.0 to 0.19.0
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](f325610c9f...9f73021414)

Updates `goreleaser/goreleaser-action` from 6.1.0 to 6.3.0
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](9ed2f89a66...9c156ee8a1)

Updates `slsa-framework/slsa-github-generator` from 2.0.0 to 2.1.0
- [Release notes](https://github.com/slsa-framework/slsa-github-generator/releases)
- [Changelog](https://github.com/slsa-framework/slsa-github-generator/blob/main/CHANGELOG.md)
- [Commits](https://github.com/slsa-framework/slsa-github-generator/compare/v2.0.0...v2.1.0)

Updates `fossa-contrib/fossa-action` from 3.0.0 to 3.0.1
- [Release notes](https://github.com/fossa-contrib/fossa-action/releases)
- [Changelog](https://github.com/fossa-contrib/fossa-action/blob/master/CHANGELOG.md)
- [Commits](cdc5065bcd...3d2ef181b1)

Updates `github/codeql-action` from 3.28.8 to 3.28.16
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](dd746615b3...28deaeda66)

---
updated-dependencies:
- dependency-name: korthout/backport-action
  dependency-version: 3.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: actions/setup-go
  dependency-version: 5.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/setup-qemu-action
  dependency-version: 3.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/setup-buildx-action
  dependency-version: 3.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: actions/cache
  dependency-version: 4.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: docker/login-action
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/metadata-action
  dependency-version: 5.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/build-push-action
  dependency-version: 6.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: sigstore/cosign-installer
  dependency-version: 3.8.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: anchore/sbom-action
  dependency-version: 0.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: goreleaser/goreleaser-action
  dependency-version: 6.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: slsa-framework/slsa-github-generator
  dependency-version: 2.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: fossa-contrib/fossa-action
  dependency-version: 3.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: github/codeql-action
  dependency-version: 3.28.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-27 09:17:55 +00:00
Matheus Pimenta 3842f0c471
Merge pull request #1120 from fluxcd/rfc-0010-docs
[RFC-0010] Link workload identity docs to complete guide
2025-05-27 09:28:20 +01:00
Matheus Pimenta f2e2340807
[RFC-0010] Link workload identity docs to complete guide
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-05-26 23:42:01 +01:00
Matheus Pimenta 01dfe1208a
Merge pull request #1119 from fluxcd/upgrade-deps
Update dependencies
2025-05-25 16:58:51 +01:00
Matheus Pimenta 0464717037
Update dependencies
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-05-25 14:59:39 +01:00
Matheus Pimenta f3065c67b3
Merge pull request #1086 from ordovicia/fix-1048
Fix Slack `chat.postMessage` error handling
2025-05-24 14:44:39 +01:00
Hidehito Yabuuchi 882383e44c Fix Slack chat.postMessage error handling
Signed-off-by: Hidehito Yabuuchi <hdht.ybuc@gmail.com>
2025-05-24 18:23:45 +09:00
Stefan Prodan 8dd496a132
Merge pull request #1118 from fluxcd/controller-runtime-v0.21.0
Update controller-runtime to v0.21.0
2025-05-23 17:43:17 +02:00
Stefan Prodan de484cd447
Update controller-runtime to v0.21.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2025-05-23 18:28:14 +03:00
Matheus Pimenta b906831c5e
Merge pull request #1116 from fluxcd/rfc-0010-feature-gate
[RFC-0010] Introduce feature gate
2025-05-23 07:59:11 +01:00
Matheus Pimenta e95f8d5b38
[RFC-0010] Introduce feature gate
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-05-19 14:15:57 +01:00
Matheus Pimenta d78779e80b
Merge pull request #1113 from fluxcd/upgrade-deps
Upgrade fluxcd/pkg auth and git
2025-05-07 18:24:56 +01:00
Matheus Pimenta 637d55d0b9
Upgrade fluxcd/pkg auth and git
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-05-07 18:17:38 +01:00
Matheus Pimenta 99c6dbb70f
Merge pull request #1112 from fluxcd/fix-provider-state-machine
Reintroduce default state machine for Provider controller
2025-05-07 12:51:22 +01:00
Matheus Pimenta c32f9e1559
Reintroduce default state machine for Provider controller
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-05-05 22:00:46 +01:00
Matheus Pimenta f5ddc97108
Merge pull request #1106 from dipti-pai/azeventhub-mi-support
[RFC-0010] Implement managed identity support for Azure Event Hub provider
2025-05-05 20:39:45 +01:00
Dipti Pai 0beb3d02f7 Managed Identity support for Azure Event Hubs. Changes include -
- If authentication token is not specified in provider, attempt to get the token using workload identity.
= Add new field .spec.serviceAccountName to support multi-tenant workload identity as defined in RFC-0010 to use an identity with a service account other than the notification-controller.
- Use proxy to get the token if specified in provider spec.
- Cache the tokens if enabled in the notification controller options.
- If address has SAS connection string, use that for authentication, this takes priority over token-authentication
- If static JWT token is specified in the secret reference, use it for authentication, this takes priority over workload identity-acquired token.
- Update RBAC for notification-controller to be able to create service token requests.
- Add unit tests for the 3 authentication mechanisms (SAS, JWT, managed identity).
- Add documentation for using single-tenant and multi-tenant approaches of workload identity with azureeventhub provider.
- Add operation post to github helpers and provider controller for cache event metrics
- Enable token cache by default.

Signed-off-by: Dipti Pai <diptipai89@outlook.com>

review comments

Signed-off-by: Dipti Pai <diptipai89@outlook.com>

enable cache by default

Signed-off-by: Dipti Pai <diptipai89@outlook.com>
2025-05-05 12:03:52 -07:00
Matheus Pimenta 5dfaa1a5ef
Merge pull request #1109 from fluxcd/delete-cache-entries
Delete cache entries on provider object deletion
2025-05-02 13:09:11 +01:00
Matheus Pimenta 4d3a53ac86
Delete cache entries on provider object deletion
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-05-02 13:00:17 +01:00
Stefan Prodan 5b72532bb1
Merge pull request #1104 from fluxcd/k8s-1.33
Update to Kubernetes 1.33.0 and Go 1.24.0
2025-04-29 15:56:10 +03:00
Stefan Prodan 3f7486168e
Update to Kubernetes 1.33.0 and Go 1.24.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2025-04-29 15:45:24 +03:00
Stefan Prodan e970526b1e
Merge pull request #1087 from sdreger/geature/gitea-proxy-url
feat: add `proxyURL` support to Gitea notifier
2025-04-09 17:57:45 +03:00
Sergey Dreger 0338a311f4 feat: add 'proxyURL' support to Gitea notifier
Signed-off-by: Sergey Dreger <sergey.dreger@gmail.com>
2025-04-09 15:06:49 +03:00
Matheus Pimenta 671f7dd377
Merge pull request #1093 from fluxcd/proxy-log
Sanitize proxy error logging
2025-04-08 10:53:12 +01:00
Matheus Pimenta fdeab17bff
Sanitize proxy error logging
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-04-08 10:37:45 +01:00
Stefan Prodan f313afa287
Merge pull request #1084 from sdreger/bugfix/1083/gitea-tls-error
fix: pass 'certPool' to Gitea client on creation
2025-03-24 09:29:19 +02:00
Sergey Dreger 30d8d01687 fix: pass 'certPool' to Gitea client on creation
It is required when a custom CA is passed, otherwise the
gitea.NewClient() call will fail with the 'tls: failed to verify
certificate: x509: certificate signed by unknown authority' error.
Because the current version of Gitea SDK performs a call to the
'/api/v1/version' endpoint during a new client creation, so the
'certPool' must be passed when creating the client.

Resolves: #1083
Signed-off-by: Sergey Dreger <sergey.dreger@gmail.com>
2025-03-23 17:17:41 +02:00
Matheus Pimenta d62be26a3f
Merge pull request #1058 from dipti-pai/github-app-auth
[RFC-007] GitHub App authentication support for github and github-dispatch providers
2025-03-21 16:47:27 +00:00
Dipti Pai bc7166d419 [RFC-007] GitHub App authentication support for github and github-dispatch providers.
- Add providerOpts in notifier to configure authentication options for various providers.
- If token/password are not set to PAT, check if github app details are configured in secret and if found; authenticate using github-app by retrieving app installation token.
- If proxy is specified in the provider spec OR in the secret, configure github app authentication to fetch the installation token over the proxy.
- Add unit tests for providers.
- Update documentation describing the usage of github app authentication with the providers.
- Add token cache to notification controller to cache and re-use the tokens.

Signed-off-by: Dipti Pai <diptipai89@outlook.com>
2025-03-20 14:18:10 -07:00
Matheus Pimenta c476965793
Merge pull request #1077 from v1km4n/docs1063
Update docs to include Telegram forum configuration
2025-03-19 12:41:46 +00:00
Alexey Orlov 1a9858d725 updated docs to include telegram forum chat conf
Signed-off-by: Alexey Orlov <orlov.aa@selectel.com>
Signed-off-by: Alexey Orlov <v1km4n@ya.ru>
2025-03-19 15:15:34 +03:00
Matheus Pimenta e2eac40c33
Merge pull request #1068 from kathleenfrench/kfrench/provider-commit-expr
feat: support CEL string expressions for custom commit statuses in v1beta3 provider type
2025-03-18 19:08:26 +00:00
kathleen french 1967bc0c74 feat: support CEL expressions to construct commit statuses for v1beta3 provider types
Signed-off-by: kathleen french <kfrench@groq.com>
2025-03-14 08:53:55 -04:00
Matheus Pimenta 2763e548bd
Merge pull request #1045 from fluxcd/update-labels
Add 1.5.x release label
2025-02-13 16:05:48 +00:00
Matheus Pimenta cc51c36926
Add 1.5.x release label
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-02-13 15:55:06 +00:00
Matheus Pimenta 543a2b0da2
Merge pull request #1044 from fluxcd/release/v1.5.x
Release/v1.5.x
2025-02-13 15:52:30 +00:00
Matheus Pimenta 85d897c59d
Merge pull request #1043 from fluxcd/release-v1.5.0
Release v1.5.0
2025-02-13 15:28:56 +00:00
Matheus Pimenta ff00d11dae
Release v1.5.0
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-02-13 14:44:11 +00:00
Matheus Pimenta 2b3ccd7ddf
Add changelog entry for v1.5.0
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-02-13 14:44:10 +00:00
Stefan Prodan 384ae9889f
Merge pull request #1042 from fluxcd/dependabot/go_modules/go-deps-80f865df1d
build(deps): bump the go-deps group across 1 directory with 2 updates
2025-02-12 23:19:19 +02:00
dependabot[bot] 2295fcf8e2
build(deps): bump the go-deps group across 1 directory with 2 updates
Bumps the go-deps group with 2 updates in the / directory: [github.com/fluxcd/pkg/ssa](https://github.com/fluxcd/pkg) and [google.golang.org/api](https://github.com/googleapis/google-api-go-client).


Updates `github.com/fluxcd/pkg/ssa` from 0.45.0 to 0.45.1
- [Commits](https://github.com/fluxcd/pkg/compare/oci/v0.45.0...ssa/v0.45.1)

Updates `google.golang.org/api` from 0.218.0 to 0.221.0
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.218.0...v0.221.0)

---
updated-dependencies:
- dependency-name: github.com/fluxcd/pkg/ssa
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-12 20:25:11 +00:00
Matheus Pimenta b64453ba2f
Merge pull request #1041 from fluxcd/cel-fixes
Improvements after CEL resource filtering
2025-02-12 20:23:24 +00:00
Matheus Pimenta 3dc0b66390
Improvements after CEL resource filtering
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-02-12 16:46:59 +00:00
Matheus Pimenta 022b97cabe
Merge pull request #1040 from fluxcd/grafana-annotations
Add involved object reference as annotations for the grafana provider
2025-02-12 15:53:46 +00:00
Matheus Pimenta 7a34aee2bd
Add involved object reference as annotations for the grafana provider
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-02-12 14:10:13 +00:00
Matheus Pimenta 7e14e41f0f
Merge pull request #953 from swoehrl-mw/clarify-gitlab-provider-usage
Clarify gitlab notification provider usage
2025-02-12 12:22:17 +00:00
Sebastian Woehrl b72ecab696 Clarify gitlab provider usage
Currrent gitlab API does not accept project name for setting git commit
status, a project ID must be used.

Signed-off-by: Sebastian Woehrl <sebastian.woehrl@maibornwolff.de>
2025-02-12 11:57:51 +00:00
Matheus Pimenta 5df5b78783
Merge pull request #1039 from fluxcd/missing-return-statement
Fix add missing return statement and a few style issues
2025-02-12 11:57:28 +00:00
Matheus Pimenta c4eed6b243
Fix add missing return statement and a few style issues
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-02-12 11:17:50 +00:00
Matheus Pimenta 83ed0c59e5
Merge pull request #1037 from fluxcd/upgrade-deps
Upgrade pkg/runtime
2025-02-11 12:22:16 +00:00
Matheus Pimenta d52c41e0c4
Upgrade pkg/runtime
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-02-11 11:53:09 +00:00
Stefan Prodan 652d3d331e
Merge pull request #1036 from fluxcd/dependabot/go_modules/go-deps-58a8740459
build(deps): bump the go-deps group across 1 directory with 9 updates
2025-02-11 10:59:26 +02:00
dependabot[bot] 232e66c985
build(deps): bump the go-deps group across 1 directory with 9 updates
Bumps the go-deps group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [cloud.google.com/go/pubsub](https://github.com/googleapis/google-cloud-go) | `1.45.3` | `1.47.0` |
| [github.com/DataDog/datadog-api-client-go/v2](https://github.com/DataDog/datadog-api-client-go) | `2.34.0` | `2.35.0` |
| [github.com/fluxcd/pkg/ssa](https://github.com/fluxcd/pkg) | `0.44.0` | `0.45.0` |
| [github.com/google/cel-go](https://github.com/google/cel-go) | `0.23.1` | `0.23.2` |
| [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) | `1.38.0` | `1.39.0` |
| [gitlab.com/gitlab-org/api/client-go](https://gitlab.com/gitlab-org/api/client-go) | `0.121.0` | `0.122.0` |
| [golang.org/x/oauth2](https://github.com/golang/oauth2) | `0.25.0` | `0.26.0` |
| [golang.org/x/text](https://github.com/golang/text) | `0.21.0` | `0.22.0` |



Updates `cloud.google.com/go/pubsub` from 1.45.3 to 1.47.0
- [Release notes](https://github.com/googleapis/google-cloud-go/releases)
- [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-cloud-go/compare/pubsub/v1.45.3...pubsub/v1.47.0)

Updates `github.com/DataDog/datadog-api-client-go/v2` from 2.34.0 to 2.35.0
- [Release notes](https://github.com/DataDog/datadog-api-client-go/releases)
- [Changelog](https://github.com/DataDog/datadog-api-client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DataDog/datadog-api-client-go/compare/v2.34.0...v2.35.0)

Updates `github.com/fluxcd/pkg/ssa` from 0.44.0 to 0.45.0
- [Commits](https://github.com/fluxcd/pkg/compare/oci/v0.44.0...oci/v0.45.0)

Updates `github.com/google/cel-go` from 0.23.1 to 0.23.2
- [Release notes](https://github.com/google/cel-go/releases)
- [Commits](https://github.com/google/cel-go/compare/v0.23.1...v0.23.2)

Updates `github.com/nats-io/nats.go` from 1.38.0 to 1.39.0
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.38.0...v1.39.0)

Updates `gitlab.com/gitlab-org/api/client-go` from 0.121.0 to 0.122.0
- [Release notes](https://gitlab.com/gitlab-org/api/client-go/tags)
- [Commits](https://gitlab.com/gitlab-org/api/client-go/compare/v0.121.0...v0.122.0)

Updates `golang.org/x/oauth2` from 0.25.0 to 0.26.0
- [Commits](https://github.com/golang/oauth2/compare/v0.25.0...v0.26.0)

Updates `golang.org/x/text` from 0.21.0 to 0.22.0
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.21.0...v0.22.0)

Updates `google.golang.org/api` from 0.211.0 to 0.218.0
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.211.0...v0.218.0)

---
updated-dependencies:
- dependency-name: cloud.google.com/go/pubsub
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/DataDog/datadog-api-client-go/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/fluxcd/pkg/ssa
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/google/cel-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/nats-io/nats.go
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: gitlab.com/gitlab-org/api/client-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-11 08:41:55 +00:00
Stefan Prodan 2eb3c35ec3
Merge pull request #948 from bigkevmcd/cel-resource-filtering
Implement Receiver resource filtering with CEL
2025-02-11 10:39:28 +02:00
Kevin McDermott 28deef923f
Implement Receiver resource filtering with CEL
Signed-off-by: Kevin McDermott <bigkevmcd@gmail.com>
Co-authored-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-02-10 16:21:50 +00:00
Stefan Prodan 9b83efa21f
Merge pull request #1032 from fluxcd/dependabot/github_actions/ci-05f176d660
build(deps): bump the ci group across 1 directory with 3 updates
2025-02-09 11:42:55 +02:00
dependabot[bot] e68bc3b7e3
build(deps): bump the ci group across 1 directory with 3 updates
Bumps the ci group with 3 updates in the / directory: [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action), [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) and [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `docker/setup-qemu-action` from 3.3.0 to 3.4.0
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](53851d1459...4574d27a47)

Updates `docker/setup-buildx-action` from 3.8.0 to 3.9.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](6524bf65af...f7ce87c1d6)

Updates `sigstore/cosign-installer` from 3.7.0 to 3.8.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](dc72c7d5c4...c56c2d3e59)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-07 07:08:21 +00:00
Stefan Prodan f4001109db
Merge pull request #1027 from fluxcd/up-deps-api
Update API dependencies
2025-02-01 11:04:19 +02:00
Stefan Prodan ed7f6adac6
Update API dependencies
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2025-02-01 10:47:32 +02:00
Stefan Prodan dcbf4a7f73
Merge pull request #1025 from fluxcd/dependabot/github_actions/ci-fbaebe1433
build(deps): bump the ci group across 1 directory with 12 updates
2025-02-01 10:17:31 +02:00
dependabot[bot] b7cef8af24
build(deps): bump the ci group across 1 directory with 12 updates
Bumps the ci group with 12 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `4.2.0` | `4.2.2` |
| [actions/setup-go](https://github.com/actions/setup-go) | `5.0.2` | `5.3.0` |
| [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `3.2.0` | `3.3.0` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3.6.1` | `3.8.0` |
| [actions/cache](https://github.com/actions/cache) | `4.0.2` | `4.2.0` |
| [helm/kind-action](https://github.com/helm/kind-action) | `1.10.0` | `1.12.0` |
| [docker/metadata-action](https://github.com/docker/metadata-action) | `5.5.1` | `5.6.1` |
| [docker/build-push-action](https://github.com/docker/build-push-action) | `6.7.0` | `6.13.0` |
| [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) | `3.6.0` | `3.7.0` |
| [anchore/sbom-action](https://github.com/anchore/sbom-action) | `0.17.2` | `0.18.0` |
| [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) | `6.0.0` | `6.1.0` |
| [github/codeql-action](https://github.com/github/codeql-action) | `3.26.9` | `3.28.8` |



Updates `actions/checkout` from 4.2.0 to 4.2.2
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](d632683dd7...11bd71901b)

Updates `actions/setup-go` from 5.0.2 to 5.3.0
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](0a12ed9d6a...f111f3307d)

Updates `docker/setup-qemu-action` from 3.2.0 to 3.3.0
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](49b3bc8e6b...53851d1459)

Updates `docker/setup-buildx-action` from 3.6.1 to 3.8.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](988b5a0280...6524bf65af)

Updates `actions/cache` from 4.0.2 to 4.2.0
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](0c45773b62...1bd1e32a3b)

Updates `helm/kind-action` from 1.10.0 to 1.12.0
- [Release notes](https://github.com/helm/kind-action/releases)
- [Commits](0025e74a8c...a1b0e39133)

Updates `docker/metadata-action` from 5.5.1 to 5.6.1
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](8e5442c4ef...369eb591f4)

Updates `docker/build-push-action` from 6.7.0 to 6.13.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](5cd11c3a4c...ca877d9245)

Updates `sigstore/cosign-installer` from 3.6.0 to 3.7.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](4959ce089c...dc72c7d5c4)

Updates `anchore/sbom-action` from 0.17.2 to 0.18.0
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](61119d458a...f325610c9f)

Updates `goreleaser/goreleaser-action` from 6.0.0 to 6.1.0
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](286f3b13b1...9ed2f89a66)

Updates `github/codeql-action` from 3.26.9 to 3.28.8
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](461ef6c76d...dd746615b3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: helm/kind-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: goreleaser/goreleaser-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-01 07:49:38 +00:00
Stefan Prodan 1aea3c2275
Merge pull request #1023 from fluxcd/upgrade-deps
Update dependencies
2025-02-01 09:19:04 +02:00
Matheus Pimenta 7b8535bce0
Update dependencies
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-01-31 17:43:49 +00:00
Matheus Pimenta d9bb201c36
Merge pull request #1010 from mo-rieger/mrieger/1009
fix: adding of duplicate commit statuses in gitlab
2025-01-31 17:23:33 +00:00
Moritz Rieger 764123c6d3 fix: adding of duplicate commit statuses in gitlab
RESOLVES #1009

Signed-off-by: Moritz Rieger <moritz.rieger@exaring.de>
2025-01-31 09:00:27 +01:00
Matheus Pimenta 7ee7239ff3
Merge pull request #1022 from fluxcd/receiver
Enforce namespace check on receiver
2025-01-30 10:41:17 +00:00
Matheus Pimenta b362a258fe
Enforce namespace check on receiver
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-01-30 10:27:01 +00:00
Matheus Pimenta 8235026aa1
Merge pull request #1021 from d4rkfella/main
Add support for Bearer Token authentication to Provider `alertmanager`
2025-01-26 22:02:09 +00:00
Georgi Panov ecc3395615 Add support for Bearer Token authentication to Provider alertmanager
Signed-off-by: Georgi Panov <77702912+d4rkfella@users.noreply.github.com>
Signed-off-by: Darkfella91 <darkfella91@gmail.com>

Update alertmanager_test.go

Signed-off-by: Georgi Panov <77702912+d4rkfella@users.noreply.github.com>
Signed-off-by: Darkfella91 <darkfella91@gmail.com>

Update alertmanager_fuzz_test.go

Signed-off-by: Georgi Panov <77702912+d4rkfella@users.noreply.github.com>
Signed-off-by: Darkfella91 <darkfella91@gmail.com>

Update factory.go

Signed-off-by: Georgi Panov <77702912+d4rkfella@users.noreply.github.com>
Signed-off-by: Darkfella91 <darkfella91@gmail.com>

Update factory.go

Signed-off-by: Darkfella91 <darkfella91@gmail.com>

Fix a mistake with the last commit to update the docs

Signed-off-by: Darkfella91 <darkfella91@gmail.com>

Fix another formatting issue

Signed-off-by: Darkfella91 <darkfella91@gmail.com>

Screwed up my previous commit so implementing the suggested changes again and fixed formatting for the structs

Signed-off-by: Darkfella91 <darkfella91@gmail.com>

Tried to use better wording, to outline that authentication is optional

Signed-off-by: Darkfella91 <darkfella91@gmail.com>

Another small change to the explanation for bearer token authentication

Signed-off-by: Darkfella91 <darkfella91@gmail.com>

Fix incorrect article usage and the configured address example as suggested

Signed-off-by: Darkfella91 <darkfella91@gmail.com>
2025-01-26 23:43:03 +02:00
Matheus Pimenta fa7d9f260c
Merge pull request #1019 from fluxcd/origin-revision
Add subsection for Git providers supporting commit status updates
2025-01-23 11:22:08 +00:00
Matheus Pimenta 9dc18128c8
Add subsection for Git providers supporting commit status updates
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-01-23 10:33:56 +00:00
Matheus Pimenta a2eb8ea3be
Merge pull request #1018 from fluxcd/origin-revision
Add support for MetaOriginRevisionKey from the Event API
2025-01-21 08:53:15 +00:00
Matheus Pimenta e0b98ca519
Add support for MetaOriginRevisionKey from the Event API
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-01-21 08:28:31 +00:00
Matheus Pimenta 5469e2a1f0
Merge pull request #1017 from vflaux/teams_adaptive_cards_full_width
msteams notifier: adaptive cards full width
2025-01-15 11:06:32 +00:00
Valentin Flaux 56c5a5a4bc
msteams notifier: adaptive cards full width
Configure the adaptive card to expand and make full use of extra canvas
space in teams.

Signed-off-by: Valentin Flaux <38909103+vflaux@users.noreply.github.com>
2025-01-13 16:50:46 +01:00
Matheus Pimenta d455ac69fe
Merge pull request #1014 from fluxcd/rfc-0008
[RFC-0008] Custom Event Metadata from Annotations
2025-01-10 14:16:47 +00:00
Matheus Pimenta 939a16620f
[RFC-0008] Custom Event Metadata from Annotations
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2025-01-10 13:19:15 +00:00
Stefan Prodan 51db46dfee
Merge pull request #1016 from erikgb/gitlab-client-migration
Migrate to `gitlab.com/gitlab-org/api/client-go`
2025-01-09 11:21:50 +02:00
Erik Godding Boye f3438f7709
Migrate to gitlab.com/gitlab-org/api/client-go
Signed-off-by: Erik Godding Boye <egboye@gmail.com>
2025-01-03 13:36:13 +01:00
Stefan Prodan 8b1d9a1e0b
Merge pull request #1002 from fluxcd/k8s-1.32
Update dependencies to Kubernetes 1.32.0 and Go 1.23.0
2024-12-12 18:05:33 +02:00
Stefan Prodan a27f00191a
Update dependencies to Kubernetes 1.32.0 and Go 1.23.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-12-12 16:44:59 +02:00
Stefan Prodan 0667ba6629
Merge pull request #997 from hasithsen/main
Remove deprecated object metrics
2024-12-11 23:46:13 +02:00
hasithsen fb2adadc43 feat: Remove deprecated object metrics from controllers fluxcd/flux2#5083
Signed-off-by: hasithsen <sen.hasith@gmail.com>
2024-12-12 00:30:23 +05:30
Matheus Pimenta 276511a10a
Merge pull request #991 from fluxcd/matheuscscp-coremaintainer
Add @matheuscscp to core maintainers (remove from maintainers)
2024-12-05 12:18:17 +00:00
Matheus Pimenta effda518f4 Add @matheuscscp to core maintainers (remove from maintainers)
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2024-12-03 12:33:13 +00:00
Matheus Pimenta 632437c78e
Merge pull request #989 from fluxcd/matheuscscp-affiliation
Update matheuscscp affiliation
2024-11-27 18:10:53 +00:00
Matheus Pimenta e7a4503e51 Update matheuscscp affiliation
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2024-11-27 16:47:43 +00:00
Matheus Pimenta 2ebbf4803a
Merge pull request #937 from fluxcd/add-release-label
Add 1.4.x release label
2024-09-27 14:56:34 -03:00
Matheus Pimenta b6bdd3c2ce Add 1.4.x release label
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2024-09-27 14:41:37 -03:00
Matheus Pimenta 278fd67d9a
Merge pull request #938 from fluxcd/release/v1.4.x
Merge `release/v1.4.x` back to `main`
2024-09-27 14:40:45 -03:00
Matheus Pimenta 2525f2ce4e
Merge pull request #935 from fluxcd/release-v1.4.0
Release v1.4.0
2024-09-27 12:33:01 -03:00
Matheus Pimenta 52a4049be2 Release v1.4.0
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2024-09-27 15:34:18 +01:00
Matheus Pimenta 6fcfb6337c Add changelog entry for v1.4.0
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2024-09-27 11:27:23 -03:00
Stefan Prodan c43e6a93a6
Merge pull request #934 from fluxcd/go-github-v64
Update go-github to v63
2024-09-26 15:42:10 +03:00
Stefan Prodan b2ab2c2b07
Update go-github to v63
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-09-26 15:05:47 +03:00
Stefan Prodan 3acbe68075
Merge pull request #933 from fluxcd/dependabot/github_actions/ci-74c3fc3a14
build(deps): bump the ci group across 1 directory with 2 updates
2024-09-26 13:06:17 +03:00
dependabot[bot] 4997635afa
build(deps): bump the ci group across 1 directory with 2 updates
Bumps the ci group with 2 updates in the / directory: [actions/checkout](https://github.com/actions/checkout) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `actions/checkout` from 4.1.7 to 4.2.0
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](692973e3d9...d632683dd7)

Updates `github/codeql-action` from 3.26.4 to 3.26.9
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](f0f3afee80...461ef6c76d)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-26 08:14:56 +00:00
Stefan Prodan b4a9933f59
Merge pull request #932 from fluxcd/dependabot/go_modules/go-deps-d2f960fbdc
build(deps): bump the go-deps group across 1 directory with 7 updates
2024-09-26 11:02:04 +03:00
Stefan Prodan 519248ff29
Bump Go to 1.23.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-09-26 10:40:55 +03:00
Stefan Prodan 05be0bd5a1
Fix CDEvents example
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-09-26 10:40:37 +03:00
Sunny 3585b77c40 Fix CDEvents API usage and tests
Signed-off-by: Sunny <github@darkowlzz.space>
2024-09-25 23:31:05 +00:00
dependabot[bot] edb88c62fb
build(deps): bump the go-deps group across 1 directory with 7 updates
Bumps the go-deps group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [cloud.google.com/go/pubsub](https://github.com/googleapis/google-cloud-go) | `1.41.0` | `1.43.0` |
| [github.com/DataDog/datadog-api-client-go/v2](https://github.com/DataDog/datadog-api-client-go) | `2.29.0` | `2.30.0` |
| [github.com/cdevents/sdk-go](https://github.com/cdevents/sdk-go) | `0.3.2` | `0.4.1` |
| [github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go) | `0.28.1` | `0.29.0` |
| [github.com/slok/go-http-metrics](https://github.com/slok/go-http-metrics) | `0.12.0` | `0.13.0` |
| [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab) | `0.107.0` | `0.109.0` |



Updates `cloud.google.com/go/pubsub` from 1.41.0 to 1.43.0
- [Release notes](https://github.com/googleapis/google-cloud-go/releases)
- [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-cloud-go/compare/pubsub/v1.41.0...pubsub/v1.43.0)

Updates `github.com/DataDog/datadog-api-client-go/v2` from 2.29.0 to 2.30.0
- [Release notes](https://github.com/DataDog/datadog-api-client-go/releases)
- [Changelog](https://github.com/DataDog/datadog-api-client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DataDog/datadog-api-client-go/compare/v2.29.0...v2.30.0)

Updates `github.com/cdevents/sdk-go` from 0.3.2 to 0.4.1
- [Release notes](https://github.com/cdevents/sdk-go/releases)
- [Changelog](https://github.com/cdevents/sdk-go/blob/main/.goreleaser.yaml)
- [Commits](https://github.com/cdevents/sdk-go/compare/v0.3.2...v0.4.1)

Updates `github.com/getsentry/sentry-go` from 0.28.1 to 0.29.0
- [Release notes](https://github.com/getsentry/sentry-go/releases)
- [Changelog](https://github.com/getsentry/sentry-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-go/compare/v0.28.1...v0.29.0)

Updates `github.com/slok/go-http-metrics` from 0.12.0 to 0.13.0
- [Release notes](https://github.com/slok/go-http-metrics/releases)
- [Changelog](https://github.com/slok/go-http-metrics/blob/master/CHANGELOG.md)
- [Commits](https://github.com/slok/go-http-metrics/compare/v0.12.0...v0.13.0)

Updates `github.com/xanzy/go-gitlab` from 0.107.0 to 0.109.0
- [Release notes](https://github.com/xanzy/go-gitlab/releases)
- [Changelog](https://github.com/xanzy/go-gitlab/blob/main/releases_test.go)
- [Commits](https://github.com/xanzy/go-gitlab/compare/v0.107.0...v0.109.0)

Updates `google.golang.org/api` from 0.192.0 to 0.196.0
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.192.0...v0.196.0)

---
updated-dependencies:
- dependency-name: cloud.google.com/go/pubsub
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/DataDog/datadog-api-client-go/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/cdevents/sdk-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/getsentry/sentry-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/slok/go-http-metrics
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/xanzy/go-gitlab
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-25 16:44:30 +00:00
Stefan Prodan 7d279b98f5
Merge pull request #931 from fluxcd/deps-update
Update fluxcd/pkg deps and k8s deps to 1.31.1
2024-09-25 19:42:21 +03:00
Sunny 7407570bee Update fluxcd/pkg and k8s deps to 1.31.1
Signed-off-by: Sunny <github@darkowlzz.space>
2024-09-25 14:54:23 +00:00
Stefan Prodan 46813c05b9
Merge pull request #925 from fluxcd/controller-gen-v0.16.1
Update controller-gen to v0.16.1
2024-09-13 12:50:45 +03:00
Stefan Prodan 7c15798aaa
Update controller-gen to v0.16.1
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-09-13 10:39:03 +03:00
Matheus Pimenta 205cd17fb0
Merge pull request #920 from fluxcd/ms-adaptive-card-provider
Add MS Adaptive Card payload to `msteams` Provider
2024-09-12 11:16:18 -03:00
Matheus Pimenta e0cf7a1fc7 Add MS Adaptive Card payload to `msteams` Provider
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2024-09-12 11:00:51 -03:00
Stefan Prodan b81755d3f3
Merge pull request #841 from Kuzbekov/main
New flag to disable detailed metrics for path
2024-08-26 11:37:13 +03:00
Alexey Kuzbekov c85b1eb391
Change default behavior and naming
Signed-off-by: Alexey Kuzbekov <alexey@kuzbekov.me>
2024-08-24 15:29:29 +01:00
Alexey Kuzbekov ab58c812bd
New flag to disable detailed metrics for path
Flag detailed-metrics added to provide a way to disable exposing all accessed paths to the metrics and  prevent potential metrics cardinality explosion

Signed-off-by: Alexey Kuzbekov <alexey@kuzbekov.me>
2024-08-24 15:29:24 +01:00
Stefan Prodan 0871ad710a
Merge pull request #912 from fluxcd/dependabot/github_actions/ci-4516fd8e81
build(deps): bump the ci group across 1 directory with 3 updates
2024-08-22 13:02:56 +03:00
dependabot[bot] 42c2c79d2b
build(deps): bump the ci group across 1 directory with 3 updates
Bumps the ci group with 3 updates in the / directory: [korthout/backport-action](https://github.com/korthout/backport-action), [anchore/sbom-action](https://github.com/anchore/sbom-action) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `korthout/backport-action` from 3.0.2 to 3.1.0
- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](bd410d37cd...be567af183)

Updates `anchore/sbom-action` from 0.17.1 to 0.17.2
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](ab9d16d4b4...61119d458a)

Updates `github/codeql-action` from 3.26.2 to 3.26.4
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](429e197704...f0f3afee80)

---
updated-dependencies:
- dependency-name: korthout/backport-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-22 07:45:28 +00:00
Stefan Prodan 117bc7a91d
Merge pull request #903 from fluxcd/dependabot/github_actions/ci-3bac6ad11c
build(deps): bump the ci group across 1 directory with 8 updates
2024-08-15 16:36:07 +03:00
dependabot[bot] e6c53a0ae2
build(deps): bump the ci group across 1 directory with 8 updates
Bumps the ci group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/setup-go](https://github.com/actions/setup-go) | `5.0.1` | `5.0.2` |
| [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `3.0.0` | `3.2.0` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3.3.0` | `3.6.1` |
| [docker/login-action](https://github.com/docker/login-action) | `3.2.0` | `3.3.0` |
| [docker/build-push-action](https://github.com/docker/build-push-action) | `6.2.0` | `6.7.0` |
| [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) | `3.5.0` | `3.6.0` |
| [anchore/sbom-action](https://github.com/anchore/sbom-action) | `0.16.0` | `0.17.1` |
| [github/codeql-action](https://github.com/github/codeql-action) | `3.25.11` | `3.26.2` |



Updates `actions/setup-go` from 5.0.1 to 5.0.2
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](cdcb360436...0a12ed9d6a)

Updates `docker/setup-qemu-action` from 3.0.0 to 3.2.0
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](68827325e0...49b3bc8e6b)

Updates `docker/setup-buildx-action` from 3.3.0 to 3.6.1
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](d70bba72b1...988b5a0280)

Updates `docker/login-action` from 3.2.0 to 3.3.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](0d4c9c5ea7...9780b0c442)

Updates `docker/build-push-action` from 6.2.0 to 6.7.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](15560696de...5cd11c3a4c)

Updates `sigstore/cosign-installer` from 3.5.0 to 3.6.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](59acb6260d...4959ce089c)

Updates `anchore/sbom-action` from 0.16.0 to 0.17.1
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](e8d2a6937e...ab9d16d4b4)

Updates `github/codeql-action` from 3.25.11 to 3.26.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](b611370bb5...429e197704)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-15 13:02:48 +00:00
Stefan Prodan 478718ee48
Merge pull request #907 from fluxcd/go-1.23
Build with Go 1.23
2024-08-15 16:00:53 +03:00
Matheus Pimenta 7373cf4b62 Build with Go 1.23
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2024-08-15 09:36:36 -03:00
Matheus Pimenta d20a810652
Merge pull request #905 from fluxcd/upgrade-deps
Update dependencies to Kubernetes v1.31.0
2024-08-15 09:28:21 -03:00
Matheus Pimenta bd12728d0f Upgrade dependencies
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2024-08-15 09:03:03 -03:00
Max Jonas Werner 4e01193860
Merge pull request #894 from fluxcd/fix-telegram-test
Fix telegram test flake
2024-08-01 22:13:37 +02:00
Max Jonas Werner f9610afa8d
Fix telegram test flake
The test would sometimes fail because the metadata lines are built
from a map and map iteration order in Go is non-deterministic.
Therefore, the lines may be ordered differently between different test
runs.

Now, the test sorts the metadata lines of the telegram message so they
are always the same and only then verifies the expected output.

closes #867

Signed-off-by: Max Jonas Werner <max.werner@associmates.eu>
2024-08-01 15:50:58 +02:00
Stefan Prodan fa93b71722
Merge pull request #879 from octo/fix-conditions-usage
Fix incorrect use of format strings with the `conditions` package.
2024-07-12 10:51:45 +03:00
Florian Forster 1f4cdff23c
Fix incorrect use of format strings with the `conditions` package.
The `Mark…` functions in the `conditions` package accept a format string and
(optional) arguments, just like `fmt.Printf` and friends.

In many places, the code passed an error message as the format string, causing
it to be interpreted as a format string by the `fmt` package. This leads to
issues when the message contains percent signs, e.g. URL-encoded values.

This PR adds a format string and shortens `err.Error()` to `err`, which yields
the same output.

This change is identical in principle to fluxcd/source-controller#1529.

Signed-off-by: Florian Forster <fforster@gitlab.com>
2024-07-12 09:18:59 +02:00
Stefan Prodan 86f2a6d20f
Merge pull request #873 from ThomasDangleterre/stringdata-pat-github
docs: use `stringData` for secret of GitHub PAT
2024-07-09 12:15:13 +03:00
Thomas DANGLETERRE fd2df2cffe chore: set stringData for secret of github PAT in githubdispatch provider doc
Signed-off-by: Thomas DANGLETERRE <thomas.dangleterre@decathlon.com>
2024-07-09 10:42:28 +02:00
Stefan Prodan 48675f2426
Merge pull request #870 from matheuscscp/matheuscscp-maintainer
Add matheuscscp as maintainer
2024-07-05 09:30:31 +03:00
Matheus Pimenta 86b33d0f3c Add matheuscscp as maintainer
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2024-07-03 15:35:51 +01:00
Max Jonas Werner d9216e5c58
Merge pull request #866 from fluxcd/dependabot/github_actions/ci-6034f0241a
build(deps): bump github/codeql-action from 3.25.10 to 3.25.11 in the ci group
2024-07-01 09:28:09 +01:00
dependabot[bot] 84b8c037e9
build(deps): bump github/codeql-action in the ci group
Bumps the ci group with 1 update: [github/codeql-action](https://github.com/github/codeql-action).


Updates `github/codeql-action` from 3.25.10 to 3.25.11
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](23acc5c183...b611370bb5)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 07:35:48 +00:00
souleb 39f345231f
Merge pull request #865 from fluxcd/dependabot/github_actions/ci-cb991c8081
build(deps): bump docker/build-push-action from 6.0.1 to 6.2.0 in the ci group across 1 directory
2024-06-27 15:31:28 +02:00
dependabot[bot] 9c4d43f32a
build(deps): bump docker/build-push-action
Bumps the ci group with 1 update in the / directory: [docker/build-push-action](https://github.com/docker/build-push-action).


Updates `docker/build-push-action` from 6.0.1 to 6.2.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](94f8f8c2ee...15560696de)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-27 08:01:32 +00:00
Max Jonas Werner a1cf5e0d43
Merge pull request #829 from hs1o/patch-1
telegram notifier should escape with metadata key
2024-06-25 10:29:49 +01:00
Max Jonas Werner e70166d5e3
Add test for telegram notifier
This test will make sure we're properly escaping the message and
constructing the URL correctly.

Signed-off-by: Max Jonas Werner <max.werner@associmates.eu>
2024-06-25 10:16:08 +02:00
hohohong 0f8ff3c0d8
telegram notifier should escape with metadata key
Signed-off-by: hohohong <github@m.hs1o.dev>
2024-06-25 10:16:08 +02:00
Max Jonas Werner b6037078a3
Merge pull request #857 from fluxcd/dependabot/go_modules/go-deps-278891ca24
build(deps): bump google.golang.org/api from 0.184.0 to 0.185.0 in the go-deps group
2024-06-21 18:04:06 +01:00
dependabot[bot] 5572c7fa04
build(deps): bump google.golang.org/api in the go-deps group
Bumps the go-deps group with 1 update: [google.golang.org/api](https://github.com/googleapis/google-api-go-client).


Updates `google.golang.org/api` from 0.184.0 to 0.185.0
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.184.0...v0.185.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-21 07:25:12 +00:00
Max Jonas Werner ef7db0026b
Merge pull request #854 from fluxcd/dependabot/go_modules/go-deps-129d757b84
build(deps): bump the go-deps group across 1 directory with 10 updates
2024-06-20 18:39:34 +01:00
dependabot[bot] 7adf4f2c41
build(deps): bump the go-deps group across 1 directory with 10 updates
Bumps the go-deps group with 7 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [cloud.google.com/go/pubsub](https://github.com/googleapis/google-cloud-go) | `1.37.0` | `1.39.0` |
| [github.com/DataDog/datadog-api-client-go/v2](https://github.com/DataDog/datadog-api-client-go) | `2.25.0` | `2.26.0` |
| [github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go) | `0.27.0` | `0.28.1` |
| [github.com/hashicorp/go-retryablehttp](https://github.com/hashicorp/go-retryablehttp) | `0.7.5` | `0.7.7` |
| [github.com/ktrysmt/go-bitbucket](https://github.com/ktrysmt/go-bitbucket) | `0.9.79` | `0.9.80` |
| [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) | `1.34.1` | `1.36.0` |
| [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab) | `0.104.0` | `0.105.0` |



Updates `cloud.google.com/go/pubsub` from 1.37.0 to 1.39.0
- [Release notes](https://github.com/googleapis/google-cloud-go/releases)
- [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-cloud-go/compare/pubsub/v1.37.0...pubsub/v1.39.0)

Updates `github.com/DataDog/datadog-api-client-go/v2` from 2.25.0 to 2.26.0
- [Release notes](https://github.com/DataDog/datadog-api-client-go/releases)
- [Changelog](https://github.com/DataDog/datadog-api-client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DataDog/datadog-api-client-go/compare/v2.25.0...v2.26.0)

Updates `github.com/getsentry/sentry-go` from 0.27.0 to 0.28.1
- [Release notes](https://github.com/getsentry/sentry-go/releases)
- [Changelog](https://github.com/getsentry/sentry-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-go/compare/v0.27.0...v0.28.1)

Updates `github.com/hashicorp/go-retryablehttp` from 0.7.5 to 0.7.7
- [Changelog](https://github.com/hashicorp/go-retryablehttp/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/go-retryablehttp/compare/v0.7.5...v0.7.7)

Updates `github.com/ktrysmt/go-bitbucket` from 0.9.79 to 0.9.80
- [Release notes](https://github.com/ktrysmt/go-bitbucket/releases)
- [Commits](https://github.com/ktrysmt/go-bitbucket/compare/v0.9.79...v0.9.80)

Updates `github.com/nats-io/nats.go` from 1.34.1 to 1.36.0
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.34.1...v1.36.0)

Updates `github.com/xanzy/go-gitlab` from 0.104.0 to 0.105.0
- [Changelog](https://github.com/xanzy/go-gitlab/blob/main/releases_test.go)
- [Commits](https://github.com/xanzy/go-gitlab/compare/v0.104.0...v0.105.0)

Updates `golang.org/x/oauth2` from 0.20.0 to 0.21.0
- [Commits](https://github.com/golang/oauth2/compare/v0.20.0...v0.21.0)

Updates `golang.org/x/text` from 0.15.0 to 0.16.0
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.15.0...v0.16.0)

Updates `google.golang.org/api` from 0.177.0 to 0.184.0
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.177.0...v0.184.0)

---
updated-dependencies:
- dependency-name: cloud.google.com/go/pubsub
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/DataDog/datadog-api-client-go/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/getsentry/sentry-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/hashicorp/go-retryablehttp
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/ktrysmt/go-bitbucket
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/nats-io/nats.go
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/xanzy/go-gitlab
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-20 17:20:49 +00:00
Max Jonas Werner c518265dae
Merge pull request #855 from fluxcd/dependabot/github_actions/ci-f2c4839187
build(deps): bump the ci group across 1 directory with 3 updates
2024-06-20 18:16:17 +01:00
dependabot[bot] 6240b16776
build(deps): bump the ci group across 1 directory with 3 updates
Bumps the ci group with 3 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [docker/build-push-action](https://github.com/docker/build-push-action) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `actions/checkout` from 4.1.6 to 4.1.7
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](a5ac7e51b4...692973e3d9)

Updates `docker/build-push-action` from 5.3.0 to 6.0.1
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](2cdde995de...94f8f8c2ee)

Updates `github/codeql-action` from 3.25.8 to 3.25.10
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](2e230e8fe0...23acc5c183)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-19 08:04:32 +00:00
Stefan Prodan 3ae80f6475
Merge pull request #845 from fluxcd/dependabot/github_actions/ci-8595c0ecb0
build(deps): bump the ci group across 1 directory with 6 updates
2024-06-11 09:47:08 +03:00
Stefan Prodan 219f86fd11
Adapt config to GoRelease v2
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-06-11 09:33:07 +03:00
dependabot[bot] 129f60e6e6
build(deps): bump the ci group across 1 directory with 6 updates
Bumps the ci group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `4.1.4` | `4.1.6` |
| [korthout/backport-action](https://github.com/korthout/backport-action) | `2.5.0` | `3.0.2` |
| [docker/login-action](https://github.com/docker/login-action) | `3.1.0` | `3.2.0` |
| [anchore/sbom-action](https://github.com/anchore/sbom-action) | `0.15.11` | `0.16.0` |
| [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) | `5.0.0` | `6.0.0` |
| [github/codeql-action](https://github.com/github/codeql-action) | `2.13.4` | `3.25.8` |



Updates `actions/checkout` from 4.1.4 to 4.1.6
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](0ad4b8fada...a5ac7e51b4)

Updates `korthout/backport-action` from 2.5.0 to 3.0.2
- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](ef20d86abc...bd410d37cd)

Updates `docker/login-action` from 3.1.0 to 3.2.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](e92390c5fb...0d4c9c5ea7)

Updates `anchore/sbom-action` from 0.15.11 to 0.16.0
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](7ccf588e3c...e8d2a6937e)

Updates `goreleaser/goreleaser-action` from 5.0.0 to 6.0.0
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](7ec5c2b0c6...286f3b13b1)

Updates `github/codeql-action` from 2.13.4 to 3.25.8
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](cdcdbb5797...2e230e8fe0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: korthout/backport-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: goreleaser/goreleaser-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 07:35:41 +00:00
Stefan Prodan 580497beeb
Merge pull request #823 from matheuscscp/new-release-label
Add 1.3.x release label
2024-05-08 17:07:14 +03:00
Matheus Pimenta f4e8df6360 Add 1.3.x release label
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2024-05-08 14:24:32 +01:00
Stefan Prodan eb62655b73
Merge pull request #818 from fluxcd/release/v1.3.x
Housekeeping: merge `release/v1.3.x` back into `main`
2024-05-06 16:11:52 +03:00
Stefan Prodan e0a1f00358
Merge pull request #817 from fluxcd/release-v1.3.0
Release v1.3.0
2024-05-06 14:57:33 +03:00
Stefan Prodan a8f81b3a00
Release v1.3.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-05-06 14:34:36 +03:00
Stefan Prodan 696f065673
Add changelog entry for v1.3.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-05-06 14:34:06 +03:00
Stefan Prodan 1b5dbd997a
Merge pull request #816 from fluxcd/dependabot/go_modules/go-deps-9d3f077bc0
build(deps): bump the go-deps group with 3 updates
2024-05-06 11:29:08 +03:00
dependabot[bot] 5bfdcc04fc
build(deps): bump the go-deps group with 3 updates
Bumps the go-deps group with 3 updates: [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab), [golang.org/x/oauth2](https://github.com/golang/oauth2) and [golang.org/x/text](https://github.com/golang/text).


Updates `github.com/xanzy/go-gitlab` from 0.103.0 to 0.104.0
- [Changelog](https://github.com/xanzy/go-gitlab/blob/main/releases_test.go)
- [Commits](https://github.com/xanzy/go-gitlab/compare/v0.103.0...v0.104.0)

Updates `golang.org/x/oauth2` from 0.19.0 to 0.20.0
- [Commits](https://github.com/golang/oauth2/compare/v0.19.0...v0.20.0)

Updates `golang.org/x/text` from 0.14.0 to 0.15.0
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.14.0...v0.15.0)

---
updated-dependencies:
- dependency-name: github.com/xanzy/go-gitlab
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-06 08:05:11 +00:00
Stefan Prodan 5f0f561ac0
Merge pull request #815 from fluxcd/dependabot/github_actions/ci-b23e0286c6
build(deps): bump actions/setup-go from 5.0.0 to 5.0.1 in the ci group
2024-05-05 09:10:20 +03:00
dependabot[bot] 9a948c7290
build(deps): bump actions/setup-go from 5.0.0 to 5.0.1 in the ci group
Bumps the ci group with 1 update: [actions/setup-go](https://github.com/actions/setup-go).


Updates `actions/setup-go` from 5.0.0 to 5.0.1
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](0c52d547c9...cdcb360436)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-03 07:15:11 +00:00
Stefan Prodan b2c799203d
Merge pull request #814 from fluxcd/update-apis
Update Helm APIs to `source.toolkit.fluxcd.io/v1` (GA)
2024-05-03 00:11:23 +03:00
Stefan Prodan 05abe0a9de
Update runtime dependencies
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-05-02 21:02:29 +03:00
Stefan Prodan 3aba5bbd39
Update Helm APIs to v1
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-05-02 21:00:30 +03:00
Stefan Prodan 35e2a0ebc0
Merge pull request #813 from fluxcd/dependabot/go_modules/go-deps-219a9f80f6
build(deps): bump the go-deps group across 1 directory with 2 updates
2024-05-01 10:38:51 +03:00
dependabot[bot] fd635f7dff
build(deps): bump the go-deps group across 1 directory with 2 updates
Bumps the go-deps group with 2 updates in the / directory: [github.com/onsi/gomega](https://github.com/onsi/gomega) and [google.golang.org/api](https://github.com/googleapis/google-api-go-client).


Updates `github.com/onsi/gomega` from 1.33.0 to 1.33.1
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/gomega/compare/v1.33.0...v1.33.1)

Updates `google.golang.org/api` from 0.176.1 to 0.177.0
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.176.1...v0.177.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-01 07:15:59 +00:00
souleb 838514c874
Merge pull request #811 from fluxcd/dependabot/github_actions/ci-df358fd3c4
build(deps): bump anchore/sbom-action from 0.15.10 to 0.15.11 in the ci group
2024-04-30 22:47:40 +02:00
dependabot[bot] b7b9a018e8
build(deps): bump anchore/sbom-action in the ci group
Bumps the ci group with 1 update: [anchore/sbom-action](https://github.com/anchore/sbom-action).


Updates `anchore/sbom-action` from 0.15.10 to 0.15.11
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](ab5d7b5f48...7ccf588e3c)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-30 07:48:39 +00:00
Stefan Prodan c4835fbdbd
Merge pull request #810 from fluxcd/dependabot/go_modules/go-deps-152f4dbed8
build(deps): bump the go-deps group across 1 directory with 6 updates
2024-04-29 11:01:10 +03:00
dependabot[bot] 3407bf5486
build(deps): bump the go-deps group across 1 directory with 6 updates
Bumps the go-deps group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| code.gitea.io/sdk/gitea | `0.17.1` | `0.18.0` |
| [github.com/DataDog/datadog-api-client-go/v2](https://github.com/DataDog/datadog-api-client-go) | `2.24.0` | `2.25.0` |
| [github.com/ktrysmt/go-bitbucket](https://github.com/ktrysmt/go-bitbucket) | `0.9.77` | `0.9.79` |
| [github.com/onsi/gomega](https://github.com/onsi/gomega) | `1.32.0` | `1.33.0` |
| [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab) | `0.102.0` | `0.103.0` |
| [google.golang.org/api](https://github.com/googleapis/google-api-go-client) | `0.172.0` | `0.176.1` |



Updates `code.gitea.io/sdk/gitea` from 0.17.1 to 0.18.0

Updates `github.com/DataDog/datadog-api-client-go/v2` from 2.24.0 to 2.25.0
- [Release notes](https://github.com/DataDog/datadog-api-client-go/releases)
- [Changelog](https://github.com/DataDog/datadog-api-client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DataDog/datadog-api-client-go/compare/v2.24.0...v2.25.0)

Updates `github.com/ktrysmt/go-bitbucket` from 0.9.77 to 0.9.79
- [Release notes](https://github.com/ktrysmt/go-bitbucket/releases)
- [Commits](https://github.com/ktrysmt/go-bitbucket/compare/v0.9.77...v0.9.79)

Updates `github.com/onsi/gomega` from 1.32.0 to 1.33.0
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/gomega/compare/v1.32.0...v1.33.0)

Updates `github.com/xanzy/go-gitlab` from 0.102.0 to 0.103.0
- [Changelog](https://github.com/xanzy/go-gitlab/blob/main/releases_test.go)
- [Commits](https://github.com/xanzy/go-gitlab/compare/v0.102.0...v0.103.0)

Updates `google.golang.org/api` from 0.172.0 to 0.176.1
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.172.0...v0.176.1)

---
updated-dependencies:
- dependency-name: code.gitea.io/sdk/gitea
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/DataDog/datadog-api-client-go/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/ktrysmt/go-bitbucket
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/xanzy/go-gitlab
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-29 07:44:46 +00:00
Stefan Prodan 6d7913063d
Merge pull request #795 from tdemin/main
Alertmanager: Change timestamp label to .StartsAt
2024-04-29 09:30:55 +03:00
Timur Demin 531c5873e7 Alertmanager: Change timestamp label to .StartsAt
notification-controller posted all outgoing Alertmanager alerts with
"timestamp" label, effectively preventing grouping alerts related to the
same resource and forcing users to configure a separate alert receiver
with `send_resolved: false`.

This changes it to instead set "startsAt", which was previously set
(automatically by Alertmanager) to alert posting time. "endsAt" remains
unset, as we have no way of figuring that out but the reconciliation
interval of the resource that generated the alert, which can currently
only be found out by making a Kubernetes API round-trip.

Note that this requires users to adapt alert templates that relied on
.Labels.Timestamp.

Signed-off-by: Timur Demin <me@tdem.in>
2024-04-27 16:20:12 +05:00
Stefan Prodan cf2f554c11
Merge pull request #809 from fluxcd/kubernetes-1.30
Update dependencies to Kubernetes 1.30
2024-04-26 12:53:54 +03:00
Stefan Prodan d29f5f4919
Update dependencies to Kubernetes 1.30
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-04-26 12:33:21 +03:00
souleb f9c93e2952
Merge pull request #807 from fluxcd/dependabot/github_actions/ci-46f46a1c32
build(deps): bump the ci group across 1 directory with 3 updates
2024-04-25 10:17:34 +02:00
dependabot[bot] f5026a7443
build(deps): bump the ci group across 1 directory with 3 updates
Bumps the ci group with 3 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [helm/kind-action](https://github.com/helm/kind-action) and [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator).


Updates `actions/checkout` from 4.1.2 to 4.1.4
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](9bb56186c3...0ad4b8fada)

Updates `helm/kind-action` from 1.9.0 to 1.10.0
- [Release notes](https://github.com/helm/kind-action/releases)
- [Commits](99576bfa6d...0025e74a8c)

Updates `slsa-framework/slsa-github-generator` from 1.10.0 to 2.0.0
- [Release notes](https://github.com/slsa-framework/slsa-github-generator/releases)
- [Changelog](https://github.com/slsa-framework/slsa-github-generator/blob/main/CHANGELOG.md)
- [Commits](https://github.com/slsa-framework/slsa-github-generator/compare/v1.10.0...v2.0.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: helm/kind-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: slsa-framework/slsa-github-generator
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-25 07:32:57 +00:00
Stefan Prodan 678f374bc3
Merge pull request #747 from gdasson/fix_742
Add support for Bitbucket Context path
2024-04-23 17:16:49 +03:00
Gaurav Dasson 633e33bf4b Add support for Bitbucket Context path - Fix issue #742
Signed-off-by: Gaurav Dasson <gaurav.dasson@gmail.com>
2024-04-20 23:56:03 -05:00
souleb f22dd2bfff
Merge pull request #796 from al-lac/opsgenie-add-severity
Add severity to opsgenie alerts
2024-04-19 15:32:17 +02:00
al-lac 94ce6da0f2 Add severity to opsgenie Details payload
Co-authored-by: souleb <bah.soule@gmail.com>
Signed-off-by: al-lac <lackner.alex@gmail.com>
2024-04-19 14:36:35 +02:00
Stefan Prodan 0bea894c2e
Merge pull request #791 from fluxcd/dependabot/github_actions/ci-fd594e3a59
build(deps): bump the ci group with 2 updates
2024-04-11 12:24:47 +03:00
dependabot[bot] 857c11dd26
build(deps): bump the ci group with 2 updates
Bumps the ci group with 2 updates: [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) and [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `docker/setup-buildx-action` from 3.2.0 to 3.3.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](2b51285047...d70bba72b1)

Updates `sigstore/cosign-installer` from 3.4.0 to 3.5.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](e1523de757...59acb6260d)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-11 07:53:45 +00:00
Stefan Prodan 2bac104a69
Merge pull request #790 from fluxcd/git-token-password
Use `password` as fallback for the Git provider `token` auth
2024-04-10 11:17:13 +03:00
Soule BA e3ae7c2d48
refactor notifier factory
Signed-off-by: Soule BA <bah.soule@gmail.com>
2024-04-09 22:21:11 +02:00
Stefan Prodan 952ccd000f
User the password as fallback for Git provider token auth
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-04-09 18:59:04 +03:00
Stefan Prodan 0106b53e02
Merge pull request #789 from fluxcd/sanitize-provider-data
Sanitize provider data loaded from secret
2024-04-09 18:54:19 +03:00
Stefan Prodan 6ba1a713fe
Sanitize provider data loaded from secret
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-04-09 18:35:01 +03:00
Stefan Prodan c6b89cd2d6
Merge pull request #787 from fluxcd/dependabot/go_modules/go-deps-f80f47cc43
build(deps): bump the go-deps group with 6 updates
2024-04-05 10:50:34 +03:00
dependabot[bot] e30844fe7b
build(deps): bump the go-deps group with 6 updates
Bumps the go-deps group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [github.com/fluxcd/cli-utils](https://github.com/fluxcd/cli-utils) | `0.36.0-flux.4` | `0.36.0-flux.5` |
| [github.com/fluxcd/pkg/runtime](https://github.com/fluxcd/pkg) | `0.45.0` | `0.46.0` |
| [github.com/fluxcd/pkg/ssa](https://github.com/fluxcd/pkg) | `0.37.0` | `0.38.0` |
| [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) | `1.34.0` | `1.34.1` |
| [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab) | `0.101.0` | `0.102.0` |
| [golang.org/x/oauth2](https://github.com/golang/oauth2) | `0.18.0` | `0.19.0` |


Updates `github.com/fluxcd/cli-utils` from 0.36.0-flux.4 to 0.36.0-flux.5
- [Commits](https://github.com/fluxcd/cli-utils/compare/v0.36.0-flux.4...v0.36.0-flux.5)

Updates `github.com/fluxcd/pkg/runtime` from 0.45.0 to 0.46.0
- [Commits](https://github.com/fluxcd/pkg/compare/runtime/v0.45.0...runtime/v0.46.0)

Updates `github.com/fluxcd/pkg/ssa` from 0.37.0 to 0.38.0
- [Commits](https://github.com/fluxcd/pkg/compare/ssa/v0.37.0...ssa/v0.38.0)

Updates `github.com/nats-io/nats.go` from 1.34.0 to 1.34.1
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.34.0...v1.34.1)

Updates `github.com/xanzy/go-gitlab` from 0.101.0 to 0.102.0
- [Changelog](https://github.com/xanzy/go-gitlab/blob/main/releases_test.go)
- [Commits](https://github.com/xanzy/go-gitlab/compare/v0.101.0...v0.102.0)

Updates `golang.org/x/oauth2` from 0.18.0 to 0.19.0
- [Commits](https://github.com/golang/oauth2/compare/v0.18.0...v0.19.0)

---
updated-dependencies:
- dependency-name: github.com/fluxcd/cli-utils
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/fluxcd/pkg/runtime
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/fluxcd/pkg/ssa
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/nats-io/nats.go
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/xanzy/go-gitlab
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-05 07:31:05 +00:00
Stefan Prodan 1fa1e28e33
Merge pull request #783 from fluxcd/dependabot/github_actions/ci-39c307716c
build(deps): bump the ci group with 12 updates
2024-04-02 17:27:38 +03:00
dependabot[bot] cb595180b1
build(deps): bump the ci group with 12 updates
Bumps the ci group with 12 updates:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `4.1.1` | `4.1.2` |
| [korthout/backport-action](https://github.com/korthout/backport-action) | `2.4.1` | `2.5.0` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3.0.0` | `3.2.0` |
| [actions/cache](https://github.com/actions/cache) | `4.0.0` | `4.0.2` |
| [helm/kind-action](https://github.com/helm/kind-action) | `1.8.0` | `1.9.0` |
| [docker/login-action](https://github.com/docker/login-action) | `3.0.0` | `3.1.0` |
| [docker/metadata-action](https://github.com/docker/metadata-action) | `5.5.0` | `5.5.1` |
| [docker/build-push-action](https://github.com/docker/build-push-action) | `5.1.0` | `5.3.0` |
| [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) | `3.3.0` | `3.4.0` |
| [anchore/sbom-action](https://github.com/anchore/sbom-action) | `0.15.7` | `0.15.10` |
| [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator) | `1.9.0` | `1.10.0` |
| [EndBug/label-sync](https://github.com/endbug/label-sync) | `2.3.2` | `2.3.3` |


Updates `actions/checkout` from 4.1.1 to 4.1.2
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](b4ffde65f4...9bb56186c3)

Updates `korthout/backport-action` from 2.4.1 to 2.5.0
- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](e8161d6a0d...ef20d86abc)

Updates `docker/setup-buildx-action` from 3.0.0 to 3.2.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](f95db51fdd...2b51285047)

Updates `actions/cache` from 4.0.0 to 4.0.2
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](13aacd865c...0c45773b62)

Updates `helm/kind-action` from 1.8.0 to 1.9.0
- [Release notes](https://github.com/helm/kind-action/releases)
- [Commits](dda0770415...99576bfa6d)

Updates `docker/login-action` from 3.0.0 to 3.1.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](343f7c4344...e92390c5fb)

Updates `docker/metadata-action` from 5.5.0 to 5.5.1
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](dbef88086f...8e5442c4ef)

Updates `docker/build-push-action` from 5.1.0 to 5.3.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](4a13e500e5...2cdde995de)

Updates `sigstore/cosign-installer` from 3.3.0 to 3.4.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](9614fae9e5...e1523de757)

Updates `anchore/sbom-action` from 0.15.7 to 0.15.10
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](767b08fd88...ab5d7b5f48)

Updates `slsa-framework/slsa-github-generator` from 1.9.0 to 1.10.0
- [Release notes](https://github.com/slsa-framework/slsa-github-generator/releases)
- [Changelog](https://github.com/slsa-framework/slsa-github-generator/blob/main/CHANGELOG.md)
- [Commits](https://github.com/slsa-framework/slsa-github-generator/compare/v1.9.0...v1.10.0)

Updates `EndBug/label-sync` from 2.3.2 to 2.3.3
- [Release notes](https://github.com/endbug/label-sync/releases)
- [Commits](da00f2c11f...5207415819)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: korthout/backport-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: helm/kind-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: slsa-framework/slsa-github-generator
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: EndBug/label-sync
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-02 13:11:57 +00:00
Stefan Prodan 7659221a4a
Merge pull request #785 from fluxcd/go1.22
Update dependencies to Go 1.22 and Kubernetes 1.29.3
2024-04-02 16:10:01 +03:00
Stefan Prodan 08e74d5209
Update dependencies to Go 1.22 and Kubernetes 1.29.3
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-04-02 15:32:20 +03:00
Stefan Prodan 17adf69aeb
Merge pull request #772 from Nordix/cdevents-validation
[RFC-0006] Add CDEvent Receiver Support
2024-03-27 18:26:42 +02:00
adam b4949b6e05 Implement CDEvents Receiver
Signed-off-by: adamkenihan <adam.kenihan@est.tech>

Added CDEvents Receiver

Signed-off-by: adamkenihan <adam.kenihan@est.tech>

Added CDEvent Validation + Tests

Signed-off-by: adamkenihan <adam.kenihan@est.tech>

Small changes to CDEvent Receiver

Signed-off-by: adamkenihan <adam.kenihan@est.tech>

More CDEvents Tests and Docs added

Signed-off-by: adamkenihan <adam.kenihan@est.tech>

Adding imports to go.mod

Signed-off-by: adamkenihan <adam.kenihan@est.tech>

small changes + manifests and formatting

Signed-off-by: adamkenihan <adam.kenihan@est.tech>

Changing string compare to EqualFold

Signed-off-by: adamkenihan <adam.kenihan@est.tech>
2024-03-27 10:36:51 +00:00
Stefan Prodan 20eee15786
Merge pull request #776 from coding4food/734-fix-telegram-markup
Fix Telegram MarkdownV2 escaping
2024-03-25 12:50:08 +02:00
Anatoly Medvedkov bf918b9b3c Fix Telegram MarkdownV2 escaping
Current implementation was missing '*' symbol.

Signed-off-by: Anatoly Medvedkov <32126+coding4food@users.noreply.github.com>
2024-03-21 13:41:04 +03:00
souleb 440aad84b0
Merge pull request #763 from fluxcd/update-controllergen-0.14
Update controller-gen to v0.14.0
2024-03-12 16:10:37 +01:00
Soule BA c2302f8fed
Update controller-gen to v0.14.0
Also update to use GOBIN if it exist

Signed-off-by: Soule BA <bah.soule@gmail.com>
2024-03-12 15:01:35 +01:00
Stefan Prodan cd529f5588
Merge pull request #757 from fluxcd/api-docs-provider-timeout
Fix timeout propagation for alerts
2024-03-07 21:08:19 +02:00
Stefan Prodan aef940033c
Fix timout propagation for alerts
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-03-07 16:30:39 +02:00
Stefan Prodan 34a9099884
Add the Provider `.spec.timeout` field to the API docs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-03-07 15:22:25 +02:00
Stefan Prodan e73db32382
Merge pull request #749 from gmolau/main
Remove `genclient:Namespaced` tag
2024-02-29 13:50:20 +00:00
Georg Molau b3e4bf2ad5 Remove `genclient:Namespaced` tag
This tag isn't used by controller-tools, only `nonNamespaced` is.

Context: https://cloud-native.slack.com/archives/CLAJ40HV3/p1708794732147909

Tested by running `make generate` and verifying that there is no diff.

Signed-off-by: Georg Molau [georg.molau@gmail.com](mailto:georg.molau@gmail.com)
Signed-off-by: Georg Molau <georg.molau@gmail.com>
2024-02-27 22:23:51 +01:00
Sunny bd242e091c
Merge pull request #730 from fluxcd/pick-changelog-v1.2.4
Add changelog entry for v1.2.4
2024-02-01 20:01:44 +05:30
Sunny 36a83074f2 Add changelog entry for v1.2.4
Signed-off-by: Sunny <github@darkowlzz.space>
(cherry picked from commit be91fe2beb)
2024-02-01 19:38:49 +05:30
Stefan Prodan eceae7774f
Merge pull request #724 from fluxcd/dependabot/github_actions/ci-bfff10142b
build(deps): bump the ci group with 2 updates
2024-01-31 15:12:49 +02:00
dependabot[bot] edb771fa6c
build(deps): bump the ci group with 2 updates
Bumps the ci group with 2 updates: [korthout/backport-action](https://github.com/korthout/backport-action) and [anchore/sbom-action](https://github.com/anchore/sbom-action).


Updates `korthout/backport-action` from 2.3.0 to 2.4.1
- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](addffea45a...e8161d6a0d)

Updates `anchore/sbom-action` from 0.15.4 to 0.15.7
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](41f7a6c033...767b08fd88)

---
updated-dependencies:
- dependency-name: korthout/backport-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-31 13:05:55 +00:00
Stefan Prodan ee50f74164
Merge pull request #725 from fluxcd/dependabot/go_modules/go-deps-08706ae5bf
build(deps): bump the go-deps group with 2 updates
2024-01-31 14:11:27 +02:00
dependabot[bot] 6dafac748f
build(deps): bump the go-deps group with 2 updates
Bumps the go-deps group with 2 updates: [cloud.google.com/go/pubsub](https://github.com/googleapis/google-cloud-go) and [google.golang.org/api](https://github.com/googleapis/google-api-go-client).


Updates `cloud.google.com/go/pubsub` from 1.36.0 to 1.36.1
- [Release notes](https://github.com/googleapis/google-cloud-go/releases)
- [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-cloud-go/compare/pubsub/v1.36.0...pubsub/v1.36.1)

Updates `google.golang.org/api` from 0.160.0 to 0.161.0
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.160.0...v0.161.0)

---
updated-dependencies:
- dependency-name: cloud.google.com/go/pubsub
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-31 08:05:35 +00:00
Stefan Prodan 333e6c3d07
Merge pull request #722 from fluxcd/fix-bitbucket-panic
Fix BitBucket status update panic
2024-01-30 16:27:22 +02:00
Stefan Prodan 32c59b2474
Fix BitBucket status update panic
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-01-30 15:23:38 +02:00
Stefan Prodan 681ad49b98
Merge pull request #720 from fluxcd/dependabot/go_modules/go-deps-5f4080d6cc
build(deps): bump the go-deps group with 1 update
2024-01-30 13:53:54 +02:00
dependabot[bot] 4e8bb2e4d5
build(deps): bump the go-deps group with 1 update
Bumps the go-deps group with 1 update: [google.golang.org/api](https://github.com/googleapis/google-api-go-client).


Updates `google.golang.org/api` from 0.159.0 to 0.160.0
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.159.0...v0.160.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-30 07:58:21 +00:00
Stefan Prodan 8cedefd341
Merge pull request #717 from fluxcd/dependabot/go_modules/go-deps-3a14492254
Update controller to Kubernetes 1.28.6
2024-01-29 15:54:51 +02:00
Stefan Prodan 5ed66321a9
Update API to Kubernetes v1.28.6
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-01-29 15:39:57 +02:00
dependabot[bot] f325f774d8
build(deps): bump the go-deps group with 16 updates
Bumps the go-deps group with 16 updates:

| Package | From | To |
| --- | --- | --- |
| [cloud.google.com/go/pubsub](https://github.com/googleapis/google-cloud-go) | `1.33.0` | `1.36.0` |
| code.gitea.io/sdk/gitea | `0.17.0` | `0.17.1` |
| [github.com/Azure/azure-event-hubs-go/v3](https://github.com/Azure/azure-event-hubs-go) | `3.6.1` | `3.6.2` |
| [github.com/DataDog/datadog-api-client-go/v2](https://github.com/DataDog/datadog-api-client-go) | `2.19.0` | `2.21.0` |
| [github.com/PagerDuty/go-pagerduty](https://github.com/PagerDuty/go-pagerduty) | `1.7.0` | `1.8.0` |
| [github.com/fluxcd/cli-utils](https://github.com/fluxcd/cli-utils) | `0.36.0-flux.2` | `0.36.0-flux.3` |
| [github.com/fluxcd/pkg/apis/event](https://github.com/fluxcd/pkg) | `0.6.0` | `0.7.0` |
| [github.com/fluxcd/pkg/apis/meta](https://github.com/fluxcd/pkg) | `1.2.0` | `1.3.0` |
| [github.com/fluxcd/pkg/git](https://github.com/fluxcd/pkg) | `0.16.0` | `0.17.0` |
| [github.com/fluxcd/pkg/runtime](https://github.com/fluxcd/pkg) | `0.43.2` | `0.44.0` |
| [github.com/fluxcd/pkg/ssa](https://github.com/fluxcd/pkg) | `0.35.0` | `0.36.0` |
| [github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go) | `0.25.0` | `0.26.0` |
| [github.com/ktrysmt/go-bitbucket](https://github.com/ktrysmt/go-bitbucket) | `0.9.73` | `0.9.74` |
| [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) | `1.31.0` | `1.32.0` |
| [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab) | `0.95.1` | `0.96.0` |
| [google.golang.org/api](https://github.com/googleapis/google-api-go-client) | `0.157.0` | `0.159.0` |


Updates `cloud.google.com/go/pubsub` from 1.33.0 to 1.36.0
- [Release notes](https://github.com/googleapis/google-cloud-go/releases)
- [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-cloud-go/compare/pubsub/v1.33.0...pubsub/v1.36.0)

Updates `code.gitea.io/sdk/gitea` from 0.17.0 to 0.17.1

Updates `github.com/Azure/azure-event-hubs-go/v3` from 3.6.1 to 3.6.2
- [Release notes](https://github.com/Azure/azure-event-hubs-go/releases)
- [Changelog](https://github.com/Azure/azure-event-hubs-go/blob/master/changelog.md)
- [Commits](https://github.com/Azure/azure-event-hubs-go/compare/v3.6.1...v3.6.2)

Updates `github.com/DataDog/datadog-api-client-go/v2` from 2.19.0 to 2.21.0
- [Release notes](https://github.com/DataDog/datadog-api-client-go/releases)
- [Changelog](https://github.com/DataDog/datadog-api-client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DataDog/datadog-api-client-go/compare/v2.19.0...v2.21.0)

Updates `github.com/PagerDuty/go-pagerduty` from 1.7.0 to 1.8.0
- [Release notes](https://github.com/PagerDuty/go-pagerduty/releases)
- [Changelog](https://github.com/PagerDuty/go-pagerduty/blob/main/CHANGELOG.md)
- [Commits](https://github.com/PagerDuty/go-pagerduty/compare/v1.7.0...v1.8.0)

Updates `github.com/fluxcd/cli-utils` from 0.36.0-flux.2 to 0.36.0-flux.3
- [Commits](https://github.com/fluxcd/cli-utils/compare/v0.36.0-flux.2...v0.36.0-flux.3)

Updates `github.com/fluxcd/pkg/apis/event` from 0.6.0 to 0.7.0
- [Commits](https://github.com/fluxcd/pkg/compare/git/v0.6.0...git/v0.7.0)

Updates `github.com/fluxcd/pkg/apis/meta` from 1.2.0 to 1.3.0
- [Commits](https://github.com/fluxcd/pkg/compare/apis/meta/v1.2.0...apis/meta/v1.3.0)

Updates `github.com/fluxcd/pkg/git` from 0.16.0 to 0.17.0
- [Commits](https://github.com/fluxcd/pkg/compare/git/v0.16.0...git/v0.17.0)

Updates `github.com/fluxcd/pkg/runtime` from 0.43.2 to 0.44.0
- [Commits](https://github.com/fluxcd/pkg/compare/runtime/v0.43.2...runtime/v0.44.0)

Updates `github.com/fluxcd/pkg/ssa` from 0.35.0 to 0.36.0
- [Commits](https://github.com/fluxcd/pkg/compare/oci/v0.35.0...ssa/v0.36.0)

Updates `github.com/getsentry/sentry-go` from 0.25.0 to 0.26.0
- [Release notes](https://github.com/getsentry/sentry-go/releases)
- [Changelog](https://github.com/getsentry/sentry-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-go/compare/v0.25.0...v0.26.0)

Updates `github.com/ktrysmt/go-bitbucket` from 0.9.73 to 0.9.74
- [Release notes](https://github.com/ktrysmt/go-bitbucket/releases)
- [Commits](https://github.com/ktrysmt/go-bitbucket/compare/v0.9.73...v0.9.74)

Updates `github.com/nats-io/nats.go` from 1.31.0 to 1.32.0
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.31.0...v1.32.0)

Updates `github.com/xanzy/go-gitlab` from 0.95.1 to 0.96.0
- [Changelog](https://github.com/xanzy/go-gitlab/blob/main/releases_test.go)
- [Commits](https://github.com/xanzy/go-gitlab/compare/v0.95.1...v0.96.0)

Updates `google.golang.org/api` from 0.157.0 to 0.159.0
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.157.0...v0.159.0)

---
updated-dependencies:
- dependency-name: cloud.google.com/go/pubsub
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: code.gitea.io/sdk/gitea
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/Azure/azure-event-hubs-go/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/DataDog/datadog-api-client-go/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/PagerDuty/go-pagerduty
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/fluxcd/cli-utils
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/fluxcd/pkg/apis/event
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/fluxcd/pkg/apis/meta
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/fluxcd/pkg/git
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/fluxcd/pkg/runtime
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/fluxcd/pkg/ssa
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/getsentry/sentry-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/ktrysmt/go-bitbucket
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/nats-io/nats.go
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/xanzy/go-gitlab
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-29 13:31:16 +00:00
Stefan Prodan bba04db89d
Merge pull request #716 from fluxcd/dependabot-ignore-logr
dependabot: Ignore `go-logr` package
2024-01-29 15:28:11 +02:00
Stefan Prodan c71a90e01a
dependabot: Ignore `go-logr` package
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-01-29 15:24:47 +02:00
Stefan Prodan 56120e9afc
Merge pull request #713 from fluxcd/dependabot-gomod
ci: Enable dependabot `gomod` updates
2024-01-29 15:13:01 +02:00
Stefan Prodan f455608bfd
ci: Enable dependabot `gomod` updates
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-01-26 20:38:53 +02:00
Sunny b816076657
Merge pull request #699 from piny940/fix/docs/v1beta3/providers
fix typo in docs/spec/v1beta3/providers.md
2024-01-26 20:37:28 +05:30
piny940 f5c0f6d33b fix typo in docs/spec/v1beta3/providers.md
Signed-off-by: piny940 <an.s.shoma@gmail.com>
2024-01-26 20:04:14 +05:30
Stefan Prodan d72c7df6a5
Merge pull request #711 from fluxcd/dependabot/github_actions/ci-1ce66589eb
build(deps): bump the ci group with 2 updates
2024-01-22 16:58:10 +02:00
dependabot[bot] b4deeb98be
build(deps): bump the ci group with 2 updates
Bumps the ci group with 2 updates: [actions/cache](https://github.com/actions/cache) and [anchore/sbom-action](https://github.com/anchore/sbom-action).


Updates `actions/cache` from 3.3.3 to 4.0.0
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](e12d46a63a...13aacd865c)

Updates `anchore/sbom-action` from 0.15.3 to 0.15.4
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](c7f031d924...41f7a6c033)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-22 07:47:21 +00:00
Stefan Prodan 4df3ce451a
Merge pull request #710 from fluxcd/dependabot/github_actions/ci-425d4b0f20
build(deps): bump the ci group with 2 updates
2024-01-15 10:57:58 +02:00
dependabot[bot] 70b93d3f3d
build(deps): bump the ci group with 2 updates
Bumps the ci group with 2 updates: [actions/cache](https://github.com/actions/cache) and [anchore/sbom-action](https://github.com/anchore/sbom-action).


Updates `actions/cache` from 3.3.2 to 3.3.3
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](704facf57e...e12d46a63a)

Updates `anchore/sbom-action` from 0.15.2 to 0.15.3
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](719133684c...c7f031d924)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 07:25:50 +00:00
Stefan Prodan ec61423cc5
Merge pull request #703 from radenui/fix/grafana-provider-remove-unsupported-character
fix(grafana-provider): replace ":" character in eventMetadata
2024-01-11 20:55:02 +02:00
Arthur ANDRIEU 5371d8a79d fix(grafana-provider): replace ":" character in eventMetadata
Signed-off-by: Arthur Andrieu  <arthur.andrieu@gmail.com>
2024-01-11 19:16:00 +01:00
Somtochi Onyekwere 071bf10fa3
Merge pull request #708 from fluxcd/update-maintainer-details
Update Somtochi's maintainer details
2024-01-09 20:13:06 +01:00
Somtochi Onyekwere d29d1f0804 change company
Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>
2024-01-09 19:48:47 +01:00
Somtochi Onyekwere 0d39d277d2 update Somtochi's maintainer details
Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>
2024-01-09 19:46:59 +01:00
Stefan Prodan c368adbbcc
Merge pull request #706 from fluxcd/dependabot/go_modules/github.com/cloudflare/circl-1.3.7
build(deps): bump github.com/cloudflare/circl from 1.3.6 to 1.3.7
2024-01-08 19:08:22 +02:00
dependabot[bot] 69dfee9318
build(deps): bump github.com/cloudflare/circl from 1.3.6 to 1.3.7
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.3.6 to 1.3.7.
- [Release notes](https://github.com/cloudflare/circl/releases)
- [Commits](https://github.com/cloudflare/circl/compare/v1.3.6...v1.3.7)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/circl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-08 16:54:20 +00:00
Max Jonas Werner e7a241d777
Merge pull request #704 from fluxcd/dependabot/github_actions/ci-9edfa6747d
build(deps): bump the ci group with 2 updates
2024-01-08 08:53:07 +01:00
dependabot[bot] 8ce32f9553
build(deps): bump the ci group with 2 updates
Bumps the ci group with 2 updates: [docker/metadata-action](https://github.com/docker/metadata-action) and [anchore/sbom-action](https://github.com/anchore/sbom-action).


Updates `docker/metadata-action` from 5.4.0 to 5.5.0
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](9dc751fe24...dbef88086f)

Updates `anchore/sbom-action` from 0.15.1 to 0.15.2
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](5ecf649a41...719133684c)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-08 07:33:03 +00:00
Sunny dcabd7c42b
Merge pull request #693 from fluxcd/update-old-api-versions
Remove old/incorrect API version usage
2023-12-19 19:12:21 +05:30
Sunny 5b152f583d Remove old/incorrect API version usage
- Update README.md to point to v1beta3 spec docs.
- Remove provider testdata which had old API version and is no longer
  used in any test.
- Update Provider v1beta2 spec docs to use Alert v1beta2.
- Update Provider v1beta3 spec docs to use v1beta3 API in all the
  code snippets.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-12-19 18:25:16 +05:30
Hidde Beydals 0b48a065e3
Merge pull request #696 from fluxcd/dependabot/github_actions/ci-c99cc58ab6
build(deps): bump the ci group with 3 updates
2023-12-19 10:11:58 +01:00
dependabot[bot] a88f97eb44
build(deps): bump the ci group with 3 updates
Bumps the ci group with 3 updates: [korthout/backport-action](https://github.com/korthout/backport-action), [docker/metadata-action](https://github.com/docker/metadata-action) and [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `korthout/backport-action` from 2.2.0 to 2.3.0
- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](b982d297e3...addffea45a)

Updates `docker/metadata-action` from 5.3.0 to 5.4.0
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](31cebacef4...9dc751fe24)

Updates `sigstore/cosign-installer` from 3.2.0 to 3.3.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](1fc5bd396d...9614fae9e5)

---
updated-dependencies:
- dependency-name: korthout/backport-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-19 09:02:07 +00:00
Hidde Beydals 0bb0c6041c
Merge pull request #694 from fluxcd/dependabot/go_modules/golang.org/x/crypto-0.17.0
build(deps): bump golang.org/x/crypto from 0.16.0 to 0.17.0
2023-12-19 09:58:47 +01:00
dependabot[bot] 6ae9bb6fa7
build(deps): bump golang.org/x/crypto from 0.16.0 to 0.17.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/crypto/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-19 00:06:31 +00:00
Sunny f9933507d0
Merge pull request #689 from fluxcd/pick-changelog-v1.2.3
Pick changelog v1.2.3
2023-12-14 19:59:49 +05:30
Sunny 20423eb80a Add changelog entry for v1.2.3
Signed-off-by: Sunny <darkowlzz@protonmail.com>
(cherry picked from commit 3289dbd35d)
2023-12-14 18:09:08 +05:30
Sunny a817cf91c1
Merge pull request #686 from fluxcd/exclude-token
Exclude eventv1.MetaTokenKey from event metadata
2023-12-14 14:20:30 +05:30
Sunny 68c38244cc Exclude eventv1.MetaTokenKey from event metadata
eventv1.MetaTokenKey is required to be considered in rate limiting but
it is only for internal use by flux components and should not be sent to
the alert provider. Remove eventv1.MetaTokenKey from the metadata of
event before processing the event for various matching alerts.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-12-13 23:13:38 +05:30
Sunny 7834608f77
Merge pull request #683 from fluxcd/v1beta3-provider-interval
Add .spec.interval in v1beta3 Provider
2023-12-13 15:28:25 +05:30
Sunny 7f5eea0a2e Add .spec.interval in v1beta3 Provider
For backwards compatibility with v1beta2 Provider, add .spec.interval
with deprecation marker.
Interval was an optional field in v1beta2 with internal default. Only
the users who had explicitly set intervals would have encountered this
incompatibility error after upgrade.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-12-13 15:06:10 +05:30
Stefan Prodan 73e1965419
Merge pull request #682 from matheuscscp/fix-address-validation
Remove URL syntax validation for provider address entirely
2023-12-13 11:35:18 +02:00
Matheus Pimenta 143a0b3ee0 Remove URL syntax validation for provider address entirely
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2023-12-12 19:01:31 +00:00
Hidde Beydals e48be82c89
Merge pull request #679 from fluxcd/pick-changelog-v1.2.2 2023-12-11 15:47:22 +01:00
Hidde Beydals 2a8ab214c9
Add changelog entry for v1.2.2
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
(cherry picked from commit 9066a87e56)
2023-12-11 15:39:57 +01:00
Stefan Prodan ef5c602fb1
Merge pull request #676 from fluxcd/runtime-v0.43.2
Update dependencies
2023-12-11 14:42:52 +01:00
Stefan Prodan 74bd37a992
Update dependencies
- github.com/fluxcd/pkg/runtime v0.43.2
- github.com/fluxcd/cli-utils v0.36.0-flux.2
- github.com/xanzy/go-gitlab v0.95.1

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-12-11 15:28:02 +02:00
Hidde Beydals 52da6c48ca
Merge pull request #672 from fluxcd/dependabot/github_actions/ci-4167a8d32d
build(deps): bump the ci group with 1 update
2023-12-11 09:32:15 +01:00
dependabot[bot] 879f9576e2
build(deps): bump the ci group with 1 update
Bumps the ci group with 1 update: [actions/setup-go](https://github.com/actions/setup-go).

- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](93397bea11...0c52d547c9)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 08:21:39 +00:00
Hidde Beydals 6ffb5f3f70
Merge pull request #673 from fluxcd/alpine-319
build: update Alpine to 3.19
2023-12-11 09:19:50 +01:00
Hidde Beydals 40ba471d6b
build: update Alpine to 3.19
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
2023-12-11 09:04:49 +01:00
Hidde Beydals 791d34ef46
Merge pull request #671 from fluxcd/pick-changelog-v1.2.1
Add changelog entry for v1.2.1
2023-12-08 13:08:34 +01:00
Hidde Beydals 57c32c15be
Add changelog entry for v1.2.1
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
(cherry picked from commit d5572c1e2f)
2023-12-08 12:03:27 +01:00
Hidde Beydals 9492ef1b96
Merge pull request #668 from fluxcd/update-deps
Update dependencies
2023-12-08 09:30:16 +01:00
Hidde Beydals b007f42139
Update dependencies
- github.com/ktrysmt/go-bitbucket to v0.9.73
- google.golang.org/api to v0.153.0

Signed-off-by: Hidde Beydals <hidde@hhh.computer>
2023-12-08 09:11:10 +01:00
Hidde Beydals 9f90225f04
Merge pull request #664 from hectorj2f/replace_go_module
Replace whilp/git-urls module by chainguard-dev/git-urls
2023-12-06 09:43:47 +01:00
Hector Fernandez 39a3853c5c replace whilp/git-urls module by chainguard-dev/git-urls
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
2023-12-06 09:38:59 +01:00
Hidde Beydals cd51b02fdd
Merge pull request #663 from fluxcd/backport-release-v1.2.x-label
Add `backport:release/v1.2.x` label
2023-12-06 09:37:25 +01:00
Sunny c857eb65b3 Add backport:release/v1.2.x label
Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-12-06 09:22:16 +01:00
Hidde Beydals 46d54b024d
Merge pull request #665 from fluxcd/go-1.21
Update Go to 1.21.x
2023-12-06 09:20:18 +01:00
Hidde Beydals c8d287e9c3
Update `tonistiigi/xx` to 1.3.0
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
2023-12-06 09:02:25 +01:00
Hidde Beydals f045217d70
Update Go to 1.21.x
As appears to be magically required by
`github.com/slok/go-http-metrics`.

Signed-off-by: Hidde Beydals <hidde@hhh.computer>
2023-12-06 09:02:25 +01:00
Hidde Beydals 5acc9a12a8
Merge pull request #662 from fluxcd/release-v1.2.x
Merge release/v1.2.x changes to main
2023-12-05 21:08:28 +01:00
Sunny f4f6cdc73b Release v1.2.0
Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-12-06 00:49:03 +05:30
Sunny 42870e46ce Add changelog entry for v1.2.0
Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-12-06 00:49:03 +05:30
Stefan Prodan fe333842be
Merge pull request #659 from fluxcd/dependabot/github_actions/ci-3e3005af3f
build(deps): bump the ci group with 3 updates
2023-12-05 16:29:55 +02:00
dependabot[bot] 29fb291738
build(deps): bump the ci group with 3 updates
Bumps the ci group with 3 updates: [korthout/backport-action](https://github.com/korthout/backport-action), [docker/metadata-action](https://github.com/docker/metadata-action) and [anchore/sbom-action](https://github.com/anchore/sbom-action).


Updates `korthout/backport-action` from 2.1.1 to 2.2.0
- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](08bafb375e...b982d297e3)

Updates `docker/metadata-action` from 5.0.0 to 5.3.0
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](96383f4557...31cebacef4)

Updates `anchore/sbom-action` from 0.15.0 to 0.15.1
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](fd74a6fb98...5ecf649a41)

---
updated-dependencies:
- dependency-name: korthout/backport-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-05 13:48:13 +00:00
Sunny 5500739269
Merge pull request #657 from fluxcd/deps-update-v1.2.0
Update go dependencies
2023-12-05 17:36:07 +05:30
Sunny 998cec97b8
Update go dependencies
Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-12-05 17:09:44 +05:30
Stefan Prodan 832757c139
Merge pull request #656 from fluxcd/dependabot/go_modules/github.com/nats-io/nkeys-0.4.6
build(deps): bump github.com/nats-io/nkeys from 0.4.5 to 0.4.6
2023-12-04 11:21:45 +02:00
dependabot[bot] b732427a7a
build(deps): bump github.com/nats-io/nkeys from 0.4.5 to 0.4.6
Bumps [github.com/nats-io/nkeys](https://github.com/nats-io/nkeys) from 0.4.5 to 0.4.6.
- [Release notes](https://github.com/nats-io/nkeys/releases)
- [Changelog](https://github.com/nats-io/nkeys/blob/main/.goreleaser.yml)
- [Commits](https://github.com/nats-io/nkeys/compare/v0.4.5...v0.4.6)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nkeys
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 09:06:44 +00:00
Stefan Prodan bf58d33bd0
Merge pull request #651 from SkullKidCode/nats-provider
Add Provider for NATS Subject
2023-12-04 11:05:51 +02:00
SkullKidCode 3c05438d62
Update docs/spec/v1beta3/providers.md
Co-authored-by: Stefan Prodan <stefan.prodan@gmail.com>
Signed-off-by: SkullKidCode <SkullKidCode@users.noreply.github.com>
2023-12-01 13:50:35 +00:00
Toby Watson 427d20046e
Add NATS provider to v1beta3
Signed-off-by: Toby Watson <SkullKidCode@users.noreply.github.com>
2023-11-30 23:19:21 +00:00
Max Jonas Werner 6e1ccfe653
Merge pull request #654 from fluxcd/cap-address
Cap provider address at 2048 bytes
2023-11-28 14:59:24 +01:00
Max Jonas Werner 52d8945284
Cap provider address at 2048 bytes
The provider address is already capped at 2048 bytes in the CRD and
this commit adds the same upper limit when reading the address from a
Secret.

Signed-off-by: Max Jonas Werner <mail@makk.es>
2023-11-28 12:31:20 +01:00
Sunny 78f5509fe7
Merge pull request #540 from fluxcd/refactor-events
Refactor events and introduce v1beta3 API for Alert and Provider
2023-11-28 16:38:07 +05:30
Sunny 6df2c74b2a event_handler: Use proper ctx for post fail log
Use the context containing proper information about the event for
logging. Previously, the logged error didn't contain any information
about the event, alert or the involved object.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-11-28 16:17:03 +05:30
Sunny 9a5debde32 Deprecate v1beta1 & v1beta2 Alert & Provider APIs
Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-11-28 16:17:03 +05:30
Sunny b2e533af67 Add v1beta3 spec docs
Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-11-28 16:17:03 +05:30
Sunny b99de58dd3 workflows/e2e: Update status-defaults & smoke test
The new alert and provider don't have any status. Remove any status
related checks from workflows/e2e tests.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-11-28 16:17:03 +05:30
Sunny 84e1d74e32 Add alert and provider reconcilers for migration
Add new Alert and Provider reconcilers to perform migration to static
objects. The new Alert and Provider APIs don't contain any status. When
the existing Alerts and Providers are queries using the new API client,
the status would be dropped. A subsequent write of the object to update
the object in api-server will migrate the objects to the new version and
drop the status.
For the stale finalizers on the objects, the new reconcilers ensure that
the finalizers get removed.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-11-28 16:17:03 +05:30
Sunny 19a60e98ea event handler: Add k8s events for Alerts
Emit events in the event handler along with logs on the respective alert
to make the message visible on the alert it belongs to.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-11-28 16:17:03 +05:30
Sunny 80f7237673 Refactor event handler
- Break down the EventServer.handleEvent() implementation into multiple
  smaller functions which are extensively tested on their own.
  - New implementation of filter Alerts for Event
  - New implementation of Event matches Alert
- Remove any readiness check on Alert or Provider.
- Add kubebuilder marker for generating RBAC permissions to create and
  patch events, and query Alert and Provider objects.
- Convert the event handler test from controllers/ dir to work with
  just EventServer without any reconciler, keeping all the test cases
  and slightly modified test set up code.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-11-28 16:17:03 +05:30
Sunny 36bc6529ae Remove Alert and Provider reconcilers
In v1beta3 API, Alert and Provider are static objects and don't need
reconcilers.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-11-28 16:17:03 +05:30
Sunny 4bf469e61b Add Alert and Provider v1beta3 API
v1beta3 API for Alert and Provider makes them static objects, removing
the status subresource and spec fields that are relevant to dynamic
objects with reconcilers.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
2023-11-28 16:17:03 +05:30
Max Jonas Werner c52522bd8b
Merge pull request #652 from fluxcd/dependabot/github_actions/ci-5ef00e396d
build(deps): bump the ci group with 2 updates
2023-11-28 10:10:27 +01:00
dependabot[bot] 7ad92b51de
build(deps): bump the ci group with 2 updates
Bumps the ci group with 2 updates: [anchore/sbom-action](https://github.com/anchore/sbom-action) and [fossa-contrib/fossa-action](https://github.com/fossa-contrib/fossa-action).


Updates `anchore/sbom-action` from 0.14.3 to 0.15.0
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](78fc58e266...fd74a6fb98)

Updates `fossa-contrib/fossa-action` from 2.0.0 to 3.0.0
- [Release notes](https://github.com/fossa-contrib/fossa-action/releases)
- [Changelog](https://github.com/fossa-contrib/fossa-action/blob/master/CHANGELOG.md)
- [Commits](6728dc6fe9...cdc5065bcd)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: fossa-contrib/fossa-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-27 07:41:26 +00:00
Stefan Prodan 26ddbbd726
Merge pull request #648 from fluxcd/k8s-1.28
Update dependencies to Kubernetes v1.28
2023-11-21 14:01:22 +02:00
Stefan Prodan 49d510de81
Update dependencies to Kubernetes v1.28
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-11-21 13:41:08 +02:00
Max Jonas Werner 9869e395fe
Merge pull request #639 from gdasson/main
Add Bitbucket server/Bitbucket Data Center provider for git commit status
2023-11-21 10:16:28 +01:00
gdasson 504dc991cc Adding bitbucketserver provider for git commit status
Signed-off-by: gdasson <gaurav.dasson@gmail.com>
2023-11-20 23:17:04 -06:00
Max Jonas Werner e425a6e307
Merge pull request #646 from fluxcd/dependabot/github_actions/ci-98b70e8bec
build(deps): bump the ci group with 1 update
2023-11-20 09:32:34 +01:00
dependabot[bot] 603c48fbbe
build(deps): bump the ci group with 1 update
Bumps the ci group with 1 update: [docker/build-push-action](https://github.com/docker/build-push-action).

- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](0565240e2d...4a13e500e5)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-20 07:29:24 +00:00
Max Jonas Werner 9549ebfc07
Merge pull request #643 from fluxcd/dependabot/github_actions/ci-da8bbba46e
build(deps): bump the ci group with 2 updates
2023-11-13 08:44:06 +01:00
dependabot[bot] da52599998
build(deps): bump the ci group with 2 updates
Bumps the ci group with 2 updates: [korthout/backport-action](https://github.com/korthout/backport-action) and [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `korthout/backport-action` from 2.1.0 to 2.1.1
- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](cb79e4e5f4...08bafb375e)

Updates `sigstore/cosign-installer` from 3.1.2 to 3.2.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](11086d2504...1fc5bd396d)

---
updated-dependencies:
- dependency-name: korthout/backport-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-13 07:19:13 +00:00
Max Jonas Werner 5d8924a319
Merge pull request #641 from fluxcd/dependabot/github_actions/ci-18c09be9f8
build(deps): bump the ci group with 1 update
2023-11-06 08:34:45 +01:00
dependabot[bot] 0377782fe6
build(deps): bump the ci group with 1 update
Bumps the ci group with 1 update: [korthout/backport-action](https://github.com/korthout/backport-action).

- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](408fae11ed...cb79e4e5f4)

---
updated-dependencies:
- dependency-name: korthout/backport-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 07:11:36 +00:00
Max Jonas Werner f4a050871e
Merge pull request #637 from fluxcd/dependabot/github_actions/ci-2e2e3c3b83
build(deps): bump the ci group with 1 update
2023-10-30 08:56:50 +01:00
dependabot[bot] 341a819d65
build(deps): bump the ci group with 1 update
Bumps the ci group with 1 update: [korthout/backport-action](https://github.com/korthout/backport-action).

- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](bd68141f07...408fae11ed)

---
updated-dependencies:
- dependency-name: korthout/backport-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 07:17:46 +00:00
Hidde Beydals 968ab5ee3c
Merge pull request #635 from fluxcd/dependabot/go_modules/google.golang.org/grpc-1.57.1
build(deps): bump google.golang.org/grpc from 1.57.0 to 1.57.1
2023-10-26 00:22:35 +02:00
dependabot[bot] 3087c0e291
build(deps): bump google.golang.org/grpc from 1.57.0 to 1.57.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.57.0 to 1.57.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.57.0...v1.57.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-25 21:26:57 +00:00
Max Jonas Werner 38a8562b63
Merge pull request #632 from fluxcd/dependabot/github_actions/ci-16ff15100a
build(deps): bump the ci group with 1 update
2023-10-23 10:38:42 +02:00
dependabot[bot] 15efcb55b6
build(deps): bump the ci group with 1 update
Bumps the ci group with 1 update: [actions/checkout](https://github.com/actions/checkout).

- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](8ade135a41...b4ffde65f4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 08:01:48 +00:00
Hidde Beydals 820fe53ce7
Merge pull request #628 from fluxcd/dependabot/go_modules/api/golang.org/x/net-0.17.0
build(deps): bump golang.org/x/net from 0.10.0 to 0.17.0 in /api
2023-10-12 09:44:08 +02:00
dependabot[bot] c51ac08026
build(deps): bump golang.org/x/net from 0.10.0 to 0.17.0 in /api
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.10.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.10.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-12 07:24:23 +00:00
Hidde Beydals c64d76801a
Merge pull request #629 from fluxcd/dependabot/go_modules/golang.org/x/net-0.17.0
build(deps): bump golang.org/x/net from 0.14.0 to 0.17.0
2023-10-12 09:23:42 +02:00
dependabot[bot] 4c5c0eadd7
build(deps): bump golang.org/x/net from 0.14.0 to 0.17.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.14.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.14.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-11 23:05:14 +00:00
Hidde Beydals 56facfa96b
Merge pull request #627 from fluxcd/tidy-nits 2023-10-11 21:35:54 +02:00
Hidde Beydals 3dce75a07e
misc: fix hypothetical implicit memory aliasing
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
2023-10-11 15:02:56 +02:00
Hidde Beydals edb6a54e23
misc: take errs into account
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
2023-10-11 15:01:35 +02:00
Hidde Beydals bdda58062f
misc: handle `strings.Title` deprecation
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
2023-10-11 15:01:29 +02:00
Hidde Beydals 16fb90ed84
misc: remove redundant `break` statements
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
2023-10-10 12:07:32 +02:00
Hidde Beydals 23d57eb9d3
misc: use `strings.EqualFold`
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
2023-10-10 12:07:31 +02:00
Hidde Beydals 30db06d0df
misc: do not capitalize err strings
Except for where names are being used (e.g. `Authorization` header,
Nexus, etc.)

Signed-off-by: Hidde Beydals <hidde@hhh.computer>
2023-10-10 12:07:30 +02:00
Max Jonas Werner 7d6dc52fdb
Merge pull request #623 from fluxcd/dependabot/github_actions/ci-663ed1f0b6
build(deps): bump the ci group with 1 update
2023-09-25 17:09:52 +02:00
dependabot[bot] dab1c00a2a
build(deps): bump the ci group with 1 update
Bumps the ci group with 1 update: [actions/checkout](https://github.com/actions/checkout).

- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](3df4ab11eb...8ade135a41)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-25 07:28:16 +00:00
Stefan Prodan 8c67c1e473
Merge pull request #621 from fluxcd/dependabot/github_actions/ci-8ad0e81912
build(deps): bump the ci group with 6 updates
2023-09-18 11:21:50 +03:00
dependabot[bot] e0c88e9bb1
build(deps): bump the ci group with 6 updates
Bumps the ci group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `2.2.0` | `3.0.0` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `2.10.0` | `3.0.0` |
| [docker/login-action](https://github.com/docker/login-action) | `2.2.0` | `3.0.0` |
| [docker/metadata-action](https://github.com/docker/metadata-action) | `4.6.0` | `5.0.0` |
| [docker/build-push-action](https://github.com/docker/build-push-action) | `4.2.1` | `5.0.0` |
| [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) | `4.6.0` | `5.0.0` |


Updates `docker/setup-qemu-action` from 2.2.0 to 3.0.0
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](2b82ce82d5...68827325e0)

Updates `docker/setup-buildx-action` from 2.10.0 to 3.0.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](885d1462b8...f95db51fdd)

Updates `docker/login-action` from 2.2.0 to 3.0.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](465a07811f...343f7c4344)

Updates `docker/metadata-action` from 4.6.0 to 5.0.0
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Upgrade guide](https://github.com/docker/metadata-action/blob/master/UPGRADE.md)
- [Commits](818d4b7b91...96383f4557)

Updates `docker/build-push-action` from 4.2.1 to 5.0.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](0a97817b6a...0565240e2d)

Updates `goreleaser/goreleaser-action` from 4.6.0 to 5.0.0
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](5fdedb94ab...7ec5c2b0c6)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: goreleaser/goreleaser-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-18 07:56:41 +00:00
Stefan Prodan 60e2525330
Merge pull request #619 from arikkfir/patch-1
Fix README.md links to notification APIs
2023-09-16 13:13:38 +03:00
Arik Kfir 823c76342b
Fix README.md links to notification APIs
This change fixes the documentation links for the notification manager APIs.

Signed-off-by: Arik Kfir <arik@kfirs.com>
2023-09-16 12:28:33 +03:00
Stefan Prodan e333d95872
Merge pull request #617 from fluxcd/dependabot/github_actions/ci-dbfd6c86b4
build(deps): bump the ci group with 4 updates
2023-09-11 16:06:46 +01:00
dependabot[bot] 9c0fcac72c
build(deps): bump the ci group with 4 updates
Bumps the ci group with 4 updates: [actions/checkout](https://github.com/actions/checkout), [actions/cache](https://github.com/actions/cache), [docker/build-push-action](https://github.com/docker/build-push-action) and [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action).


Updates `actions/checkout` from 3.6.0 to 4.0.0
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](f43a0e5ff2...3df4ab11eb)

Updates `actions/cache` from 3.3.1 to 3.3.2
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](88522ab9f3...704facf57e)

Updates `docker/build-push-action` from 4.1.1 to 4.2.1
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](2eb1c1961a...0a97817b6a)

Updates `goreleaser/goreleaser-action` from 4.4.0 to 4.6.0
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](3fa32b8bb5...5fdedb94ab)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: goreleaser/goreleaser-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-11 08:03:22 +00:00
Max Jonas Werner 0b4eee1446
Merge pull request #613 from fluxcd/dependabot/go_modules/github.com/cyphar/filepath-securejoin-0.2.4
build(deps): bump github.com/cyphar/filepath-securejoin from 0.2.3 to 0.2.4
2023-09-08 11:58:05 +02:00
dependabot[bot] 4137ce50c4
build(deps): bump github.com/cyphar/filepath-securejoin
Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.2.3 to 0.2.4.
- [Release notes](https://github.com/cyphar/filepath-securejoin/releases)
- [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.2.3...v0.2.4)

---
updated-dependencies:
- dependency-name: github.com/cyphar/filepath-securejoin
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-08 07:30:22 +00:00
Stefan Prodan 795a9db0f3
Merge pull request #612 from fluxcd/dependabot/github_actions/ci-06f6b75e12
build(deps): bump the ci group with 1 update
2023-09-08 10:28:45 +03:00
dependabot[bot] 61137e5eeb
build(deps): bump the ci group with 1 update
Bumps the ci group with 1 update: [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).

- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](6e04d228eb...11086d2504)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 07:07:33 +00:00
Max Jonas Werner 4735dc5578
Merge pull request #611 from fluxcd/1.1.x-label
Add 1.1.x backport labels
2023-08-28 12:31:05 +02:00
Max Jonas Werner c6b1ef67a3
Add 1.1.x backport labels
Signed-off-by: Max Jonas Werner <mail@makk.es>
2023-08-28 11:53:37 +02:00
Stefan Prodan ec834ff3ae
Merge pull request #609 from fluxcd/dependabot/github_actions/ci-34f3dadbdb
build(deps): bump the ci group with 3 updates
2023-08-28 11:22:38 +03:00
dependabot[bot] c33b88d946
build(deps): bump the ci group with 3 updates
Bumps the ci group with 3 updates: [actions/checkout](https://github.com/actions/checkout), [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) and [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator).


Updates `actions/checkout` from 3.5.3 to 3.6.0
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](c85c95e3d7...f43a0e5ff2)

Updates `docker/setup-buildx-action` from 2.9.1 to 2.10.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](4c0219f9ac...885d1462b8)

Updates `slsa-framework/slsa-github-generator` from 1.8.0 to 1.9.0
- [Release notes](https://github.com/slsa-framework/slsa-github-generator/releases)
- [Changelog](https://github.com/slsa-framework/slsa-github-generator/blob/main/CHANGELOG.md)
- [Commits](https://github.com/slsa-framework/slsa-github-generator/compare/v1.8.0...v1.9.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: slsa-framework/slsa-github-generator
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-28 07:27:11 +00:00
Stefan Prodan bb8cfd3ead
Merge pull request #608 from fluxcd/release/v1.1.x
Housekeeping: merge `release/v1.1.x` back into `main`
2023-08-24 15:38:43 +03:00
161 changed files with 14785 additions and 5929 deletions

View File

@ -1,16 +1,30 @@
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
labels: ["dependencies"]
schedule:
interval: "monthly"
groups:
go-deps:
patterns:
- "*"
allow:
- dependency-type: "direct"
ignore:
# Kubernetes deps are updated by fluxcd/pkg
- dependency-name: "k8s.io/*"
- dependency-name: "sigs.k8s.io/*"
- dependency-name: "github.com/go-logr/*"
# Flux APIs pkg are updated at release time
- dependency-name: "github.com/fluxcd/notification-controller/api"
- package-ecosystem: "github-actions"
directory: "/"
labels: ["area/ci", "dependencies"]
schedule:
# By default, this will be on a monday.
interval: "weekly"
groups:
# Group all updates together, so that they are all applied in a single PR.
# Grouped updates are currently in beta and is subject to change.
# xref: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#groups
ci:
patterns:
- "*"
schedule:
interval: "monthly"

18
.github/labels.yaml vendored
View File

@ -10,3 +10,21 @@
- name: backport:release/v1.0.x
description: To be backported to release/v1.0.x
color: '#ffd700'
- name: backport:release/v1.1.x
description: To be backported to release/v1.1.x
color: '#ffd700'
- name: backport:release/v1.2.x
description: To be backported to release/v1.2.x
color: '#ffd700'
- name: backport:release/v1.3.x
description: To be backported to release/v1.3.x
color: '#ffd700'
- name: backport:release/v1.4.x
description: To be backported to release/v1.4.x
color: '#ffd700'
- name: backport:release/v1.5.x
description: To be backported to release/v1.5.x
color: '#ffd700'
- name: backport:release/v1.6.x
description: To be backported to release/v1.6.x
color: '#ffd700'

View File

@ -13,11 +13,11 @@ jobs:
if: github.event.pull_request.state == 'closed' && github.event.pull_request.merged && (github.event_name != 'labeled' || startsWith('backport:', github.event.label.name))
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Create backport PRs
uses: korthout/backport-action@bd68141f079bd036e45ea8149bc9d174d5a04703 # v1.4.0
uses: korthout/backport-action@436145e922f9561fc5ea157ff406f21af2d6b363 # v3.2.0
# xref: https://github.com/korthout/backport-action#inputs
with:
# Use token to allow workflows to be triggered for the created PR

View File

@ -11,11 +11,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: 1.20.x
go-version: 1.24.x
cache-dependency-path: |
**/go.sum
**/go.mod

View File

@ -12,14 +12,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup QEMU
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
- name: Setup Docker Buildx
id: buildx
uses: docker/setup-buildx-action@4c0219f9ac95b02789c1075625400b2acbff50b1 # v2.9.1
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
- name: Cache Docker layers
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
id: cache
with:
path: /tmp/.buildx-cache
@ -27,18 +27,16 @@ jobs:
restore-keys: |
${{ runner.os }}-buildx-ghcache-
- name: Setup Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: 1.20.x
go-version: 1.24.x
cache-dependency-path: |
**/go.sum
**/go.mod
- name: Setup Kubernetes
uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
with:
version: v0.20.0
cluster_name: kind
node_image: kindest/node:v1.27.3@sha256:3966ac761ae0136263ffdb6cfd4db23ef8a83cba8a463690e98317add2c9ba72
- name: Setup Kustomize
uses: fluxcd/pkg/actions/kustomize@main
- name: Run tests
@ -71,7 +69,7 @@ jobs:
- name: Run default status test
run: |
kubectl apply -f config/testdata/status-defaults
for crd in alert provider receiver ; do
for crd in receiver ; do
RESULT=$(kubectl get ${crd} status-defaults -o go-template={{.status}})
EXPECTED='map[observedGeneration:-1]'
if [ "${RESULT}" != "${EXPECTED}" ] ; then
@ -88,9 +86,6 @@ jobs:
- name: Run smoke tests
run: |
kubectl -n notification-system apply -f ./config/samples
kubectl -n notification-system wait provider/slack-provider-sample --for=condition=ready --timeout=1m
kubectl -n notification-system wait provider/generic-provider-sample --for=condition=ready --timeout=1m
kubectl -n notification-system wait alert/alert-sample --for=condition=ready --timeout=1m
kubectl -n notification-system wait receiver/receiver-sample --for=condition=ready --timeout=1m
- name: Logs
run: |

View File

@ -29,7 +29,7 @@ jobs:
packages: write # for pushing and signing container images.
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Kustomize
uses: fluxcd/pkg/actions/kustomize@main
- name: Prepare
@ -42,24 +42,24 @@ jobs:
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
- name: Setup QEMU
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
- name: Setup Docker Buildx
id: buildx
uses: docker/setup-buildx-action@4c0219f9ac95b02789c1075625400b2acbff50b1 # v2.9.1
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
- name: Login to GitHub Container Registry
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ghcr.io
username: fluxcdbot
password: ${{ secrets.GHCR_TOKEN }}
- name: Login to Docker Hub
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
username: fluxcdbot
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
- name: Generate images meta
id: meta
uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175 # v4.6.0
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
with:
images: |
fluxcd/${{ env.CONTROLLER }}
@ -68,7 +68,7 @@ jobs:
type=raw,value=${{ steps.prep.outputs.VERSION }}
- name: Publish images
id: build-push
uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825 # v4.1.1
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0
with:
sbom: true
provenance: true
@ -79,7 +79,7 @@ jobs:
platforms: linux/amd64,linux/arm/v7,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 # v3.1.1
- uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2
- name: Sign images
env:
COSIGN_EXPERIMENTAL: 1
@ -92,14 +92,14 @@ jobs:
mkdir -p config/release
kustomize build ./config/crd > ./config/release/${{ env.CONTROLLER }}.crds.yaml
kustomize build ./config/manager > ./config/release/${{ env.CONTROLLER }}.deployment.yaml
- uses: anchore/sbom-action/download-syft@78fc58e266e87a38d4194b2137a3d4e9bcaf7ca1 # v0.14.3
- uses: anchore/sbom-action/download-syft@e11c554f704a0b820cbf8c51673f6945e0731532 # v0.20.0
- name: Create release and SBOM
id: run-goreleaser
if: startsWith(github.ref, 'refs/tags/v')
uses: goreleaser/goreleaser-action@3fa32b8bb5620a2c1afe798654bbad59f9da4906 # v4.4.0
uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0
with:
version: latest
args: release --clean --skip-validate
args: release --clean --skip=validate
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Generate SLSA metadata
@ -123,7 +123,7 @@ jobs:
id-token: write # for creating OIDC tokens for signing.
contents: write # for uploading attestations to GitHub releases.
if: startsWith(github.ref, 'refs/tags/v')
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.8.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
with:
provenance-name: "provenance.intoto.jsonl"
base64-subjects: "${{ needs.release.outputs.hashes }}"
@ -136,7 +136,7 @@ jobs:
id-token: write # for creating OIDC tokens for signing.
packages: write # for uploading attestations.
if: startsWith(github.ref, 'refs/tags/v')
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.8.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
with:
image: ${{ needs.release.outputs.image_url }}
digest: ${{ needs.release.outputs.image_digest }}
@ -151,7 +151,7 @@ jobs:
id-token: write # for creating OIDC tokens for signing.
packages: write # for uploading attestations.
if: startsWith(github.ref, 'refs/tags/v')
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.8.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
with:
image: ghcr.io/${{ needs.release.outputs.image_url }}
digest: ${{ needs.release.outputs.image_digest }}

View File

@ -18,9 +18,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Run FOSSA scan and upload build data
uses: fossa-contrib/fossa-action@6728dc6fe9a068c648d080c33829ffbe56565023 # v2.0.0
uses: fossa-contrib/fossa-action@3d2ef181b1820d6dcd1972f86a767d18167fa19b # v3.0.1
with:
# FOSSA Push-Only API Token
fossa-api-key: 5ee8bf422db1471e0bcf2bcb289185de
@ -31,22 +31,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: 1.20.x
go-version: 1.24.x
cache-dependency-path: |
**/go.sum
**/go.mod
- name: Initialize CodeQL
uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
with:
languages: go
# xref: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# xref: https://codeql.github.com/codeql-query-help/go/
queries: security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18

View File

@ -17,8 +17,8 @@ jobs:
permissions:
issues: write
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- uses: EndBug/label-sync@da00f2c11fdb78e4fae44adac2fdd713778ea3e8 # v2.3.2
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: EndBug/label-sync@52074158190acb45f3077f9099fea818aa43f97a # v2.3.3
with:
# Configuration file
config-file: |

View File

@ -23,7 +23,7 @@ release:
To verify the images and their provenance (SLSA level 3), please see the [security documentation](https://fluxcd.io/flux/security/).
changelog:
skip: true
disable: true
checksum:
extra_files:

View File

@ -2,6 +2,388 @@
All notable changes to this project are documented in this file.
## 1.6.0
**Release date:** 2025-05-27
This minor release comes with various bug fixes and improvements.
### Provider
The `azureeventhub` provider now supports workload identity both
at the controller and object levels. For object level, the
`.spec.serviceAccountName` field can be set to the name of a
service account in the same namespace that was configured with
a Managed Identity.
For object level to work, the controller feature gate
`ObjectLevelWorkloadIdentity` must be enabled. See a complete guide
[here](https://fluxcd.io/flux/integrations/azure/).
The `github` and `githubdispatch` providers now support authenticating
with a GitHub App. See docs
[here](https://fluxcd.io/flux/components/notification/providers/#github)
and
[here](https://fluxcd.io/flux/components/notification/providers/#github-dispatch).
For commit status providers it is now possible to define a custom
status string by defining a CEL expression in the `.spec.commitStatusExpr`
field. The variables `event`, `alert` and `provider` are available
for the CEL expression. See
[docs](https://fluxcd.io/flux/components/notification/providers/#custom-commit-status-messages).
### General updates
In addition, the Kubernetes dependencies have been updated to v1.33 and
various other controller dependencies have been updated to their latest
version. The controller is now built with Go 1.24.
Fixes:
- Fix Slack chat.postMessage error handling
[#1086](https://github.com/fluxcd/notification-controller/pull/1086)
- Fix pass 'certPool' to Gitea client on creation
[#1084](https://github.com/fluxcd/notification-controller/pull/1084)
- CrossNamespaceObjectReference: Fix MaxLength validation to kubernetes max size of 253
[#1108](https://github.com/fluxcd/notification-controller/pull/1108)
- Sanitize proxy error logging
[#1093](https://github.com/fluxcd/notification-controller/pull/1093)
Improvements:
- [RFC-0010] Workload Identity support for `azureeventhub` provider
[#1106](https://github.com/fluxcd/notification-controller/pull/1106)
[#1116](https://github.com/fluxcd/notification-controller/pull/1116)
[#1120](https://github.com/fluxcd/notification-controller/pull/1120)
[#1109](https://github.com/fluxcd/notification-controller/pull/1109)
[#1112](https://github.com/fluxcd/notification-controller/pull/1112)
- GitHub App authentication support for `github` and `githubdispatch`
[#1058](https://github.com/fluxcd/notification-controller/pull/1058)
- Support CEL expressions to construct commit statuses
[#1068](https://github.com/fluxcd/notification-controller/pull/1068)
- Add proxy support to `gitea` provider
[#1087](https://github.com/fluxcd/notification-controller/pull/1087)
- Various dependency updates
[#1101](https://github.com/fluxcd/notification-controller/pull/1101)
[#1119](https://github.com/fluxcd/notification-controller/pull/1119)
[#1118](https://github.com/fluxcd/notification-controller/pull/1118)
[#1113](https://github.com/fluxcd/notification-controller/pull/1113)
[#1104](https://github.com/fluxcd/notification-controller/pull/1104)
## 1.5.0
**Release date:** 2025-02-13
This minor release comes with various bug fixes and improvements.
### Alert
Now notification-controller also sends event metadata specified in Flux objects through
annotations. See [docs](https://fluxcd.io/flux/components/notification/alerts/#event-metadata-from-object-annotations).
Now notification-controller is also capable of updating Git commit statuses
from events about Kustomizations that consume OCIRepositories. See
[docs](https://fluxcd.io/flux/cheatsheets/oci-artifacts/#git-commit-status-updates).
### Receiver
The Receiver API now supports filtering the declared resources that
match a given Common Expression Language (CEL) expression. See
[docs](https://fluxcd.io/flux/components/notification/receivers/#filtering-reconciled-objects-with-cel).
In addition, the Kubernetes dependencies have been updated to v1.32.1 and
various other controller dependencies have been updated to their latest
version.
Fixes:
- Remove deprecated object metrics from controllers
[#997](https://github.com/fluxcd/notification-controller/pull/997)
- msteams notifier: adaptive cards full width
[#1017](https://github.com/fluxcd/notification-controller/pull/1017)
- fix: adding of duplicate commit statuses in gitlab
[#1010](https://github.com/fluxcd/notification-controller/pull/1010)
- Fix add missing return statement and a few style issues
[#1039](https://github.com/fluxcd/notification-controller/pull/1039)
Improvements:
- [RFC-0008] Custom Event Metadata from Annotations
[#1014](https://github.com/fluxcd/notification-controller/pull/1014)
- Add support for MetaOriginRevisionKey from the Event API
[#1018](https://github.com/fluxcd/notification-controller/pull/1018)
- Add subsection for Git providers supporting commit status updates
[#1019](https://github.com/fluxcd/notification-controller/pull/1019)
- Add support for Bearer Token authentication to Provider alertmanager
[#1021](https://github.com/fluxcd/notification-controller/pull/1021)
- Enforce namespace check on receiver
[#1022](https://github.com/fluxcd/notification-controller/pull/1022)
- Implement Receiver resource filtering with CEL
[#948](https://github.com/fluxcd/notification-controller/pull/948)
- Clarify gitlab provider usage
[#953](https://github.com/fluxcd/notification-controller/pull/953)
- Add involved object reference as annotations for the grafana provider
[#1040](https://github.com/fluxcd/notification-controller/pull/1040)
- Improvements after CEL resource filtering
[#1041](https://github.com/fluxcd/notification-controller/pull/1041)
- Various dependency updates
[#1002](https://github.com/fluxcd/notification-controller/pull/1002)
[#1016](https://github.com/fluxcd/notification-controller/pull/1016)
[#1023](https://github.com/fluxcd/notification-controller/pull/1023)
[#1025](https://github.com/fluxcd/notification-controller/pull/1025)
[#1027](https://github.com/fluxcd/notification-controller/pull/1027)
[#1032](https://github.com/fluxcd/notification-controller/pull/1032)
[#1036](https://github.com/fluxcd/notification-controller/pull/1036)
[#1037](https://github.com/fluxcd/notification-controller/pull/1037)
[#1042](https://github.com/fluxcd/notification-controller/pull/1042)
## 1.4.0
**Release date:** 2024-09-27
This minor release comes with various bug fixes and improvements.
MS Teams Provider has been updated to support MS Adaptive Card payloads.
This allows users to migrate from the deprecated
[Office 365 Connector for Incoming Webhooks](https://devblogs.microsoft.com/microsoft365dev/retirement-of-office-365-connectors-within-microsoft-teams/)
to the new [Microsoft Teams Incoming Webhooks with Workflows](https://support.microsoft.com/en-us/office/create-incoming-webhooks-with-workflows-for-microsoft-teams-8ae491c7-0394-4861-ba59-055e33f75498).
See the [Provider API documentation](https://fluxcd.io/flux/components/notification/providers/#microsoft-teams)
for more information. After getting the URL for the new Incoming Webhook Workflow,
update the secret used by the `msteams` Provider object with the new URL.
In addition, the Kubernetes dependencies have been updated to v1.31.1 and
various other controller dependencies have been updated to their latest
version. The controller is now built with Go 1.23.
Fixes:
- telegram notifier should escape with metadata key
[#829](https://github.com/fluxcd/notification-controller/pull/829)
- docs: use stringData for secret of GitHub PAT
[#873](https://github.com/fluxcd/notification-controller/pull/873)
- Fix incorrect use of format strings with the conditions package.
[#879](https://github.com/fluxcd/notification-controller/pull/879)
Improvements:
- New flag to disable detailed metrics for path
[#841](https://github.com/fluxcd/notification-controller/pull/841)
- Fix telegram test flake
[#894](https://github.com/fluxcd/notification-controller/pull/894)
- Build with Go 1.23
[#907](https://github.com/fluxcd/notification-controller/pull/907)
- Add MS Adaptive Card payload to msteams Provider
[#920](https://github.com/fluxcd/notification-controller/pull/920)
- Various dependency updates
[#845](https://github.com/fluxcd/notification-controller/pull/845)
[#855](https://github.com/fluxcd/notification-controller/pull/855)
[#854](https://github.com/fluxcd/notification-controller/pull/854)
[#857](https://github.com/fluxcd/notification-controller/pull/857)
[#865](https://github.com/fluxcd/notification-controller/pull/865)
[#866](https://github.com/fluxcd/notification-controller/pull/866)
[#905](https://github.com/fluxcd/notification-controller/pull/905)
[#903](https://github.com/fluxcd/notification-controller/pull/903)
[#912](https://github.com/fluxcd/notification-controller/pull/912)
[#925](https://github.com/fluxcd/notification-controller/pull/925)
[#931](https://github.com/fluxcd/notification-controller/pull/931)
[#932](https://github.com/fluxcd/notification-controller/pull/932)
[#933](https://github.com/fluxcd/notification-controller/pull/933)
[#934](https://github.com/fluxcd/notification-controller/pull/934)
## 1.3.0
**Release date:** 2024-05-06
This minor release comes with new features, improvements and bug fixes.
The `Receiver` API has been extended to support CDEvents,
for more information, please see the
[CDEvents Receiver API documentation](https://github.com/fluxcd/notification-controller/blob/release/v1.3.x/docs/spec/v1/receivers.md#cdevents).
Starting with this version, the controller allows grouping alerts for Alertmanager
by setting the `startsAt` label instead of `timestamp`. When sending alerts to
OpsGenie, the controller now sets the `severity` field to the alert's details.
In addition, the controller dependencies have been updated to Kubernetes v1.30
and controller-runtime v0.18. Various other dependencies have also been updated to
their latest version to patch upstream CVEs.
Lastly, the controller is now built with Go 1.22.
Improvements:
- Add CDEvent Receiver Support
[#772](https://github.com/fluxcd/notification-controller/pull/772)
- Add severity to opsgenie alerts
[#796](https://github.com/fluxcd/notification-controller/pull/796)
- Alertmanager: Change timestamp label to .StartsAt
[#795](https://github.com/fluxcd/notification-controller/pull/795)
- Use `password` as fallback for the Git provider `token` auth
[#790](https://github.com/fluxcd/notification-controller/pull/790)
- Add support for Bitbucket Context path
[#747](https://github.com/fluxcd/notification-controller/pull/747)
- Various dependency updates
[#816](https://github.com/fluxcd/notification-controller/pull/816)
[#814](https://github.com/fluxcd/notification-controller/pull/814)
[#813](https://github.com/fluxcd/notification-controller/pull/813)
[#810](https://github.com/fluxcd/notification-controller/pull/810)
[#809](https://github.com/fluxcd/notification-controller/pull/809)
[#787](https://github.com/fluxcd/notification-controller/pull/787)
[#783](https://github.com/fluxcd/notification-controller/pull/783)
[#763](https://github.com/fluxcd/notification-controller/pull/763)
Fixes:
- Sanitize provider data loaded from secret
[#789](https://github.com/fluxcd/notification-controller/pull/789)
- Fix timeout propagation for alerts
[#757](https://github.com/fluxcd/notification-controller/pull/757)
- Fix Telegram MarkdownV2 escaping
[#776](https://github.com/fluxcd/notification-controller/pull/776)
- Remove `genclient:Namespaced` tag
[#749](https://github.com/fluxcd/notification-controller/pull/749)
## 1.2.4
**Release date:** 2024-02-01
This patch release fixes various issues, updates the Kubernetes dependencies
to v1.28.6 and various other dependencies to their latest version to patch
upstream CVEs.
Improvements:
- Various dependency updates
[#727](https://github.com/fluxcd/notification-controller/pull/727)
[#726](https://github.com/fluxcd/notification-controller/pull/726)
[#721](https://github.com/fluxcd/notification-controller/pull/721)
[#718](https://github.com/fluxcd/notification-controller/pull/718)
[#707](https://github.com/fluxcd/notification-controller/pull/707)
[#695](https://github.com/fluxcd/notification-controller/pull/695)
Fixes:
- Fix BitBucket status update panic
[#722](https://github.com/fluxcd/notification-controller/pull/722)
- fix typo in docs/spec/v1beta3/providers.md
[#699](https://github.com/fluxcd/notification-controller/pull/699)
- fix(grafana-provider): replace ":" character in eventMetadata
[#703](https://github.com/fluxcd/notification-controller/pull/703)
- Remove old/incorrect API version usage
[#693](https://github.com/fluxcd/notification-controller/pull/693)
## 1.2.3
**Release date:** 2023-12-14
This patch release fixes various issues, most notably, the Provider v1beta3 API
backwards compatibility issue when `.spec.interval` was explicitly set in a
v1beta2 version of Provider.
Fixes:
- Exclude eventv1.MetaTokenKey from event metadata
[#686](https://github.com/fluxcd/notification-controller/pull/686)
- Add .spec.interval in v1beta3 Provider
[#683](https://github.com/fluxcd/notification-controller/pull/683)
- Remove URL syntax validation for provider address entirely
[#682](https://github.com/fluxcd/notification-controller/pull/682)
## 1.2.2
**Release date:** 2023-12-11
This patch releases updates a variety of dependencies, including an update of
the container base image to Alpine v3.19.
Improvements:
- build: update Alpine to 3.19
[#675](https://github.com/fluxcd/notification-controller/pull/675)
- Update dependencies
[#677](https://github.com/fluxcd/notification-controller/pull/677)
## 1.2.1
**Release date:** 2023-12-08
This patch release updates the Go version the controller is built with to
`1.21.x`, while mitigating recently published security vulnerabilities in the
`net/http` package.
In addition, it ensures static analyzers no longer detect a vulnerability in the
`whilp/git-urls` module by using `chainguard-dev/git-urls`. For which the
(potential) issue itself got already addressed internally in the [previous
v1.2.0 release](#120).
Lastly, a small number of dependencies got updated to their latest versions.
Improvements:
- Update Go to 1.21.x
[#666](https://github.com/fluxcd/notification-controller/pull/666)
- Replace whilp/git-urls module by chainguard-dev/git-urls
[#667](https://github.com/fluxcd/notification-controller/pull/667)
- Update dependencies
[#669](https://github.com/fluxcd/notification-controller/pull/669)
## 1.2.0
**Release date:** 2023-12-05
This minor release graduates the notification `Alert` and `Provider` APIs to
`v1beta3`. In addition, this version comes with alert Provider support for
[BitBucket
Server](https://github.com/fluxcd/notification-controller/blob/api/v1.2.0/docs/spec/v1beta3/providers.md#bitbucket-serverdata-center)
and
[NATS](https://github.com/fluxcd/notification-controller/blob/api/v1.2.0/docs/spec/v1beta3/providers.md#nats).
### `notification.toolkit.fluxcd.io/v1beta3`
After upgrading the controller to v1.2.0, please update the notification Custom
Resources for `Alert` and `Provider` in Git by replacing
`notification.toolkit.fluxcd.io/v1beta2` with
`notification.toolkit.fluxcd.io/v1beta3` in all the YAML manifests.
#### Static Alerts and Providers
The notification Alert and Provider API resources will become static objects
with configurations that will be used by the event handlers for processing the
respective incoming events. They will no longer be reconciled by a reconciler
and will not advertise any status. Once `Alerts` and `Providers` are created,
they can be considered ready. Users of
[kstatus](https://github.com/kubernetes-sigs/cli-utils/blob/master/pkg/kstatus/README.md)
shouldn't see any difference. Existing `Alerts` and `Providers` objects in
`v1beta2` API will undergo a one-time automatic migration to be converted into
static objects without any status.
#### Enhanced Alert events
The event handler will emit Kubernetes native events on the respective Alert
object for any relevant information, including failures due to any
misconfiguration.
Improvements:
- Add Provider for NATS Subject
[#651](https://github.com/fluxcd/notification-controller/pull/651)
- Cap provider address at 2048 bytes
[#654](https://github.com/fluxcd/notification-controller/pull/654)
- Refactor events and introduce v1beta3 API for Alert and Provider
[#540](https://github.com/fluxcd/notification-controller/pull/540)
- Add Bitbucket server/Bitbucket Data Center provider for git commit status
[#639](https://github.com/fluxcd/notification-controller/pull/639)
- Address miscellaneous issues throughout code base
[#627](https://github.com/fluxcd/notification-controller/pull/627)
- Update dependencies
[#609](https://github.com/fluxcd/notification-controller/pull/609)
[#612](https://github.com/fluxcd/notification-controller/pull/612)
[#613](https://github.com/fluxcd/notification-controller/pull/613)
[#617](https://github.com/fluxcd/notification-controller/pull/617)
[#621](https://github.com/fluxcd/notification-controller/pull/621)
[#623](https://github.com/fluxcd/notification-controller/pull/623)
[#628](https://github.com/fluxcd/notification-controller/pull/628)
[#629](https://github.com/fluxcd/notification-controller/pull/629)
[#632](https://github.com/fluxcd/notification-controller/pull/632)
[#635](https://github.com/fluxcd/notification-controller/pull/635)
[#637](https://github.com/fluxcd/notification-controller/pull/637)
[#641](https://github.com/fluxcd/notification-controller/pull/641)
[#643](https://github.com/fluxcd/notification-controller/pull/643)
[#646](https://github.com/fluxcd/notification-controller/pull/646)
[#648](https://github.com/fluxcd/notification-controller/pull/648)
[#652](https://github.com/fluxcd/notification-controller/pull/652)
[#656](https://github.com/fluxcd/notification-controller/pull/656)
[#657](https://github.com/fluxcd/notification-controller/pull/657)
Fixes:
- Fix README.md links to notification APIs
[#619](https://github.com/fluxcd/notification-controller/pull/619)
## 1.1.0
**Release date:** 2023-08-23

View File

@ -24,7 +24,7 @@ If any of the above dependencies are not present on your system, the first invoc
## How to run the test suite
Prerequisites:
- Go >= 1.17
- Go >= 1.24
You can run the test suite by simply doing:

View File

@ -1,9 +1,9 @@
ARG GO_VERSION=1.20
ARG XX_VERSION=1.2.1
ARG GO_VERSION=1.24
ARG XX_VERSION=1.6.1
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine as builder
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS builder
# Copy the build utilities.
COPY --from=xx / /
@ -30,7 +30,7 @@ COPY internal/ internal/
ENV CGO_ENABLED=0
RUN xx-go build -trimpath -a -o notification-controller main.go
FROM alpine:3.18
FROM alpine:3.21
ARG TARGETPLATFORM

View File

@ -7,4 +7,6 @@ as listed in
https://github.com/fluxcd/flux2/blob/main/MAINTAINERS
Somtochi Onyekwere, Weaveworks <somtochi@weave.works> (github: @SomtochiAma, slack: somtoxhi)
In alphabetical order:
Somtochi Onyekwere, Independent <somtochionyekwere@gmail.com> (github: @somtochiama, slack: somtochiama)

View File

@ -2,14 +2,14 @@
IMG ?= fluxcd/notification-controller:latest
# Produce CRDs that work back to Kubernetes 1.16
CRD_OPTIONS ?= crd:crdVersions=v1
SOURCE_VER ?= v1.0.0-rc.3
SOURCE_VER ?= v1.2.4
# Repository root based on Git metadata
REPOSITORY_ROOT := $(shell git rev-parse --show-toplevel)
BUILD_DIR := $(REPOSITORY_ROOT)/build
# API (doc) generation utilities
CONTROLLER_GEN_VERSION ?= v0.12.0
CONTROLLER_GEN_VERSION ?= v0.16.1
GEN_API_REF_DOCS_VERSION ?= e327d0730470cbd61b06300f81c5fcf91c23c113
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
@ -88,12 +88,13 @@ manifests: controller-gen
# Generate API reference documentation
api-docs: gen-crd-api-reference-docs
$(GEN_CRD_API_REFERENCE_DOCS) -api-dir=./api/v1beta2 -config=./hack/api-docs/config.json -template-dir=./hack/api-docs/template -out-file=./docs/api/v1beta2/notification.md
$(GEN_CRD_API_REFERENCE_DOCS) -api-dir=./api/v1beta3 -config=./hack/api-docs/config.json -template-dir=./hack/api-docs/template -out-file=./docs/api/v1beta3/notification.md
$(GEN_CRD_API_REFERENCE_DOCS) -api-dir=./api/v1 -config=./hack/api-docs/config.json -template-dir=./hack/api-docs/template -out-file=./docs/api/v1/notification.md
# Run go mod tidy
tidy:
cd api; rm -f go.sum; go mod tidy -compat=1.20
rm -f go.sum; go mod tidy -compat=1.20
cd api; rm -f go.sum; go mod tidy -compat=1.24
rm -f go.sum; go mod tidy -compat=1.24
# Run go fmt against code
fmt:
@ -152,13 +153,13 @@ fuzz-native:
./tests/fuzz/native_go_run.sh
# Find or download controller-gen
CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
CONTROLLER_GEN = $(GOBIN)/controller-gen
.PHONY: controller-gen
controller-gen: ## Download controller-gen locally if necessary.
$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_GEN_VERSION))
# Find or download gen-crd-api-reference-docs
GEN_CRD_API_REFERENCE_DOCS = $(shell pwd)/bin/gen-crd-api-reference-docs
GEN_CRD_API_REFERENCE_DOCS = $(GOBIN)/gen-crd-api-reference-docs
.PHONY: gen-crd-api-reference-docs
gen-crd-api-reference-docs:
$(call go-install-tool,$(GEN_CRD_API_REFERENCE_DOCS),github.com/ahmetb/gen-crd-api-reference-docs@$(GEN_API_REF_DOCS_VERSION))
@ -170,7 +171,7 @@ install-envtest: setup-envtest
mkdir -p ${ENVTEST_ASSETS_DIR}
$(ENVTEST) use $(ENVTEST_KUBERNETES_VERSION) --arch=$(ENVTEST_ARCH) --bin-dir=$(ENVTEST_ASSETS_DIR)
ENVTEST = $(shell pwd)/bin/setup-envtest
ENVTEST = $(GOBIN)/setup-envtest
.PHONY: envtest
setup-envtest: ## Download envtest-setup locally if necessary.
$(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest)
@ -184,7 +185,7 @@ TMP_DIR=$$(mktemp -d) ;\
cd $$TMP_DIR ;\
go mod init tmp ;\
echo "Downloading $(2)" ;\
GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\
GOBIN=$(GOBIN) go install $(2) ;\
rm -rf $$TMP_DIR ;\
}
endef

10
PROJECT
View File

@ -1,3 +1,7 @@
# Code generated by tool. DO NOT EDIT.
# This file is used to track the info used to scaffold your project
# and allow the plugins properly work.
# More info: https://book.kubebuilder.io/reference/project-config.html
domain: toolkit.fluxcd.io
repo: github.com/fluxcd/notification-controller
resources:
@ -22,4 +26,10 @@ resources:
- group: notification
kind: Receiver
version: v1beta2
- group: notification
kind: Provider
version: v1beta3
- group: notification
kind: Alert
version: v1beta3
version: "2"

View File

@ -7,7 +7,7 @@
[![release](https://img.shields.io/github/release/fluxcd/notification-controller/all.svg)](https://github.com/fluxcd/notification-controller/releases)
Event forwarder and notification dispatcher for the [GitOps Toolkit](https://fluxcd.io/flux/components/) controllers.
The notification-controller is an implementation of the [notification.toolkit.fluxcd.io](docs/spec/v1beta1/README.md)
The notification-controller is an implementation of the [notification.toolkit.fluxcd.io](docs/spec/v1beta3/README.md)
API based on the specifications described in the [RFC](docs/spec/README.md).
![overview](docs/diagrams/notification-controller-overview.png)

View File

@ -1,32 +1,35 @@
module github.com/fluxcd/notification-controller/api
go 1.20
go 1.24.0
require (
github.com/fluxcd/pkg/apis/meta v1.1.2
k8s.io/apimachinery v0.27.4
sigs.k8s.io/controller-runtime v0.15.1
github.com/fluxcd/pkg/apis/meta v1.18.0
k8s.io/apimachinery v0.33.2
sigs.k8s.io/controller-runtime v0.21.0
)
// Fix CVE-2022-28948
replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1
require (
github.com/go-logr/logr v1.2.4 // indirect
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/text v0.9.0 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/text v0.27.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
sigs.k8s.io/yaml v1.5.0 // indirect
)

View File

@ -2,19 +2,22 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fluxcd/pkg/apis/meta v1.1.2 h1:Unjo7hxadtB2dvGpeFqZZUdsjpRA08YYSBb7dF2WIAM=
github.com/fluxcd/pkg/apis/meta v1.1.2/go.mod h1:BHQyRHCskGMEDf6kDGbgQ+cyiNpUHbLsCOsaMYM2maI=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/fluxcd/pkg/apis/meta v1.18.0 h1:ACHrMIjlcioE9GKS7NGk62KX4NshqNewr8sBwMcXABs=
github.com/fluxcd/pkg/apis/meta v1.18.0/go.mod h1:97l3hTwBpJbXBY+wetNbqrUsvES8B1jGioKcBUxmqd8=
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@ -31,20 +34,28 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
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/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@ -54,24 +65,26 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -81,21 +94,25 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.8/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo=
k8s.io/apimachinery v0.27.4 h1:CdxflD4AF61yewuid0fLl6bM4a3q04jWel0IlP+aYjs=
k8s.io/apimachinery v0.27.4/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU=
k8s.io/utils v0.0.0-20230505201702-9f6742963106/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.15.1 h1:9UvgKD4ZJGcj24vefUFgZFP3xej/3igL9BsOUTb/+4c=
sigs.k8s.io/controller-runtime v0.15.1/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ=
sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4=

View File

@ -40,13 +40,14 @@ const (
GCRReceiver string = "gcr"
NexusReceiver string = "nexus"
ACRReceiver string = "acr"
CDEventsReceiver string = "cdevents"
)
// ReceiverSpec defines the desired state of the Receiver.
type ReceiverSpec struct {
// Type of webhook sender, used to determine
// the validation procedure and payload deserialization.
// +kubebuilder:validation:Enum=generic;generic-hmac;github;gitlab;bitbucket;harbor;dockerhub;quay;gcr;nexus;acr
// +kubebuilder:validation:Enum=generic;generic-hmac;github;gitlab;bitbucket;harbor;dockerhub;quay;gcr;nexus;acr;cdevents
// +required
Type string `json:"type"`
@ -66,6 +67,16 @@ type ReceiverSpec struct {
// +required
Resources []CrossNamespaceObjectReference `json:"resources"`
// ResourceFilter is a CEL expression expected to return a boolean that is
// evaluated for each resource referenced in the Resources field when a
// webhook is received. If the expression returns false then the controller
// will not request a reconciliation for the resource.
// When the expression is specified the controller will parse it and mark
// the object as terminally failed if the expression is invalid or does not
// return a boolean.
// +optional
ResourceFilter string `json:"resourceFilter,omitempty"`
// SecretRef specifies the Secret containing the token used
// to validate the payload authenticity.
// +required
@ -122,7 +133,6 @@ func (in *Receiver) GetInterval() time.Duration {
}
// +genclient
// +genclient:Namespaced
// +kubebuilder:storageversion
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

View File

@ -31,13 +31,13 @@ type CrossNamespaceObjectReference struct {
// Name of the referent
// If multiple resources are targeted `*` may be set.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=53
// +kubebuilder:validation:MaxLength=253
// +required
Name string `json:"name"`
// Namespace of the referent
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=53
// +kubebuilder:validation:MaxLength=253
// +kubebuilder:validation:Optional
// +optional
Namespace string `json:"namespace,omitempty"`

View File

@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2023 The Flux authors

View File

@ -67,12 +67,8 @@ type AlertStatus struct {
}
// +genclient
// +genclient:Namespaced
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description=""
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description=""
// +kubebuilder:skipversion
// Alert is the Schema for the alerts API
type Alert struct {

View File

@ -15,6 +15,9 @@ limitations under the License.
*/
// Package v1beta1 contains API Schema definitions for the notification v1beta1 API group
//
// Deprecated: v1beta1 is no longer supported, use v1 and v1beta3 instead.
//
// +kubebuilder:object:generate=true
// +groupName=notification.toolkit.fluxcd.io
package v1beta1

View File

@ -110,12 +110,8 @@ type ProviderStatus struct {
}
// +genclient
// +genclient:Namespaced
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description=""
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description=""
// +kubebuilder:skipversion
// Provider is the Schema for the providers API
type Provider struct {

View File

@ -97,13 +97,8 @@ func (in *Receiver) SetConditions(conditions []metav1.Condition) {
}
// +genclient
// +genclient:Namespaced
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:deprecatedversion:warning="v1beta1 Receiver is deprecated, upgrade to v1"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description=""
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description=""
// +kubebuilder:skipversion
// Receiver is the Schema for the receivers API
type Receiver struct {

View File

@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2023 The Flux authors

View File

@ -20,7 +20,7 @@ import (
"github.com/fluxcd/pkg/apis/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/fluxcd/notification-controller/api/v1"
v1 "github.com/fluxcd/notification-controller/api/v1"
)
const (
@ -88,10 +88,9 @@ type AlertStatus struct {
}
// +genclient
// +genclient:Namespaced
// +kubebuilder:storageversion
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:deprecatedversion:warning="v1beta2 Alert is deprecated, upgrade to v1beta3"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description=""
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description=""

View File

@ -24,38 +24,39 @@ import (
)
const (
ProviderKind string = "Provider"
GenericProvider string = "generic"
GenericHMACProvider string = "generic-hmac"
SlackProvider string = "slack"
GrafanaProvider string = "grafana"
DiscordProvider string = "discord"
MSTeamsProvider string = "msteams"
RocketProvider string = "rocket"
GitHubDispatchProvider string = "githubdispatch"
GitHubProvider string = "github"
GitLabProvider string = "gitlab"
GiteaProvider string = "gitea"
BitbucketProvider string = "bitbucket"
AzureDevOpsProvider string = "azuredevops"
GoogleChatProvider string = "googlechat"
GooglePubSubProvider string = "googlepubsub"
WebexProvider string = "webex"
SentryProvider string = "sentry"
AzureEventHubProvider string = "azureeventhub"
TelegramProvider string = "telegram"
LarkProvider string = "lark"
Matrix string = "matrix"
OpsgenieProvider string = "opsgenie"
AlertManagerProvider string = "alertmanager"
PagerDutyProvider string = "pagerduty"
DataDogProvider string = "datadog"
ProviderKind string = "Provider"
GenericProvider string = "generic"
GenericHMACProvider string = "generic-hmac"
SlackProvider string = "slack"
GrafanaProvider string = "grafana"
DiscordProvider string = "discord"
MSTeamsProvider string = "msteams"
RocketProvider string = "rocket"
GitHubDispatchProvider string = "githubdispatch"
GitHubProvider string = "github"
GitLabProvider string = "gitlab"
GiteaProvider string = "gitea"
BitbucketServerProvider string = "bitbucketserver"
BitbucketProvider string = "bitbucket"
AzureDevOpsProvider string = "azuredevops"
GoogleChatProvider string = "googlechat"
GooglePubSubProvider string = "googlepubsub"
WebexProvider string = "webex"
SentryProvider string = "sentry"
AzureEventHubProvider string = "azureeventhub"
TelegramProvider string = "telegram"
LarkProvider string = "lark"
Matrix string = "matrix"
OpsgenieProvider string = "opsgenie"
AlertManagerProvider string = "alertmanager"
PagerDutyProvider string = "pagerduty"
DataDogProvider string = "datadog"
)
// ProviderSpec defines the desired state of the Provider.
type ProviderSpec struct {
// Type specifies which Provider implementation to use.
// +kubebuilder:validation:Enum=slack;discord;msteams;rocket;generic;generic-hmac;github;gitlab;gitea;bitbucket;azuredevops;googlechat;googlepubsub;webex;sentry;azureeventhub;telegram;lark;matrix;opsgenie;alertmanager;grafana;githubdispatch;pagerduty;datadog
// +kubebuilder:validation:Enum=slack;discord;msteams;rocket;generic;generic-hmac;github;gitlab;gitea;bitbucketserver;bitbucket;azuredevops;googlechat;googlepubsub;webex;sentry;azureeventhub;telegram;lark;matrix;opsgenie;alertmanager;grafana;githubdispatch;pagerduty;datadog
// +required
Type string `json:"type"`
@ -130,10 +131,9 @@ type ProviderStatus struct {
}
// +genclient
// +genclient:Namespaced
// +kubebuilder:storageversion
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:deprecatedversion:warning="v1beta2 Provider is deprecated, upgrade to v1beta3"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description=""
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description=""

View File

@ -129,7 +129,6 @@ func (in *Receiver) GetInterval() time.Duration {
}
// +genclient
// +genclient:Namespaced
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:deprecatedversion:warning="v1beta2 Receiver is deprecated, upgrade to v1"

View File

@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2023 The Flux authors

104
api/v1beta3/alert_types.go Normal file
View File

@ -0,0 +1,104 @@
/*
Copyright 2023 The Flux authors
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 v1beta3
import (
"github.com/fluxcd/pkg/apis/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "github.com/fluxcd/notification-controller/api/v1"
)
const (
AlertKind string = "Alert"
)
// AlertSpec defines an alerting rule for events involving a list of objects.
type AlertSpec struct {
// ProviderRef specifies which Provider this Alert should use.
// +required
ProviderRef meta.LocalObjectReference `json:"providerRef"`
// EventSeverity specifies how to filter events based on severity.
// If set to 'info' no events will be filtered.
// +kubebuilder:validation:Enum=info;error
// +kubebuilder:default:=info
// +optional
EventSeverity string `json:"eventSeverity,omitempty"`
// EventSources specifies how to filter events based
// on the involved object kind, name and namespace.
// +required
EventSources []v1.CrossNamespaceObjectReference `json:"eventSources"`
// InclusionList specifies a list of Golang regular expressions
// to be used for including messages.
// +optional
InclusionList []string `json:"inclusionList,omitempty"`
// EventMetadata is an optional field for adding metadata to events dispatched by the
// controller. This can be used for enhancing the context of the event. If a field
// would override one already present on the original event as generated by the emitter,
// then the override doesn't happen, i.e. the original value is preserved, and an info
// log is printed.
// +optional
EventMetadata map[string]string `json:"eventMetadata,omitempty"`
// ExclusionList specifies a list of Golang regular expressions
// to be used for excluding messages.
// +optional
ExclusionList []string `json:"exclusionList,omitempty"`
// Summary holds a short description of the impact and affected cluster.
// Deprecated: Use EventMetadata instead.
//
// +kubebuilder:validation:MaxLength:=255
// +optional
// +deprecated
Summary string `json:"summary,omitempty"`
// Suspend tells the controller to suspend subsequent
// events handling for this Alert.
// +optional
Suspend bool `json:"suspend,omitempty"`
}
// +genclient
// +kubebuilder:storageversion
// +kubebuilder:object:root=true
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
// Alert is the Schema for the alerts API
type Alert struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec AlertSpec `json:"spec,omitempty"`
}
//+kubebuilder:object:root=true
// AlertList contains a list of Alert
type AlertList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Alert `json:"items"`
}
func init() {
SchemeBuilder.Register(&Alert{}, &AlertList{})
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2020 The Flux authors
Copyright 2023 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,16 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package notifier
import (
"context"
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
)
type NopNotifier struct{}
func (n *NopNotifier) Post(ctx context.Context, event eventv1.Event) error {
return nil
}
// Package v1beta3 contains API Schema definitions for the notification v1beta3 API group.
// +kubebuilder:object:generate=true
// +groupName=notification.toolkit.fluxcd.io
package v1beta3

View File

@ -0,0 +1,33 @@
/*
Copyright 2023 The Flux authors
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 v1beta3
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "notification.toolkit.fluxcd.io", Version: "v1beta3"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)

View File

@ -0,0 +1,199 @@
/*
Copyright 2023 The Flux authors
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 v1beta3
import (
"time"
"github.com/fluxcd/pkg/apis/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const (
ProviderKind string = "Provider"
GenericProvider string = "generic"
GenericHMACProvider string = "generic-hmac"
SlackProvider string = "slack"
GrafanaProvider string = "grafana"
DiscordProvider string = "discord"
MSTeamsProvider string = "msteams"
RocketProvider string = "rocket"
GitHubDispatchProvider string = "githubdispatch"
GitHubProvider string = "github"
GitLabProvider string = "gitlab"
GiteaProvider string = "gitea"
BitbucketServerProvider string = "bitbucketserver"
BitbucketProvider string = "bitbucket"
AzureDevOpsProvider string = "azuredevops"
GoogleChatProvider string = "googlechat"
GooglePubSubProvider string = "googlepubsub"
WebexProvider string = "webex"
SentryProvider string = "sentry"
AzureEventHubProvider string = "azureeventhub"
TelegramProvider string = "telegram"
LarkProvider string = "lark"
Matrix string = "matrix"
OpsgenieProvider string = "opsgenie"
AlertManagerProvider string = "alertmanager"
PagerDutyProvider string = "pagerduty"
DataDogProvider string = "datadog"
NATSProvider string = "nats"
)
// ProviderSpec defines the desired state of the Provider.
// +kubebuilder:validation:XValidation:rule="self.type == 'github' || self.type == 'gitlab' || self.type == 'gitea' || self.type == 'bitbucketserver' || self.type == 'bitbucket' || self.type == 'azuredevops' || !has(self.commitStatusExpr)", message="spec.commitStatusExpr is only supported for the 'github', 'gitlab', 'gitea', 'bitbucketserver', 'bitbucket', 'azuredevops' provider types"
type ProviderSpec struct {
// Type specifies which Provider implementation to use.
// +kubebuilder:validation:Enum=slack;discord;msteams;rocket;generic;generic-hmac;github;gitlab;gitea;bitbucketserver;bitbucket;azuredevops;googlechat;googlepubsub;webex;sentry;azureeventhub;telegram;lark;matrix;opsgenie;alertmanager;grafana;githubdispatch;pagerduty;datadog;nats
// +required
Type string `json:"type"`
// Interval at which to reconcile the Provider with its Secret references.
// Deprecated and not used in v1beta3.
//
// +kubebuilder:validation:Type=string
// +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$"
// +optional
// +deprecated
Interval *metav1.Duration `json:"interval,omitempty"`
// Channel specifies the destination channel where events should be posted.
// +kubebuilder:validation:MaxLength:=2048
// +optional
Channel string `json:"channel,omitempty"`
// Username specifies the name under which events are posted.
// +kubebuilder:validation:MaxLength:=2048
// +optional
Username string `json:"username,omitempty"`
// Address specifies the endpoint, in a generic sense, to where alerts are sent.
// What kind of endpoint depends on the specific Provider type being used.
// For the generic Provider, for example, this is an HTTP/S address.
// For other Provider types this could be a project ID or a namespace.
// +kubebuilder:validation:MaxLength:=2048
// +kubebuilder:validation:Optional
// +optional
Address string `json:"address,omitempty"`
// Timeout for sending alerts to the Provider.
// +kubebuilder:validation:Type=string
// +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m))+$"
// +optional
Timeout *metav1.Duration `json:"timeout,omitempty"`
// Proxy the HTTP/S address of the proxy server.
// Deprecated: Use ProxySecretRef instead. Will be removed in v1.
// +kubebuilder:validation:Pattern="^(http|https)://.*$"
// +kubebuilder:validation:MaxLength:=2048
// +kubebuilder:validation:Optional
// +optional
Proxy string `json:"proxy,omitempty"`
// ProxySecretRef specifies the Secret containing the proxy configuration
// for this Provider. The Secret should contain an 'address' key with the
// HTTP/S address of the proxy server. Optional 'username' and 'password'
// keys can be provided for proxy authentication.
// +optional
ProxySecretRef *meta.LocalObjectReference `json:"proxySecretRef,omitempty"`
// SecretRef specifies the Secret containing the authentication
// credentials for this Provider.
// +optional
SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"`
// ServiceAccountName is the name of the Kubernetes ServiceAccount used to
// authenticate with cloud provider services through workload identity.
// This enables multi-tenant authentication without storing static credentials.
//
// Supported provider types: azureeventhub, azuredevops, googlepubsub
//
// When specified, the controller will:
// 1. Create an OIDC token for the specified ServiceAccount
// 2. Exchange it for cloud provider credentials via STS
// 3. Use the obtained credentials for API authentication
//
// When unspecified, controller-level authentication is used (single-tenant).
//
// An error is thrown if static credentials are also defined in SecretRef.
// This field requires the ObjectLevelWorkloadIdentity feature gate to be enabled.
//
// +optional
ServiceAccountName string `json:"serviceAccountName,omitempty"`
// CertSecretRef specifies the Secret containing TLS certificates
// for secure communication.
//
// Supported configurations:
// - CA-only: Server authentication (provide ca.crt only)
// - mTLS: Mutual authentication (provide ca.crt + tls.crt + tls.key)
// - Client-only: Client authentication with system CA (provide tls.crt + tls.key only)
//
// Legacy keys "caFile", "certFile", "keyFile" are supported but deprecated. Use "ca.crt", "tls.crt", "tls.key" instead.
//
// +optional
CertSecretRef *meta.LocalObjectReference `json:"certSecretRef,omitempty"`
// Suspend tells the controller to suspend subsequent
// events handling for this Provider.
// +optional
Suspend bool `json:"suspend,omitempty"`
// CommitStatusExpr is a CEL expression that evaluates to a string value
// that can be used to generate a custom commit status message for use
// with eligible Provider types (github, gitlab, gitea, bitbucketserver,
// bitbucket, azuredevops). Supported variables are: event, provider,
// and alert.
// +optional
CommitStatusExpr string `json:"commitStatusExpr,omitempty"`
}
// +genclient
// +kubebuilder:storageversion
// +kubebuilder:object:root=true
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
// Provider is the Schema for the providers API
type Provider struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ProviderSpec `json:"spec,omitempty"`
}
//+kubebuilder:object:root=true
// ProviderList contains a list of Provider
type ProviderList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Provider `json:"items"`
}
func init() {
SchemeBuilder.Register(&Provider{}, &ProviderList{})
}
// GetTimeout returns the timeout value with a default of 15s for this Provider.
func (in *Provider) GetTimeout() time.Duration {
duration := 15 * time.Second
if in.Spec.Timeout != nil {
duration = in.Spec.Timeout.Duration
}
return duration
}

View File

@ -0,0 +1,224 @@
//go:build !ignore_autogenerated
/*
Copyright 2023 The Flux authors
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.
*/
// Code generated by controller-gen. DO NOT EDIT.
package v1beta3
import (
"github.com/fluxcd/notification-controller/api/v1"
"github.com/fluxcd/pkg/apis/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Alert) DeepCopyInto(out *Alert) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Alert.
func (in *Alert) DeepCopy() *Alert {
if in == nil {
return nil
}
out := new(Alert)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Alert) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AlertList) DeepCopyInto(out *AlertList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Alert, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlertList.
func (in *AlertList) DeepCopy() *AlertList {
if in == nil {
return nil
}
out := new(AlertList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AlertList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AlertSpec) DeepCopyInto(out *AlertSpec) {
*out = *in
out.ProviderRef = in.ProviderRef
if in.EventSources != nil {
in, out := &in.EventSources, &out.EventSources
*out = make([]v1.CrossNamespaceObjectReference, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.InclusionList != nil {
in, out := &in.InclusionList, &out.InclusionList
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.EventMetadata != nil {
in, out := &in.EventMetadata, &out.EventMetadata
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.ExclusionList != nil {
in, out := &in.ExclusionList, &out.ExclusionList
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlertSpec.
func (in *AlertSpec) DeepCopy() *AlertSpec {
if in == nil {
return nil
}
out := new(AlertSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Provider) DeepCopyInto(out *Provider) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Provider.
func (in *Provider) DeepCopy() *Provider {
if in == nil {
return nil
}
out := new(Provider)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Provider) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ProviderList) DeepCopyInto(out *ProviderList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Provider, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderList.
func (in *ProviderList) DeepCopy() *ProviderList {
if in == nil {
return nil
}
out := new(ProviderList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ProviderList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ProviderSpec) DeepCopyInto(out *ProviderSpec) {
*out = *in
if in.Interval != nil {
in, out := &in.Interval, &out.Interval
*out = new(metav1.Duration)
**out = **in
}
if in.Timeout != nil {
in, out := &in.Timeout, &out.Timeout
*out = new(metav1.Duration)
**out = **in
}
if in.ProxySecretRef != nil {
in, out := &in.ProxySecretRef, &out.ProxySecretRef
*out = new(meta.LocalObjectReference)
**out = **in
}
if in.SecretRef != nil {
in, out := &in.SecretRef, &out.SecretRef
*out = new(meta.LocalObjectReference)
**out = **in
}
if in.CertSecretRef != nil {
in, out := &in.CertSecretRef, &out.CertSecretRef
*out = new(meta.LocalObjectReference)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderSpec.
func (in *ProviderSpec) DeepCopy() *ProviderSpec {
if in == nil {
return nil
}
out := new(ProviderSpec)
in.DeepCopyInto(out)
return out
}

View File

@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.12.0
controller-gen.kubebuilder.io/version: v0.16.1
name: alerts.notification.toolkit.fluxcd.io
spec:
group: notification.toolkit.fluxcd.io
@ -24,214 +24,27 @@ spec:
- jsonPath: .status.conditions[?(@.type=="Ready")].message
name: Status
type: string
name: v1beta1
schema:
openAPIV3Schema:
description: Alert is the Schema for the alerts API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: AlertSpec defines an alerting rule for events involving a
list of objects
properties:
eventSeverity:
default: info
description: Filter events based on severity, defaults to ('info').
If set to 'info' no events will be filtered.
enum:
- info
- error
type: string
eventSources:
description: Filter events based on the involved objects.
items:
description: CrossNamespaceObjectReference contains enough information
to let you locate the typed referenced object at cluster level
properties:
apiVersion:
description: API version of the referent
type: string
kind:
description: Kind of the referent
enum:
- Bucket
- GitRepository
- Kustomization
- HelmRelease
- HelmChart
- HelmRepository
- ImageRepository
- ImagePolicy
- ImageUpdateAutomation
- OCIRepository
type: string
matchLabels:
additionalProperties:
type: string
description: MatchLabels is a map of {key,value} pairs. A single
{key,value} in the matchLabels map is equivalent to an element
of matchExpressions, whose key field is "key", the operator
is "In", and the values array contains only "value". The requirements
are ANDed.
type: object
name:
description: Name of the referent
maxLength: 53
minLength: 1
type: string
namespace:
description: Namespace of the referent
maxLength: 53
minLength: 1
type: string
required:
- name
type: object
type: array
exclusionList:
description: A list of Golang regular expressions to be used for excluding
messages.
items:
type: string
type: array
providerRef:
description: Send events using this provider.
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
summary:
description: Short description of the impact and affected cluster.
type: string
suspend:
description: This flag tells the controller to suspend subsequent
events dispatching. Defaults to false.
type: boolean
required:
- eventSources
- providerRef
type: object
status:
default:
observedGeneration: -1
description: AlertStatus defines the observed state of Alert
properties:
conditions:
items:
description: "Condition contains details for one aspect of the current
state of this API Resource. --- This struct is intended for direct
use as an array at the field path .status.conditions. For example,
\n type FooStatus struct{ // Represents the observations of a
foo's current state. // Known .status.conditions.type are: \"Available\",
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
// +listType=map // +listMapKey=type Conditions []metav1.Condition
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
observedGeneration:
description: ObservedGeneration is the last observed generation.
format: int64
type: integer
type: object
type: object
served: true
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .status.conditions[?(@.type=="Ready")].message
name: Status
type: string
deprecated: true
deprecationWarning: v1beta2 Alert is deprecated, upgrade to v1beta3
name: v1beta2
schema:
openAPIV3Schema:
description: Alert is the Schema for the alerts API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@ -242,27 +55,30 @@ spec:
eventMetadata:
additionalProperties:
type: string
description: EventMetadata is an optional field for adding metadata
to events dispatched by the controller. This can be used for enhancing
the context of the event. If a field would override one already
present on the original event as generated by the emitter, then
the override doesn't happen, i.e. the original value is preserved,
and an info log is printed.
description: |-
EventMetadata is an optional field for adding metadata to events dispatched by the
controller. This can be used for enhancing the context of the event. If a field
would override one already present on the original event as generated by the emitter,
then the override doesn't happen, i.e. the original value is preserved, and an info
log is printed.
type: object
eventSeverity:
default: info
description: EventSeverity specifies how to filter events based on
severity. If set to 'info' no events will be filtered.
description: |-
EventSeverity specifies how to filter events based on severity.
If set to 'info' no events will be filtered.
enum:
- info
- error
type: string
eventSources:
description: EventSources specifies how to filter events based on
the involved object kind, name and namespace.
description: |-
EventSources specifies how to filter events based
on the involved object kind, name and namespace.
items:
description: CrossNamespaceObjectReference contains enough information
to let you locate the typed referenced object at cluster level
description: |-
CrossNamespaceObjectReference contains enough information to let you locate the
typed referenced object at cluster level
properties:
apiVersion:
description: API version of the referent
@ -284,21 +100,22 @@ spec:
matchLabels:
additionalProperties:
type: string
description: MatchLabels is a map of {key,value} pairs. A single
{key,value} in the matchLabels map is equivalent to an element
of matchExpressions, whose key field is "key", the operator
is "In", and the values array contains only "value". The requirements
are ANDed. MatchLabels requires the name to be set to `*`.
description: |-
MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions, whose key field is "key", the
operator is "In", and the values array contains only "value". The requirements are ANDed.
MatchLabels requires the name to be set to `*`.
type: object
name:
description: Name of the referent If multiple resources are
targeted `*` may be set.
maxLength: 53
description: |-
Name of the referent
If multiple resources are targeted `*` may be set.
maxLength: 253
minLength: 1
type: string
namespace:
description: Namespace of the referent
maxLength: 53
maxLength: 253
minLength: 1
type: string
required:
@ -307,13 +124,15 @@ spec:
type: object
type: array
exclusionList:
description: ExclusionList specifies a list of Golang regular expressions
description: |-
ExclusionList specifies a list of Golang regular expressions
to be used for excluding messages.
items:
type: string
type: array
inclusionList:
description: InclusionList specifies a list of Golang regular expressions
description: |-
InclusionList specifies a list of Golang regular expressions
to be used for including messages.
items:
type: string
@ -334,8 +153,9 @@ spec:
maxLength: 255
type: string
suspend:
description: Suspend tells the controller to suspend subsequent events
handling for this Alert.
description: |-
Suspend tells the controller to suspend subsequent
events handling for this Alert.
type: boolean
required:
- eventSources
@ -349,43 +169,35 @@ spec:
conditions:
description: Conditions holds the conditions for the Alert.
items:
description: "Condition contains details for one aspect of the current
state of this API Resource. --- This struct is intended for direct
use as an array at the field path .status.conditions. For example,
\n type FooStatus struct{ // Represents the observations of a
foo's current state. // Known .status.conditions.type are: \"Available\",
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
// +listType=map // +listMapKey=type Conditions []metav1.Condition
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
@ -400,10 +212,6 @@ spec:
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
@ -416,9 +224,10 @@ spec:
type: object
type: array
lastHandledReconcileAt:
description: LastHandledReconcileAt holds the value of the most recent
reconcile request value, so a change of the annotation value can
be detected.
description: |-
LastHandledReconcileAt holds the value of the most recent
reconcile request value, so a change of the annotation value
can be detected.
type: string
observedGeneration:
description: ObservedGeneration is the last observed generation.
@ -427,6 +236,150 @@ spec:
type: object
type: object
served: true
storage: true
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1beta3
schema:
openAPIV3Schema:
description: Alert is the Schema for the alerts API
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: AlertSpec defines an alerting rule for events involving a
list of objects.
properties:
eventMetadata:
additionalProperties:
type: string
description: |-
EventMetadata is an optional field for adding metadata to events dispatched by the
controller. This can be used for enhancing the context of the event. If a field
would override one already present on the original event as generated by the emitter,
then the override doesn't happen, i.e. the original value is preserved, and an info
log is printed.
type: object
eventSeverity:
default: info
description: |-
EventSeverity specifies how to filter events based on severity.
If set to 'info' no events will be filtered.
enum:
- info
- error
type: string
eventSources:
description: |-
EventSources specifies how to filter events based
on the involved object kind, name and namespace.
items:
description: |-
CrossNamespaceObjectReference contains enough information to let you locate the
typed referenced object at cluster level
properties:
apiVersion:
description: API version of the referent
type: string
kind:
description: Kind of the referent
enum:
- Bucket
- GitRepository
- Kustomization
- HelmRelease
- HelmChart
- HelmRepository
- ImageRepository
- ImagePolicy
- ImageUpdateAutomation
- OCIRepository
type: string
matchLabels:
additionalProperties:
type: string
description: |-
MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions, whose key field is "key", the
operator is "In", and the values array contains only "value". The requirements are ANDed.
MatchLabels requires the name to be set to `*`.
type: object
name:
description: |-
Name of the referent
If multiple resources are targeted `*` may be set.
maxLength: 253
minLength: 1
type: string
namespace:
description: Namespace of the referent
maxLength: 253
minLength: 1
type: string
required:
- kind
- name
type: object
type: array
exclusionList:
description: |-
ExclusionList specifies a list of Golang regular expressions
to be used for excluding messages.
items:
type: string
type: array
inclusionList:
description: |-
InclusionList specifies a list of Golang regular expressions
to be used for including messages.
items:
type: string
type: array
providerRef:
description: ProviderRef specifies which Provider this Alert should
use.
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
summary:
description: |-
Summary holds a short description of the impact and affected cluster.
Deprecated: Use EventMetadata instead.
maxLength: 255
type: string
suspend:
description: |-
Suspend tells the controller to suspend subsequent
events handling for this Alert.
type: boolean
required:
- eventSources
- providerRef
type: object
type: object
served: true
storage: true
subresources: {}

View File

@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.12.0
controller-gen.kubebuilder.io/version: v0.16.1
name: providers.notification.toolkit.fluxcd.io
spec:
group: notification.toolkit.fluxcd.io
@ -24,203 +24,27 @@ spec:
- jsonPath: .status.conditions[?(@.type=="Ready")].message
name: Status
type: string
name: v1beta1
schema:
openAPIV3Schema:
description: Provider is the Schema for the providers API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ProviderSpec defines the desired state of Provider
properties:
address:
description: HTTP/S webhook address of this provider
pattern: ^(http|https)://
type: string
certSecretRef:
description: CertSecretRef can be given the name of a secret containing
a PEM-encoded CA certificate (`caFile`)
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
channel:
description: Alert channel for this provider
type: string
proxy:
description: HTTP/S address of the proxy
pattern: ^(http|https)://
type: string
secretRef:
description: Secret reference containing the provider webhook URL
using "address" as data key
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
suspend:
description: This flag tells the controller to suspend subsequent
events handling. Defaults to false.
type: boolean
timeout:
description: Timeout for sending alerts to the provider.
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$
type: string
type:
description: Type of provider
enum:
- slack
- discord
- msteams
- rocket
- generic
- generic-hmac
- github
- gitlab
- bitbucket
- azuredevops
- googlechat
- webex
- sentry
- azureeventhub
- telegram
- lark
- matrix
- opsgenie
- alertmanager
- grafana
- githubdispatch
type: string
username:
description: Bot username for this provider
type: string
required:
- type
type: object
status:
default:
observedGeneration: -1
description: ProviderStatus defines the observed state of Provider
properties:
conditions:
items:
description: "Condition contains details for one aspect of the current
state of this API Resource. --- This struct is intended for direct
use as an array at the field path .status.conditions. For example,
\n type FooStatus struct{ // Represents the observations of a
foo's current state. // Known .status.conditions.type are: \"Available\",
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
// +listType=map // +listMapKey=type Conditions []metav1.Condition
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
observedGeneration:
description: ObservedGeneration is the last reconciled generation.
format: int64
type: integer
type: object
type: object
served: true
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .status.conditions[?(@.type=="Ready")].message
name: Status
type: string
deprecated: true
deprecationWarning: v1beta2 Provider is deprecated, upgrade to v1beta3
name: v1beta2
schema:
openAPIV3Schema:
description: Provider is the Schema for the providers API.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@ -228,17 +52,20 @@ spec:
description: ProviderSpec defines the desired state of the Provider.
properties:
address:
description: Address specifies the endpoint, in a generic sense, to
where alerts are sent. What kind of endpoint depends on the specific
Provider type being used. For the generic Provider, for example,
this is an HTTP/S address. For other Provider types this could be
a project ID or a namespace.
description: |-
Address specifies the endpoint, in a generic sense, to where alerts are sent.
What kind of endpoint depends on the specific Provider type being used.
For the generic Provider, for example, this is an HTTP/S address.
For other Provider types this could be a project ID or a namespace.
maxLength: 2048
type: string
certSecretRef:
description: "CertSecretRef specifies the Secret containing a PEM-encoded
CA certificate (in the `ca.crt` key). \n Note: Support for the `caFile`
key has been deprecated."
description: |-
CertSecretRef specifies the Secret containing
a PEM-encoded CA certificate (in the `ca.crt` key).
Note: Support for the `caFile` key has
been deprecated.
properties:
name:
description: Name of the referent.
@ -262,7 +89,8 @@ spec:
pattern: ^(http|https)://.*$
type: string
secretRef:
description: SecretRef specifies the Secret containing the authentication
description: |-
SecretRef specifies the Secret containing the authentication
credentials for this Provider.
properties:
name:
@ -272,8 +100,9 @@ spec:
- name
type: object
suspend:
description: Suspend tells the controller to suspend subsequent events
handling for this Provider.
description: |-
Suspend tells the controller to suspend subsequent
events handling for this Provider.
type: boolean
timeout:
description: Timeout for sending alerts to the Provider.
@ -291,6 +120,7 @@ spec:
- github
- gitlab
- gitea
- bitbucketserver
- bitbucket
- azuredevops
- googlechat
@ -323,43 +153,35 @@ spec:
conditions:
description: Conditions holds the conditions for the Provider.
items:
description: "Condition contains details for one aspect of the current
state of this API Resource. --- This struct is intended for direct
use as an array at the field path .status.conditions. For example,
\n type FooStatus struct{ // Represents the observations of a
foo's current state. // Known .status.conditions.type are: \"Available\",
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
// +listType=map // +listMapKey=type Conditions []metav1.Condition
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
@ -374,10 +196,6 @@ spec:
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
@ -390,9 +208,10 @@ spec:
type: object
type: array
lastHandledReconcileAt:
description: LastHandledReconcileAt holds the value of the most recent
reconcile request value, so a change of the annotation value can
be detected.
description: |-
LastHandledReconcileAt holds the value of the most recent
reconcile request value, so a change of the annotation value
can be detected.
type: string
observedGeneration:
description: ObservedGeneration is the last reconciled generation.
@ -401,6 +220,186 @@ spec:
type: object
type: object
served: true
storage: true
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1beta3
schema:
openAPIV3Schema:
description: Provider is the Schema for the providers API
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: ProviderSpec defines the desired state of the Provider.
properties:
address:
description: |-
Address specifies the endpoint, in a generic sense, to where alerts are sent.
What kind of endpoint depends on the specific Provider type being used.
For the generic Provider, for example, this is an HTTP/S address.
For other Provider types this could be a project ID or a namespace.
maxLength: 2048
type: string
certSecretRef:
description: |-
CertSecretRef specifies the Secret containing TLS certificates
for secure communication.
Supported configurations:
- CA-only: Server authentication (provide ca.crt only)
- mTLS: Mutual authentication (provide ca.crt + tls.crt + tls.key)
- Client-only: Client authentication with system CA (provide tls.crt + tls.key only)
Legacy keys "caFile", "certFile", "keyFile" are supported but deprecated. Use "ca.crt", "tls.crt", "tls.key" instead.
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
channel:
description: Channel specifies the destination channel where events
should be posted.
maxLength: 2048
type: string
commitStatusExpr:
description: |-
CommitStatusExpr is a CEL expression that evaluates to a string value
that can be used to generate a custom commit status message for use
with eligible Provider types (github, gitlab, gitea, bitbucketserver,
bitbucket, azuredevops). Supported variables are: event, provider,
and alert.
type: string
interval:
description: |-
Interval at which to reconcile the Provider with its Secret references.
Deprecated and not used in v1beta3.
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$
type: string
proxy:
description: |-
Proxy the HTTP/S address of the proxy server.
Deprecated: Use ProxySecretRef instead. Will be removed in v1.
maxLength: 2048
pattern: ^(http|https)://.*$
type: string
proxySecretRef:
description: |-
ProxySecretRef specifies the Secret containing the proxy configuration
for this Provider. The Secret should contain an 'address' key with the
HTTP/S address of the proxy server. Optional 'username' and 'password'
keys can be provided for proxy authentication.
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
secretRef:
description: |-
SecretRef specifies the Secret containing the authentication
credentials for this Provider.
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
serviceAccountName:
description: |-
ServiceAccountName is the name of the Kubernetes ServiceAccount used to
authenticate with cloud provider services through workload identity.
This enables multi-tenant authentication without storing static credentials.
Supported provider types: azureeventhub, azuredevops, googlepubsub
When specified, the controller will:
1. Create an OIDC token for the specified ServiceAccount
2. Exchange it for cloud provider credentials via STS
3. Use the obtained credentials for API authentication
When unspecified, controller-level authentication is used (single-tenant).
An error is thrown if static credentials are also defined in SecretRef.
This field requires the ObjectLevelWorkloadIdentity feature gate to be enabled.
type: string
suspend:
description: |-
Suspend tells the controller to suspend subsequent
events handling for this Provider.
type: boolean
timeout:
description: Timeout for sending alerts to the Provider.
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$
type: string
type:
description: Type specifies which Provider implementation to use.
enum:
- slack
- discord
- msteams
- rocket
- generic
- generic-hmac
- github
- gitlab
- gitea
- bitbucketserver
- bitbucket
- azuredevops
- googlechat
- googlepubsub
- webex
- sentry
- azureeventhub
- telegram
- lark
- matrix
- opsgenie
- alertmanager
- grafana
- githubdispatch
- pagerduty
- datadog
- nats
type: string
username:
description: Username specifies the name under which events are posted.
maxLength: 2048
type: string
required:
- type
type: object
x-kubernetes-validations:
- message: spec.commitStatusExpr is only supported for the 'github', 'gitlab',
'gitea', 'bitbucketserver', 'bitbucket', 'azuredevops' provider types
rule: self.type == 'github' || self.type == 'gitlab' || self.type ==
'gitea' || self.type == 'bitbucketserver' || self.type == 'bitbucket'
|| self.type == 'azuredevops' || !has(self.commitStatusExpr)
type: object
served: true
storage: true
subresources: {}

View File

@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.12.0
controller-gen.kubebuilder.io/version: v0.16.1
name: receivers.notification.toolkit.fluxcd.io
spec:
group: notification.toolkit.fluxcd.io
@ -30,14 +30,19 @@ spec:
description: Receiver is the Schema for the receivers API.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@ -45,8 +50,9 @@ spec:
description: ReceiverSpec defines the desired state of the Receiver.
properties:
events:
description: Events specifies the list of event types to handle, e.g.
'push' for GitHub or 'Push Hook' for GitLab.
description: |-
Events specifies the list of event types to handle,
e.g. 'push' for GitHub or 'Push Hook' for GitLab.
items:
type: string
type: array
@ -56,11 +62,22 @@ spec:
Secret references.
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$
type: string
resourceFilter:
description: |-
ResourceFilter is a CEL expression expected to return a boolean that is
evaluated for each resource referenced in the Resources field when a
webhook is received. If the expression returns false then the controller
will not request a reconciliation for the resource.
When the expression is specified the controller will parse it and mark
the object as terminally failed if the expression is invalid or does not
return a boolean.
type: string
resources:
description: A list of resources to be notified about changes.
items:
description: CrossNamespaceObjectReference contains enough information
to let you locate the typed referenced object at cluster level
description: |-
CrossNamespaceObjectReference contains enough information to let you locate the
typed referenced object at cluster level
properties:
apiVersion:
description: API version of the referent
@ -82,21 +99,22 @@ spec:
matchLabels:
additionalProperties:
type: string
description: MatchLabels is a map of {key,value} pairs. A single
{key,value} in the matchLabels map is equivalent to an element
of matchExpressions, whose key field is "key", the operator
is "In", and the values array contains only "value". The requirements
are ANDed. MatchLabels requires the name to be set to `*`.
description: |-
MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions, whose key field is "key", the
operator is "In", and the values array contains only "value". The requirements are ANDed.
MatchLabels requires the name to be set to `*`.
type: object
name:
description: Name of the referent If multiple resources are
targeted `*` may be set.
maxLength: 53
description: |-
Name of the referent
If multiple resources are targeted `*` may be set.
maxLength: 253
minLength: 1
type: string
namespace:
description: Namespace of the referent
maxLength: 53
maxLength: 253
minLength: 1
type: string
required:
@ -105,7 +123,8 @@ spec:
type: object
type: array
secretRef:
description: SecretRef specifies the Secret containing the token used
description: |-
SecretRef specifies the Secret containing the token used
to validate the payload authenticity.
properties:
name:
@ -115,12 +134,236 @@ spec:
- name
type: object
suspend:
description: Suspend tells the controller to suspend subsequent events
handling for this receiver.
description: |-
Suspend tells the controller to suspend subsequent
events handling for this receiver.
type: boolean
type:
description: Type of webhook sender, used to determine the validation
procedure and payload deserialization.
description: |-
Type of webhook sender, used to determine
the validation procedure and payload deserialization.
enum:
- generic
- generic-hmac
- github
- gitlab
- bitbucket
- harbor
- dockerhub
- quay
- gcr
- nexus
- acr
- cdevents
type: string
required:
- resources
- secretRef
- type
type: object
status:
default:
observedGeneration: -1
description: ReceiverStatus defines the observed state of the Receiver.
properties:
conditions:
description: Conditions holds the conditions for the Receiver.
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
lastHandledReconcileAt:
description: |-
LastHandledReconcileAt holds the value of the most recent
reconcile request value, so a change of the annotation value
can be detected.
type: string
observedGeneration:
description: ObservedGeneration is the last observed generation of
the Receiver object.
format: int64
type: integer
webhookPath:
description: |-
WebhookPath is the generated incoming webhook address in the format
of '/hook/sha256sum(token+name+namespace)'.
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .status.conditions[?(@.type=="Ready")].message
name: Status
type: string
deprecated: true
deprecationWarning: v1beta2 Receiver is deprecated, upgrade to v1
name: v1beta2
schema:
openAPIV3Schema:
description: Receiver is the Schema for the receivers API.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: ReceiverSpec defines the desired state of the Receiver.
properties:
events:
description: |-
Events specifies the list of event types to handle,
e.g. 'push' for GitHub or 'Push Hook' for GitLab.
items:
type: string
type: array
interval:
description: Interval at which to reconcile the Receiver with its
Secret references.
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$
type: string
resources:
description: A list of resources to be notified about changes.
items:
description: |-
CrossNamespaceObjectReference contains enough information to let you locate the
typed referenced object at cluster level
properties:
apiVersion:
description: API version of the referent
type: string
kind:
description: Kind of the referent
enum:
- Bucket
- GitRepository
- Kustomization
- HelmRelease
- HelmChart
- HelmRepository
- ImageRepository
- ImagePolicy
- ImageUpdateAutomation
- OCIRepository
type: string
matchLabels:
additionalProperties:
type: string
description: |-
MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions, whose key field is "key", the
operator is "In", and the values array contains only "value". The requirements are ANDed.
MatchLabels requires the name to be set to `*`.
type: object
name:
description: |-
Name of the referent
If multiple resources are targeted `*` may be set.
maxLength: 253
minLength: 1
type: string
namespace:
description: Namespace of the referent
maxLength: 253
minLength: 1
type: string
required:
- kind
- name
type: object
type: array
secretRef:
description: |-
SecretRef specifies the Secret containing the token used
to validate the payload authenticity.
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
suspend:
description: |-
Suspend tells the controller to suspend subsequent
events handling for this receiver.
type: boolean
type:
description: |-
Type of webhook sender, used to determine
the validation procedure and payload deserialization.
enum:
- generic
- generic-hmac
@ -147,43 +390,35 @@ spec:
conditions:
description: Conditions holds the conditions for the Receiver.
items:
description: "Condition contains details for one aspect of the current
state of this API Resource. --- This struct is intended for direct
use as an array at the field path .status.conditions. For example,
\n type FooStatus struct{ // Represents the observations of a
foo's current state. // Known .status.conditions.type are: \"Available\",
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
// +listType=map // +listMapKey=type Conditions []metav1.Condition
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
@ -198,10 +433,6 @@ spec:
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
@ -214,432 +445,10 @@ spec:
type: object
type: array
lastHandledReconcileAt:
description: LastHandledReconcileAt holds the value of the most recent
reconcile request value, so a change of the annotation value can
be detected.
type: string
observedGeneration:
description: ObservedGeneration is the last observed generation of
the Receiver object.
format: int64
type: integer
webhookPath:
description: WebhookPath is the generated incoming webhook address
in the format of '/hook/sha256sum(token+name+namespace)'.
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .status.conditions[?(@.type=="Ready")].message
name: Status
type: string
deprecated: true
deprecationWarning: v1beta1 Receiver is deprecated, upgrade to v1
name: v1beta1
schema:
openAPIV3Schema:
description: Receiver is the Schema for the receivers API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ReceiverSpec defines the desired state of Receiver
properties:
events:
description: A list of events to handle, e.g. 'push' for GitHub or
'Push Hook' for GitLab.
items:
type: string
type: array
resources:
description: A list of resources to be notified about changes.
items:
description: CrossNamespaceObjectReference contains enough information
to let you locate the typed referenced object at cluster level
properties:
apiVersion:
description: API version of the referent
type: string
kind:
description: Kind of the referent
enum:
- Bucket
- GitRepository
- Kustomization
- HelmRelease
- HelmChart
- HelmRepository
- ImageRepository
- ImagePolicy
- ImageUpdateAutomation
- OCIRepository
type: string
matchLabels:
additionalProperties:
type: string
description: MatchLabels is a map of {key,value} pairs. A single
{key,value} in the matchLabels map is equivalent to an element
of matchExpressions, whose key field is "key", the operator
is "In", and the values array contains only "value". The requirements
are ANDed.
type: object
name:
description: Name of the referent
maxLength: 53
minLength: 1
type: string
namespace:
description: Namespace of the referent
maxLength: 53
minLength: 1
type: string
required:
- name
type: object
type: array
secretRef:
description: Secret reference containing the token used to validate
the payload authenticity
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
suspend:
description: This flag tells the controller to suspend subsequent
events handling. Defaults to false.
type: boolean
type:
description: Type of webhook sender, used to determine the validation
procedure and payload deserialization.
enum:
- generic
- generic-hmac
- github
- gitlab
- bitbucket
- harbor
- dockerhub
- quay
- gcr
- nexus
- acr
type: string
required:
- resources
- type
type: object
status:
default:
observedGeneration: -1
description: ReceiverStatus defines the observed state of Receiver
properties:
conditions:
items:
description: "Condition contains details for one aspect of the current
state of this API Resource. --- This struct is intended for direct
use as an array at the field path .status.conditions. For example,
\n type FooStatus struct{ // Represents the observations of a
foo's current state. // Known .status.conditions.type are: \"Available\",
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
// +listType=map // +listMapKey=type Conditions []metav1.Condition
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
observedGeneration:
description: ObservedGeneration is the last observed generation.
format: int64
type: integer
url:
description: Generated webhook URL in the format of '/hook/sha256sum(token+name+namespace)'.
type: string
type: object
type: object
served: true
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .status.conditions[?(@.type=="Ready")].message
name: Status
type: string
deprecated: true
deprecationWarning: v1beta2 Receiver is deprecated, upgrade to v1
name: v1beta2
schema:
openAPIV3Schema:
description: Receiver is the Schema for the receivers API.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ReceiverSpec defines the desired state of the Receiver.
properties:
events:
description: Events specifies the list of event types to handle, e.g.
'push' for GitHub or 'Push Hook' for GitLab.
items:
type: string
type: array
interval:
description: Interval at which to reconcile the Receiver with its
Secret references.
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$
type: string
resources:
description: A list of resources to be notified about changes.
items:
description: CrossNamespaceObjectReference contains enough information
to let you locate the typed referenced object at cluster level
properties:
apiVersion:
description: API version of the referent
type: string
kind:
description: Kind of the referent
enum:
- Bucket
- GitRepository
- Kustomization
- HelmRelease
- HelmChart
- HelmRepository
- ImageRepository
- ImagePolicy
- ImageUpdateAutomation
- OCIRepository
type: string
matchLabels:
additionalProperties:
type: string
description: MatchLabels is a map of {key,value} pairs. A single
{key,value} in the matchLabels map is equivalent to an element
of matchExpressions, whose key field is "key", the operator
is "In", and the values array contains only "value". The requirements
are ANDed. MatchLabels requires the name to be set to `*`.
type: object
name:
description: Name of the referent If multiple resources are
targeted `*` may be set.
maxLength: 53
minLength: 1
type: string
namespace:
description: Namespace of the referent
maxLength: 53
minLength: 1
type: string
required:
- kind
- name
type: object
type: array
secretRef:
description: SecretRef specifies the Secret containing the token used
to validate the payload authenticity.
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
suspend:
description: Suspend tells the controller to suspend subsequent events
handling for this receiver.
type: boolean
type:
description: Type of webhook sender, used to determine the validation
procedure and payload deserialization.
enum:
- generic
- generic-hmac
- github
- gitlab
- bitbucket
- harbor
- dockerhub
- quay
- gcr
- nexus
- acr
type: string
required:
- resources
- type
type: object
status:
default:
observedGeneration: -1
description: ReceiverStatus defines the observed state of the Receiver.
properties:
conditions:
description: Conditions holds the conditions for the Receiver.
items:
description: "Condition contains details for one aspect of the current
state of this API Resource. --- This struct is intended for direct
use as an array at the field path .status.conditions. For example,
\n type FooStatus struct{ // Represents the observations of a
foo's current state. // Known .status.conditions.type are: \"Available\",
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
// +listType=map // +listMapKey=type Conditions []metav1.Condition
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
lastHandledReconcileAt:
description: LastHandledReconcileAt holds the value of the most recent
reconcile request value, so a change of the annotation value can
be detected.
description: |-
LastHandledReconcileAt holds the value of the most recent
reconcile request value, so a change of the annotation value
can be detected.
type: string
observedGeneration:
description: ObservedGeneration is the last observed generation of
@ -647,13 +456,15 @@ spec:
format: int64
type: integer
url:
description: 'URL is the generated incoming webhook address in the
format of ''/hook/sha256sum(token+name+namespace)''. Deprecated:
Replaced by WebhookPath.'
description: |-
URL is the generated incoming webhook address in the format
of '/hook/sha256sum(token+name+namespace)'.
Deprecated: Replaced by WebhookPath.
type: string
webhookPath:
description: WebhookPath is the generated incoming webhook address
in the format of '/hook/sha256sum(token+name+namespace)'.
description: |-
WebhookPath is the generated incoming webhook address in the format
of '/hook/sha256sum(token+name+namespace)'.
type: string
type: object
type: object

View File

@ -6,4 +6,4 @@ resources:
images:
- name: fluxcd/notification-controller
newName: fluxcd/notification-controller
newTag: v1.1.0
newTag: v1.6.0

View File

@ -19,6 +19,12 @@ rules:
- get
- list
- watch
- apiGroups:
- ""
resources:
- serviceaccounts/token
verbs:
- create
- apiGroups:
- image.fluxcd.io
resources:
@ -39,45 +45,7 @@ rules:
- notification.toolkit.fluxcd.io
resources:
- alerts
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- notification.toolkit.fluxcd.io
resources:
- alerts/status
verbs:
- get
- patch
- update
- apiGroups:
- notification.toolkit.fluxcd.io
resources:
- providers
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- notification.toolkit.fluxcd.io
resources:
- providers/status
verbs:
- get
- patch
- update
- apiGroups:
- notification.toolkit.fluxcd.io
resources:
- receivers
verbs:
- create
@ -99,53 +67,8 @@ rules:
- source.fluxcd.io
resources:
- buckets
verbs:
- get
- list
- patch
- update
- watch
- apiGroups:
- source.fluxcd.io
resources:
- buckets/status
verbs:
- get
- apiGroups:
- source.fluxcd.io
resources:
- gitrepositories
verbs:
- get
- list
- patch
- update
- watch
- apiGroups:
- source.fluxcd.io
resources:
- gitrepositories/status
verbs:
- get
- apiGroups:
- source.fluxcd.io
resources:
- helmrepositories
verbs:
- get
- list
- patch
- update
- watch
- apiGroups:
- source.fluxcd.io
resources:
- helmrepositories/status
verbs:
- get
- apiGroups:
- source.fluxcd.io
resources:
- ocirepositories
verbs:
- get
@ -156,6 +79,9 @@ rules:
- apiGroups:
- source.fluxcd.io
resources:
- buckets/status
- gitrepositories/status
- helmrepositories/status
- ocirepositories/status
verbs:
- get

View File

@ -0,0 +1,13 @@
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: alert-sample
spec:
providerRef:
name: slack-provider-sample
eventSeverity: info
eventSources:
- kind: GitRepository
name: '*'
- kind: Kustomization
name: '*'

View File

@ -0,0 +1,34 @@
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
name: slack-provider-sample
spec:
type: slack
channel: general
secretRef:
name: slack-url
---
apiVersion: v1
kind: Secret
metadata:
name: slack-url
data:
address: aHR0cHM6Ly9ob29rcy5zbGFjay5jb20vc2VydmljZXMv
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
name: generic-provider-sample
spec:
type: generic
address: https://api.github.com/repos/fluxcd/notification-controller/dispatches
secretRef:
name: generic-secret
---
apiVersion: v1
kind: Secret
metadata:
name: generic-secret
stringData:
headers: |
Authorization: token

View File

@ -1,8 +0,0 @@
---
apiVersion: notification.toolkit.fluxcd.io/v1beta1
kind: Provider
metadata:
name: status-defaults
spec:
type: generic

View File

@ -1,5 +0,0 @@
---
apiVersion: notification.toolkit.fluxcd.io/v1beta1
kind: Alert
metadata:
name: status-defaults

View File

@ -1,4 +0,0 @@
apiVersion: notification.toolkit.fluxcd.io/v1beta1
kind: Provider
metadata:
name: status-defaults

View File

@ -122,6 +122,24 @@ e.g. &lsquo;push&rsquo; for GitHub or &lsquo;Push Hook&rsquo; for GitLab.</p>
</tr>
<tr>
<td>
<code>resourceFilter</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>ResourceFilter is a CEL expression expected to return a boolean that is
evaluated for each resource referenced in the Resources field when a
webhook is received. If the expression returns false then the controller
will not request a reconciliation for the resource.
When the expression is specified the controller will parse it and mark
the object as terminally failed if the expression is invalid or does not
return a boolean.</p>
</td>
</tr>
<tr>
<td>
<code>secretRef</code><br>
<em>
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
@ -321,6 +339,24 @@ e.g. &lsquo;push&rsquo; for GitHub or &lsquo;Push Hook&rsquo; for GitLab.</p>
</tr>
<tr>
<td>
<code>resourceFilter</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>ResourceFilter is a CEL expression expected to return a boolean that is
evaluated for each resource referenced in the Resources field when a
webhook is received. If the expression returns false then the controller
will not request a reconciliation for the resource.
When the expression is specified the controller will parse it and mark
the object as terminally failed if the expression is invalid or does not
return a boolean.</p>
</td>
</tr>
<tr>
<td>
<code>secretRef</code><br>
<em>
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">

View File

@ -0,0 +1,794 @@
<h1>Notification API reference v1beta3</h1>
<p>Packages:</p>
<ul class="simple">
<li>
<a href="#notification.toolkit.fluxcd.io%2fv1beta3">notification.toolkit.fluxcd.io/v1beta3</a>
</li>
</ul>
<h2 id="notification.toolkit.fluxcd.io/v1beta3">notification.toolkit.fluxcd.io/v1beta3</h2>
<p>Package v1beta3 contains API Schema definitions for the notification v1beta3 API group.</p>
Resource Types:
<ul class="simple"><li>
<a href="#notification.toolkit.fluxcd.io/v1beta3.Alert">Alert</a>
</li><li>
<a href="#notification.toolkit.fluxcd.io/v1beta3.Provider">Provider</a>
</li></ul>
<h3 id="notification.toolkit.fluxcd.io/v1beta3.Alert">Alert
</h3>
<p>Alert is the Schema for the alerts API</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>apiVersion</code><br>
string</td>
<td>
<code>notification.toolkit.fluxcd.io/v1beta3</code>
</td>
</tr>
<tr>
<td>
<code>kind</code><br>
string
</td>
<td>
<code>Alert</code>
</td>
</tr>
<tr>
<td>
<code>metadata</code><br>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta">
Kubernetes meta/v1.ObjectMeta
</a>
</em>
</td>
<td>
Refer to the Kubernetes API documentation for the fields of the
<code>metadata</code> field.
</td>
</tr>
<tr>
<td>
<code>spec</code><br>
<em>
<a href="#notification.toolkit.fluxcd.io/v1beta3.AlertSpec">
AlertSpec
</a>
</em>
</td>
<td>
<br/>
<br/>
<table>
<tr>
<td>
<code>providerRef</code><br>
<em>
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
github.com/fluxcd/pkg/apis/meta.LocalObjectReference
</a>
</em>
</td>
<td>
<p>ProviderRef specifies which Provider this Alert should use.</p>
</td>
</tr>
<tr>
<td>
<code>eventSeverity</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>EventSeverity specifies how to filter events based on severity.
If set to &lsquo;info&rsquo; no events will be filtered.</p>
</td>
</tr>
<tr>
<td>
<code>eventSources</code><br>
<em>
<a href="https://pkg.go.dev/github.com/fluxcd/notification-controller/api/v1#CrossNamespaceObjectReference">
[]github.com/fluxcd/notification-controller/api/v1.CrossNamespaceObjectReference
</a>
</em>
</td>
<td>
<p>EventSources specifies how to filter events based
on the involved object kind, name and namespace.</p>
</td>
</tr>
<tr>
<td>
<code>inclusionList</code><br>
<em>
[]string
</em>
</td>
<td>
<em>(Optional)</em>
<p>InclusionList specifies a list of Golang regular expressions
to be used for including messages.</p>
</td>
</tr>
<tr>
<td>
<code>eventMetadata</code><br>
<em>
map[string]string
</em>
</td>
<td>
<em>(Optional)</em>
<p>EventMetadata is an optional field for adding metadata to events dispatched by the
controller. This can be used for enhancing the context of the event. If a field
would override one already present on the original event as generated by the emitter,
then the override doesn&rsquo;t happen, i.e. the original value is preserved, and an info
log is printed.</p>
</td>
</tr>
<tr>
<td>
<code>exclusionList</code><br>
<em>
[]string
</em>
</td>
<td>
<em>(Optional)</em>
<p>ExclusionList specifies a list of Golang regular expressions
to be used for excluding messages.</p>
</td>
</tr>
<tr>
<td>
<code>summary</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Summary holds a short description of the impact and affected cluster.
Deprecated: Use EventMetadata instead.</p>
</td>
</tr>
<tr>
<td>
<code>suspend</code><br>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>Suspend tells the controller to suspend subsequent
events handling for this Alert.</p>
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<h3 id="notification.toolkit.fluxcd.io/v1beta3.Provider">Provider
</h3>
<p>Provider is the Schema for the providers API</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>apiVersion</code><br>
string</td>
<td>
<code>notification.toolkit.fluxcd.io/v1beta3</code>
</td>
</tr>
<tr>
<td>
<code>kind</code><br>
string
</td>
<td>
<code>Provider</code>
</td>
</tr>
<tr>
<td>
<code>metadata</code><br>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta">
Kubernetes meta/v1.ObjectMeta
</a>
</em>
</td>
<td>
Refer to the Kubernetes API documentation for the fields of the
<code>metadata</code> field.
</td>
</tr>
<tr>
<td>
<code>spec</code><br>
<em>
<a href="#notification.toolkit.fluxcd.io/v1beta3.ProviderSpec">
ProviderSpec
</a>
</em>
</td>
<td>
<br/>
<br/>
<table>
<tr>
<td>
<code>type</code><br>
<em>
string
</em>
</td>
<td>
<p>Type specifies which Provider implementation to use.</p>
</td>
</tr>
<tr>
<td>
<code>interval</code><br>
<em>
<a href="https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Duration">
Kubernetes meta/v1.Duration
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Interval at which to reconcile the Provider with its Secret references.
Deprecated and not used in v1beta3.</p>
</td>
</tr>
<tr>
<td>
<code>channel</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Channel specifies the destination channel where events should be posted.</p>
</td>
</tr>
<tr>
<td>
<code>username</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Username specifies the name under which events are posted.</p>
</td>
</tr>
<tr>
<td>
<code>address</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Address specifies the endpoint, in a generic sense, to where alerts are sent.
What kind of endpoint depends on the specific Provider type being used.
For the generic Provider, for example, this is an HTTP/S address.
For other Provider types this could be a project ID or a namespace.</p>
</td>
</tr>
<tr>
<td>
<code>timeout</code><br>
<em>
<a href="https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Duration">
Kubernetes meta/v1.Duration
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Timeout for sending alerts to the Provider.</p>
</td>
</tr>
<tr>
<td>
<code>proxy</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Proxy the HTTP/S address of the proxy server.
Deprecated: Use ProxySecretRef instead. Will be removed in v1.</p>
</td>
</tr>
<tr>
<td>
<code>proxySecretRef</code><br>
<em>
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
github.com/fluxcd/pkg/apis/meta.LocalObjectReference
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>ProxySecretRef specifies the Secret containing the proxy configuration
for this Provider. The Secret should contain an &lsquo;address&rsquo; key with the
HTTP/S address of the proxy server. Optional &lsquo;username&rsquo; and &lsquo;password&rsquo;
keys can be provided for proxy authentication.</p>
</td>
</tr>
<tr>
<td>
<code>secretRef</code><br>
<em>
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
github.com/fluxcd/pkg/apis/meta.LocalObjectReference
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>SecretRef specifies the Secret containing the authentication
credentials for this Provider.</p>
</td>
</tr>
<tr>
<td>
<code>serviceAccountName</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>ServiceAccountName is the name of the Kubernetes ServiceAccount used to
authenticate with cloud provider services through workload identity.
This enables multi-tenant authentication without storing static credentials.</p>
<p>Supported provider types: azureeventhub, azuredevops, googlepubsub</p>
<p>When specified, the controller will:
1. Create an OIDC token for the specified ServiceAccount
2. Exchange it for cloud provider credentials via STS
3. Use the obtained credentials for API authentication</p>
<p>When unspecified, controller-level authentication is used (single-tenant).</p>
<p>An error is thrown if static credentials are also defined in SecretRef.
This field requires the ObjectLevelWorkloadIdentity feature gate to be enabled.</p>
</td>
</tr>
<tr>
<td>
<code>certSecretRef</code><br>
<em>
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
github.com/fluxcd/pkg/apis/meta.LocalObjectReference
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>CertSecretRef specifies the Secret containing TLS certificates
for secure communication.</p>
<p>Supported configurations:
- CA-only: Server authentication (provide ca.crt only)
- mTLS: Mutual authentication (provide ca.crt + tls.crt + tls.key)
- Client-only: Client authentication with system CA (provide tls.crt + tls.key only)</p>
<p>Legacy keys &ldquo;caFile&rdquo;, &ldquo;certFile&rdquo;, &ldquo;keyFile&rdquo; are supported but deprecated. Use &ldquo;ca.crt&rdquo;, &ldquo;tls.crt&rdquo;, &ldquo;tls.key&rdquo; instead.</p>
</td>
</tr>
<tr>
<td>
<code>suspend</code><br>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>Suspend tells the controller to suspend subsequent
events handling for this Provider.</p>
</td>
</tr>
<tr>
<td>
<code>commitStatusExpr</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>CommitStatusExpr is a CEL expression that evaluates to a string value
that can be used to generate a custom commit status message for use
with eligible Provider types (github, gitlab, gitea, bitbucketserver,
bitbucket, azuredevops). Supported variables are: event, provider,
and alert.</p>
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<h3 id="notification.toolkit.fluxcd.io/v1beta3.AlertSpec">AlertSpec
</h3>
<p>
(<em>Appears on:</em>
<a href="#notification.toolkit.fluxcd.io/v1beta3.Alert">Alert</a>)
</p>
<p>AlertSpec defines an alerting rule for events involving a list of objects.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>providerRef</code><br>
<em>
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
github.com/fluxcd/pkg/apis/meta.LocalObjectReference
</a>
</em>
</td>
<td>
<p>ProviderRef specifies which Provider this Alert should use.</p>
</td>
</tr>
<tr>
<td>
<code>eventSeverity</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>EventSeverity specifies how to filter events based on severity.
If set to &lsquo;info&rsquo; no events will be filtered.</p>
</td>
</tr>
<tr>
<td>
<code>eventSources</code><br>
<em>
<a href="https://pkg.go.dev/github.com/fluxcd/notification-controller/api/v1#CrossNamespaceObjectReference">
[]github.com/fluxcd/notification-controller/api/v1.CrossNamespaceObjectReference
</a>
</em>
</td>
<td>
<p>EventSources specifies how to filter events based
on the involved object kind, name and namespace.</p>
</td>
</tr>
<tr>
<td>
<code>inclusionList</code><br>
<em>
[]string
</em>
</td>
<td>
<em>(Optional)</em>
<p>InclusionList specifies a list of Golang regular expressions
to be used for including messages.</p>
</td>
</tr>
<tr>
<td>
<code>eventMetadata</code><br>
<em>
map[string]string
</em>
</td>
<td>
<em>(Optional)</em>
<p>EventMetadata is an optional field for adding metadata to events dispatched by the
controller. This can be used for enhancing the context of the event. If a field
would override one already present on the original event as generated by the emitter,
then the override doesn&rsquo;t happen, i.e. the original value is preserved, and an info
log is printed.</p>
</td>
</tr>
<tr>
<td>
<code>exclusionList</code><br>
<em>
[]string
</em>
</td>
<td>
<em>(Optional)</em>
<p>ExclusionList specifies a list of Golang regular expressions
to be used for excluding messages.</p>
</td>
</tr>
<tr>
<td>
<code>summary</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Summary holds a short description of the impact and affected cluster.
Deprecated: Use EventMetadata instead.</p>
</td>
</tr>
<tr>
<td>
<code>suspend</code><br>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>Suspend tells the controller to suspend subsequent
events handling for this Alert.</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<h3 id="notification.toolkit.fluxcd.io/v1beta3.ProviderSpec">ProviderSpec
</h3>
<p>
(<em>Appears on:</em>
<a href="#notification.toolkit.fluxcd.io/v1beta3.Provider">Provider</a>)
</p>
<p>ProviderSpec defines the desired state of the Provider.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>type</code><br>
<em>
string
</em>
</td>
<td>
<p>Type specifies which Provider implementation to use.</p>
</td>
</tr>
<tr>
<td>
<code>interval</code><br>
<em>
<a href="https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Duration">
Kubernetes meta/v1.Duration
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Interval at which to reconcile the Provider with its Secret references.
Deprecated and not used in v1beta3.</p>
</td>
</tr>
<tr>
<td>
<code>channel</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Channel specifies the destination channel where events should be posted.</p>
</td>
</tr>
<tr>
<td>
<code>username</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Username specifies the name under which events are posted.</p>
</td>
</tr>
<tr>
<td>
<code>address</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Address specifies the endpoint, in a generic sense, to where alerts are sent.
What kind of endpoint depends on the specific Provider type being used.
For the generic Provider, for example, this is an HTTP/S address.
For other Provider types this could be a project ID or a namespace.</p>
</td>
</tr>
<tr>
<td>
<code>timeout</code><br>
<em>
<a href="https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Duration">
Kubernetes meta/v1.Duration
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Timeout for sending alerts to the Provider.</p>
</td>
</tr>
<tr>
<td>
<code>proxy</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Proxy the HTTP/S address of the proxy server.
Deprecated: Use ProxySecretRef instead. Will be removed in v1.</p>
</td>
</tr>
<tr>
<td>
<code>proxySecretRef</code><br>
<em>
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
github.com/fluxcd/pkg/apis/meta.LocalObjectReference
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>ProxySecretRef specifies the Secret containing the proxy configuration
for this Provider. The Secret should contain an &lsquo;address&rsquo; key with the
HTTP/S address of the proxy server. Optional &lsquo;username&rsquo; and &lsquo;password&rsquo;
keys can be provided for proxy authentication.</p>
</td>
</tr>
<tr>
<td>
<code>secretRef</code><br>
<em>
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
github.com/fluxcd/pkg/apis/meta.LocalObjectReference
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>SecretRef specifies the Secret containing the authentication
credentials for this Provider.</p>
</td>
</tr>
<tr>
<td>
<code>serviceAccountName</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>ServiceAccountName is the name of the Kubernetes ServiceAccount used to
authenticate with cloud provider services through workload identity.
This enables multi-tenant authentication without storing static credentials.</p>
<p>Supported provider types: azureeventhub, azuredevops, googlepubsub</p>
<p>When specified, the controller will:
1. Create an OIDC token for the specified ServiceAccount
2. Exchange it for cloud provider credentials via STS
3. Use the obtained credentials for API authentication</p>
<p>When unspecified, controller-level authentication is used (single-tenant).</p>
<p>An error is thrown if static credentials are also defined in SecretRef.
This field requires the ObjectLevelWorkloadIdentity feature gate to be enabled.</p>
</td>
</tr>
<tr>
<td>
<code>certSecretRef</code><br>
<em>
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
github.com/fluxcd/pkg/apis/meta.LocalObjectReference
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>CertSecretRef specifies the Secret containing TLS certificates
for secure communication.</p>
<p>Supported configurations:
- CA-only: Server authentication (provide ca.crt only)
- mTLS: Mutual authentication (provide ca.crt + tls.crt + tls.key)
- Client-only: Client authentication with system CA (provide tls.crt + tls.key only)</p>
<p>Legacy keys &ldquo;caFile&rdquo;, &ldquo;certFile&rdquo;, &ldquo;keyFile&rdquo; are supported but deprecated. Use &ldquo;ca.crt&rdquo;, &ldquo;tls.crt&rdquo;, &ldquo;tls.key&rdquo; instead.</p>
</td>
</tr>
<tr>
<td>
<code>suspend</code><br>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>Suspend tells the controller to suspend subsequent
events handling for this Provider.</p>
</td>
</tr>
<tr>
<td>
<code>commitStatusExpr</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>CommitStatusExpr is a CEL expression that evaluates to a string value
that can be used to generate a custom commit status message for use
with eligible Provider types (github, gitlab, gitea, bitbucketserver,
bitbucket, azuredevops). Supported variables are: event, provider,
and alert.</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="admonition note">
<p class="last">This page was automatically generated with <code>gen-crd-api-reference-docs</code></p>
</div>

View File

@ -3,6 +3,7 @@
## API Specification
* [v1](v1/README.md)
* [v1beta3](v1beta3/README.md)
* [v1beta2](v1beta2/README.md)
* [v1beta1](v1beta1/README.md)
* [v1alpha1](v1alpha1/README.md)

View File

@ -134,6 +134,7 @@ handle the incoming webhook request.
| [Nexus](#nexus) | `nexus` | ❌ |
| [Azure Container Registry](#acr) | `acr` | ❌ |
| [Google Container Registry](#gcr) | `gcr` | ❌ |
| [CDEvents](#cdevents) | `cdevents` | ✅ |
#### Generic
@ -613,6 +614,35 @@ spec:
name: webapp
```
#### CDEvents
When a Receiver's `.spec.type` is set to `cdevents`, the controller will respond to
a [CDEvent Event Payload](https://cdevents.dev/docs/). It will verify the CDEvent
using the [CDEvent Go-SDK](https://github.com/cdevents/sdk-go).
This type of receiver supports filtering using [Events](#events) by comparing the
`type` header to the list of events.
##### CDEvents example
```yaml
---
apiVersion: notification.toolkit.fluxcd.io/v1
kind: Receiver
metadata:
name: cdevents-receiver
namespace: flux-system
spec:
type: cdevents
events:
- "dev.cdevents.change.merged"
secretRef:
name: receiver-token
resources:
- kind: GitRepository
name: webapp
```
### Events
`.spec.events` is an optional field to specify a list of webhook payload event
@ -670,6 +700,75 @@ resources:
**Note:** Cross-namespace references [can be disabled for security
reasons](#disabling-cross-namespace-selectors).
#### Filtering reconciled objects with CEL
To filter the resources that are reconciled you can use [Common Expression Language (CEL)](https://cel.dev/).
For example, to trigger `ImageRepositories` on notifications from [Google Artifact Registry](https://cloud.google.com/artifact-registry/docs/configure-notifications#examples) you can define the following receiver:
```yaml
apiVersion: notification.toolkit.fluxcd.io/v1
kind: Receiver
metadata:
name: gar-receiver
namespace: apps
spec:
type: gcr
secretRef:
name: flux-gar-token
resources:
- apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
name: "*"
matchLabels:
registry: gar
```
This will trigger the reconciliation of all `ImageRepositories` with the label `registry: gar`.
But if you want to only notify `ImageRepository` resources that are referenced from the incoming hook you can use CEL to filter the resources.
```yaml
apiVersion: notification.toolkit.fluxcd.io/v1
kind: Receiver
metadata:
name: gar-receiver
namespace: apps
spec:
type: gcr
secretRef:
name: flux-gar-token
resources:
- apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
name: "*"
matchLabels:
registry: gar
resourceFilter: 'req.tag.contains(res.metadata.name)'
```
If the body of the incoming hook looks like this:
```json
{
"action":"INSERT",
"digest":"us-east1-docker.pkg.dev/my-project/my-repo/hello-world@sha256:6ec128e26cd5...",
"tag":"us-east1-docker.pkg.dev/my-project/my-repo/hello-world:1.1"
}
```
This simple example would match `ImageRepositories` containing the name `hello-world`.
If you want to do more complex processing:
```yaml
resourceFilter: has(res.metadata.annotations) && req.tag.split('/').last().value().split(":").first().value() == res.metadata.annotations['update-image']
```
This would look for an annotation "update-image" on the resource, and match it to the `hello-world` part of the tag name.
**Note:** Currently the `resource` value in the CEL expression only provides the object metadata, this means you can access things like `res.metadata.labels`, `res.metadata.annotations` and `res.metadata.name`.
### Secret reference
`.spec.secretRef.name` is a required field to specify a name reference to a
@ -680,7 +779,7 @@ This token is used to salt the generated [webhook path](#webhook-path), and
depending on the Receiver [type](#supported-receiver-types), to verify the
authenticity of a request.
#### Secret example
Example:
```yaml
---
@ -694,6 +793,21 @@ stringData:
token: <random token>
```
To trigger a reconciliation of the Receiver when changes occur in
the referenced Secret, you can set the following label on the
Secret:
```yaml
metadata:
labels:
reconcile.fluxcd.io/watch: Enabled
```
An alternative to labeling every Secret is setting the
`--watch-configs-label-selector=owner!=helm` flag in
notification-controller, which allows watching all
Secrets except for Helm storage Secrets.
### Interval
`.spec.interval` is an optional field with a default of ten minutes that specifies
@ -713,7 +827,7 @@ When the field is set to `false` or removed, it will resume.
On multi-tenant clusters, platform admins can disable cross-namespace
references with the `--no-cross-namespace-refs=true` flag. When this flag is
set, Receivers can only refer to [Resources](#resources) in the same namespace
as the [Alert](alerts.md) object, preventing tenants from triggering
as the Receiver object, preventing tenants from triggering
reconciliations to another tenant's resources.
### Public Ingress considerations

View File

@ -4,11 +4,11 @@ This is the v1alpha1 API specification for defining events handling and dispatch
## Specification
* [Alert](alert.md)
* [Event](event.md)
* [Provider](provider.md)
* [Receiver](receiver.md)
* [Alert](alerts.md)
* [Event](events.md)
* [Provider](providers.md)
* [Receiver](receivers.md)
## Go Client
* [github.com/fluxcd/pkg/recorder](https://github.com/fluxcd/pkg/tree/main/recorder)
* [github.com/fluxcd/pkg/runtime/events/recorder.go](https://github.com/fluxcd/pkg/blob/main/runtime/events/recorder.go#L60)

View File

@ -368,7 +368,8 @@ and use `https://api.telegram.org/` as the api url.
--from-literal=address=https://api.telegram.org
```
Also note that `spec.channel` can be a unique identifier for the target chat
Also note that `spec.channel` can be a unique identifier for the target chat,
a unique identifier with the topic identifier for the forum chat
or username of the target channel (in the format @channelusername)
```yaml
@ -379,7 +380,7 @@ metadata:
namespace: flux-system
spec:
type: telegram
channel: "@fluxtest" # or "-1557265138" (channel id)
channel: "@fluxtest" # or "-1557265138" (channel id) or "-1552289257:1" (forum chat id with topic id)
secretRef:
name: telegram-token
```

View File

@ -129,13 +129,14 @@ The supported alerting providers are:
The supported providers for [Git commit status updates](#git-commit-status-updates) are:
| Provider | Type |
|-------------------------------|---------------|
| [Azure DevOps](#azure-devops) | `azuredevops` |
| [Bitbucket](#bitbucket) | `bitbucket` |
| [GitHub](#github) | `github` |
| [GitLab](#gitlab) | `gitlab` |
| [Gitea](#gitea) | `gitea` |
| Provider | Type |
| ------------------------------------------------| ----------------- |
| [Azure DevOps](#azure-devops) | `azuredevops` |
| [Bitbucket](#bitbucket) | `bitbucket` |
| [BitbucketServer](#bitbucket-serverdata-center) | `bitbucketserver` |
| [GitHub](#github) | `github` |
| [GitLab](#gitlab) | `gitlab` |
| [Gitea](#gitea) | `gitea` |
#### Alerting
@ -446,7 +447,7 @@ metadata:
stringData:
token: <DataDog API Key>
---
apiVersion: notification.toolkit.fluxcd.io/v1beta1
apiVersion: notification.toolkit.fluxcd.io/v1beta2
kind: Alert
metadata:
name: datadog-info
@ -562,8 +563,9 @@ The Event will be formatted into a message string, with the metadata attached
as a list of key-value pairs.
The Provider's [Channel](#channel) is used to set the receiver of the message.
This can be a unique identifier (`-1234567890`) for the target chat, or
the username (`@username`) of the target channel.
This can be a unique identifier (`-1234567890`) for the target chat,
a unique identifier with the topic identifier (`-1234567890:1`) for the forum chat,
or the username (`@username`) of the target channel.
This Provider type does not support the configuration of a [proxy URL](#https-proxy)
or [TLS certificates](#tls-certificates).
@ -585,7 +587,7 @@ metadata:
spec:
type: telegram
address: https://api.telegram.org
channel: "@fluxcd" # or "-1557265138" (channel id)
channel: "@fluxcd" # or "-1557265138" (channel id) or "-1552289257:1" (forum chat id with topic id)
secretRef:
name: telegram-token
```
@ -1514,6 +1516,32 @@ You can create the secret with `kubectl` like this:
kubectl create secret generic bitbucket-token --from-literal=token=<username>:<app-password>
```
#### BitBucket Server/Data Center
When `.spec.type` is set to `bitbucketserver`, the following auth methods are available:
- Basic Authentication (username/password)
- [HTTP access tokens](https://confluence.atlassian.com/bitbucketserver/http-access-tokens-939515499.html)
For Basic Authentication, the referenced secret must contain a `password` field. The `username` field can either come from the [`.spec.username` field of the Provider](https://fluxcd.io/flux/components/notification/providers/#username) or can be defined in the referenced secret.
You can create the secret with `kubectl` like this:
```shell
kubectl create secret generic bb-server-username-password --from-literal=username=<username> --from-literal=password=<password>
```
For HTTP access tokens, the secret can be created with `kubectl` like this:
```shell
kubectl create secret generic bb-server-token --from-literal=token=<token>
```
The HTTP access token must have `Repositories (Read/Write)` permission for
the repository specified in `.spec.address`.
**NOTE:** Please provide HTTPS clone URL in the `address` field of this provider. SSH URLs are not supported by this provider type.
#### Azure DevOps
When `.spec.type` is set to `azuredevops`, the referenced secret must contain a key called `token` with the value set to a

View File

@ -0,0 +1,13 @@
# notification.toolkit.fluxcd.io/v1beta3
This is the v1beta3 API specification for defining events handling.
## Specification
* [Alerts](alerts.md)
* [Events](events.md)
* [Providers](providers.md)
## Go Client
* [github.com/fluxcd/pkg/runtime/events](https://pkg.go.dev/github.com/fluxcd/pkg/runtime/events)

319
docs/spec/v1beta3/alerts.md Normal file
View File

@ -0,0 +1,319 @@
# Alerts
<!-- menuweight:10 -->
The `Alert` API defines how events are filtered by severity and involved object, and what provider to use for dispatching.
## Example
The following is an example of how to send alerts to Slack when Flux fails to reconcile the `flux-system` namespace.
```yaml
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
name: slack-bot
namespace: flux-system
spec:
type: slack
channel: general
address: https://slack.com/api/chat.postMessage
secretRef:
name: slack-bot-token
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: slack
namespace: flux-system
spec:
providerRef:
name: slack-bot
eventMetadata:
summary: Cluster addons impacted
env: prod
cluster: my-cluster
region: us-east-2
eventSeverity: error
eventSources:
- kind: GitRepository
name: '*'
- kind: Kustomization
name: '*'
```
In the above example:
- A Provider named `slack-bot` is created, indicated by the
`Provider.metadata.name` field.
- An Alert named `slack` is created, indicated by the
`Alert.metadata.name` field.
- The Alert references the `slack-bot` provider, indicated by the
`Alert.spec.providerRef` field.
- The notification-controller starts listening for events sent for
all GitRepositories and Kustomizations in the `flux-system` namespace.
- When an event with severity `error` is received, the controller posts
a message on Slack channel from `.spec.channel`,
containing the metadata and the reconciliation error.
You can run this example by saving the manifests into `slack-alerts.yaml`.
1. First create a secret with the Slack bot token:
```sh
kubectl -n flux-system create secret generic slack-bot-token --from-literal=token=xoxb-YOUR-TOKEN
```
2. Apply the resources on the cluster:
```sh
kubectl -n flux-system apply --server-side -f slack-alerts.yaml
```
## Writing an Alert spec
As with all other Kubernetes config, an Alert needs `apiVersion`,
`kind`, and `metadata` fields. The name of an Alert object must be a
valid [DNS subdomain name](https://kubernetes.io/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).
An Alert also needs a
[`.spec` section](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).
### Summary
`.spec.summary` is an optional field to specify a short description of the impact.
The summary max length can't be greater than 255 characters.
**Warning:** Support for `.spec.summary` has been deprecated and will be removed in
Alert API v1 GA. If you have any Alerts using this field, the controller will log a
deprecation warning. Please use [`.spec.eventMetadata.summary`](#event-metadata) or
[object annotations](#event-metadata-from-object-annotations) for defining alert
summary instead.
### Provider reference
`.spec.providerRef.name` is a required field to specify a name reference to a
[Provider](providers.md) in the same namespace as the Alert.
### Event sources
`.spec.eventSources` is a required field to specify a list of references to
Flux objects for which events are forwarded to the alert provider API.
To select events issued by Flux objects, each entry in the `.spec.eventSources` list
must contain the following fields:
- `kind` is the Flux Custom Resource Kind such as GitRepository, HelmRelease, Kustomization, etc.
- `name` is the Flux Custom Resource `.metadata.name`, or it can be set to the `*` wildcard.
- `namespace` is the Flux Custom Resource `.metadata.namespace`.
When not specified, the Alert `.metadata.namespace` is used instead.
#### Select objects by name
To select events issued by a single Flux object, set the `kind`, `name` and `namespace`:
```yaml
eventSources:
- kind: GitRepository
name: webapp
namespace: apps
```
#### Select all objects in a namespace
The `*` wildcard can be used to select events issued by all Flux objects of a particular `kind` in a `namespace`:
```yaml
eventSources:
- kind: HelmRelease
name: '*'
namespace: apps
```
#### Select objects by label
To select events issued by all Flux objects of a particular `kind` with specific `labels`:
```yaml
eventSources:
- kind: HelmRelease
name: '*'
namespace: apps
matchLabels:
team: app-dev
```
#### Disable cross-namespace selectors
**Note:** On multi-tenant clusters, platform admins can disable cross-namespace references by
starting the controller with the `--no-cross-namespace-refs=true` flag.
When this flag is set, alerts can only refer to event sources in the same namespace as the alert object,
preventing tenants from subscribing to another tenant's events.
### Event metadata
`.spec.eventMetadata` is an optional field for adding metadata to events dispatched by
the controller. This can be used for enhancing the context of the event, e.g. with
cluster-level information.
For all the event metadata sources and their precedence order, please refer to
[Event metadata from object annotations](#event-metadata-from-object-annotations).
#### Example
Add metadata fields to successful `HelmRelease` events:
```yaml
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: <name>
spec:
eventSources:
- kind: HelmRelease
name: '*'
inclusionList:
- ".*succeeded.*"
eventMetadata:
env: production
cluster: my-cluster
region: us-east-1
```
### Event metadata from object annotations
Event metadata has four sources. They are listed below in order of precedence,
from lowest to highest:
1. User-defined metadata on Flux objects, set with the `event.toolkit.fluxcd.io/`
prefix in the keys of the object's `.metadata.annotations`.
2. User-defined metadata on the Alert object, set with [`.spec.eventMetadata`](#event-metadata).
3. User-defined summary on the Alert object, set with [`.spec.summary`](#summary) (deprecated, see docs).
4. Controller-defined metadata, set with the `<controller group>.toolkit.fluxcd.io/`
prefix in the metadata keys of the event payload.
If there are any metadata key conflicts between the sources, the higher
precedence source will override the lower precedence source, and a warning
log and Kubernetes event will be emitted.
#### Example
```yaml
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: <name>
spec:
eventSources:
- kind: HelmRelease
name: '*'
eventMetadata:
env: production
cluster: my-cluster
region: us-east-1
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: my-webapp
annotations:
event.toolkit.fluxcd.io/summary: "my-webapp impacted. Playbook: <URL to playbook>"
event.toolkit.fluxcd.io/deploymentID: e076e315-5a48-41c3-81c8-8d8bdee7d74d
spec:
... # fields omitted for brevity
```
In the above example, the event payload dispatched by the controller will look like this
(most fields omitted for highlighting the metadata):
```json
{
"metadata": {
"env": "production",
"cluster": "my-cluster",
"region": "us-east-1",
"summary": "my-webapp impacted. Playbook: <URL to playbook>",
"deploymentID": "e076e315-5a48-41c3-81c8-8d8bdee7d74d"
}
}
```
### Event severity
`.spec.eventSeverity` is an optional field to filter events based on severity. When not specified, or
when the value is set to `info`, all events are forwarded to the alert provider API, including errors.
To receive alerts only on errors, set the field value to `error`.
### Event exclusion
`.spec.exclusionList` is an optional field to specify a list of regex expressions to filter
events based on message content. The event will be excluded if the message matches at least
one of the expressions in the list.
#### Example
Skip alerting if the message matches a [Go regex](https://golang.org/pkg/regexp/syntax)
from the exclusion list:
```yaml
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: <name>
spec:
eventSources:
- kind: GitRepository
name: '*'
exclusionList:
- "waiting.*socket"
```
The above definition will not send alerts for transient Git clone errors like:
```text
unable to clone 'ssh://git@ssh.dev.azure.com/v3/...', error: SSH could not read data: Error waiting on socket
```
### Event inclusion
`.spec.inclusionList` is an optional field to specify a list of regex expressions to filter
events based on message content. The event will be sent if the message matches at least one
of the expressions in the list, and discarded otherwise. If the message matches one of the
expressions in the inclusion list but also matches one of the expressions in the exclusion
list, then the event is still discarded (exclusion is stronger than inclusion).
#### Example
Alert if the message matches a [Go regex](https://golang.org/pkg/regexp/syntax)
from the inclusion list:
```yaml
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: <name>
spec:
eventSources:
- kind: HelmRelease
name: '*'
inclusionList:
- ".*succeeded.*"
exclusionList:
- ".*uninstall.*"
- ".*test.*"
```
The above definition will send alerts for successful Helm installs, upgrades and rollbacks,
but not uninstalls and tests.
### Suspend
`.spec.suspend` is an optional field to suspend the altering.
When set to `true`, the controller will stop processing events.
When the field is set to `false` or removed, it will resume.

View File

@ -0,0 +1,64 @@
# Events
<!-- menuweight:20 -->
The `Event` API defines the structure of the events issued by Flux controllers.
Flux controllers use the [fluxcd/pkg/runtime/events](https://github.com/fluxcd/pkg/tree/main/runtime/events)
package to push events to the notification-controller API.
## Example
The following is an example of an event sent by kustomize-controller to report a reconciliation error.
```json
{
"involvedObject": {
"apiVersion": "kustomize.toolkit.fluxcd.io/v1",
"kind": "Kustomization",
"name": "webapp",
"namespace": "apps",
"uid": "7d0cdc51-ddcf-4743-b223-83ca5c699632"
},
"metadata": {
"kustomize.toolkit.fluxcd.io/revision": "main/731f7eaddfb6af01cb2173e18f0f75b0ba780ef1"
},
"severity":"error",
"reason": "ValidationFailed",
"message":"service/apps/webapp validation error: spec.type: Unsupported value: Ingress",
"reportingController":"kustomize-controller",
"timestamp":"2022-10-28T07:26:19Z"
}
```
In the above example:
- An event is issued by kustomize-controller for a specific object, indicated in the
`involvedObject` field.
- The notification-controller receives the event and finds the [alerts](alerts.md)
that match the `involvedObject` and `severity` values.
- For all matching alerts, the controller posts the `message` and the source revision
extracted from `metadata` to the alert provider API.
## Event structure
The Go type that defines the event structure can be found in the
[fluxcd/pkg/apis/event/v1beta1](https://github.com/fluxcd/pkg/blob/main/apis/event/v1beta1/event.go)
package.
## Rate limiting
Events received by notification-controller are subject to rate limiting to reduce the
amount of duplicate alerts sent to external systems like Slack, Sentry, etc.
Events are rate limited based on `involvedObject.name`, `involvedObject.namespace`,
`involvedObject.kind`, `message`, and `metadata`.
The interval of the rate limit is set by default to `5m` but can be configured
with the `--rate-limit-interval` controller flag.
The event server exposes HTTP request metrics to track the amount of rate limited events.
The following promql will get the rate at which requests are rate limited:
```
rate(gotk_event_http_request_duration_seconds_count{code="429"}[30s])
```

File diff suppressed because it is too large Load Diff

284
go.mod
View File

@ -1,165 +1,205 @@
module github.com/fluxcd/notification-controller
go 1.20
go 1.24.0
replace github.com/fluxcd/notification-controller/api => ./api
require (
cloud.google.com/go/pubsub v1.33.0
code.gitea.io/sdk/gitea v0.15.1
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24
github.com/Azure/azure-amqp-common-go/v4 v4.2.0
github.com/Azure/azure-event-hubs-go/v3 v3.6.1
github.com/DataDog/datadog-api-client-go/v2 v2.15.0
github.com/PagerDuty/go-pagerduty v1.7.0
github.com/containrrr/shoutrrr v0.8.0
github.com/fluxcd/notification-controller/api v1.1.0
github.com/fluxcd/pkg/apis/event v0.5.2
github.com/fluxcd/pkg/apis/meta v1.1.2
github.com/fluxcd/pkg/git v0.13.0
github.com/fluxcd/pkg/masktoken v0.2.0
github.com/fluxcd/pkg/runtime v0.42.0
github.com/fluxcd/pkg/ssa v0.32.0
github.com/getsentry/sentry-go v0.23.0
github.com/go-logr/logr v1.2.4
github.com/google/go-github/v53 v53.2.0
github.com/hashicorp/go-retryablehttp v0.7.4
github.com/ktrysmt/go-bitbucket v0.9.66
cloud.google.com/go/pubsub v1.49.0
code.gitea.io/sdk/gitea v0.21.0
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1
github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/v2 v2.0.0
github.com/DataDog/datadog-api-client-go/v2 v2.43.0
github.com/PagerDuty/go-pagerduty v1.8.0
github.com/cdevents/sdk-go v0.4.1
github.com/chainguard-dev/git-urls v1.0.2
github.com/elazarl/goproxy v1.7.2
github.com/fluxcd/cli-utils v0.36.0-flux.14
github.com/fluxcd/notification-controller/api v1.6.0
github.com/fluxcd/pkg/apis/event v0.18.0
github.com/fluxcd/pkg/apis/meta v1.18.0
github.com/fluxcd/pkg/auth v0.27.0
github.com/fluxcd/pkg/cache v0.10.0
github.com/fluxcd/pkg/git v0.35.0
github.com/fluxcd/pkg/masktoken v0.7.0
github.com/fluxcd/pkg/runtime v0.80.0
github.com/fluxcd/pkg/ssa v0.51.0
github.com/fluxcd/pkg/ssh v0.20.0
github.com/getsentry/sentry-go v0.34.1
github.com/go-logr/logr v1.4.3
github.com/google/cel-go v0.26.0
github.com/google/go-github/v64 v64.0.0
github.com/google/uuid v1.6.0
github.com/hashicorp/go-retryablehttp v0.7.8
github.com/ktrysmt/go-bitbucket v0.9.86
github.com/microsoft/azure-devops-go-api/azuredevops/v6 v6.0.1
github.com/onsi/gomega v1.27.10
github.com/sethvargo/go-limiter v0.7.2
github.com/slok/go-http-metrics v0.10.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4
github.com/whilp/git-urls v1.0.0
github.com/xanzy/go-gitlab v0.90.0
golang.org/x/oauth2 v0.11.0
google.golang.org/api v0.138.0
k8s.io/api v0.27.4
k8s.io/apimachinery v0.27.4
k8s.io/client-go v0.27.4
k8s.io/utils v0.0.0-20230505201702-9f6742963106
sigs.k8s.io/cli-utils v0.35.0
sigs.k8s.io/controller-runtime v0.15.1
sigs.k8s.io/yaml v1.3.0
github.com/nats-io/nats.go v1.43.0
github.com/onsi/gomega v1.38.0
github.com/sethvargo/go-limiter v1.0.0
github.com/slok/go-http-metrics v0.13.0
github.com/spf13/pflag v1.0.7
github.com/stretchr/testify v1.10.0
gitlab.com/gitlab-org/api/client-go v0.137.0
golang.org/x/oauth2 v0.30.0
golang.org/x/text v0.27.0
google.golang.org/api v0.243.0
k8s.io/api v0.33.2
k8s.io/apimachinery v0.33.2
k8s.io/client-go v0.33.2
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
sigs.k8s.io/controller-runtime v0.21.0
sigs.k8s.io/yaml v1.5.0
)
// Fix CVE-2022-28948
replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1
require (
cloud.google.com/go v0.110.6 // indirect
cloud.google.com/go/compute v1.23.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.1 // indirect
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
github.com/Azure/go-amqp v1.0.0 // indirect
cel.dev/expr v0.24.0 // indirect
cloud.google.com/go v0.120.0 // indirect
cloud.google.com/go/auth v0.16.3 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.7.0 // indirect
cloud.google.com/go/iam v1.5.2 // indirect
github.com/42wim/httpsig v1.2.2 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/containers/azcontainerregistry v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0 // indirect
github.com/Azure/go-amqp v1.4.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
github.com/DataDog/zstd v1.5.2 // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect
github.com/ProtonMail/go-crypto v1.3.0 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/bradleyfalzon/ghinstallation/v2 v2.16.0 // indirect
github.com/carapace-sh/carapace-shlex v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/devigned/tab v0.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.10.2 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/cloudevents/sdk-go/v2 v2.15.2 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidmz/go-pageant v1.0.2 // indirect
github.com/docker/cli v28.2.2+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.3 // indirect
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/fluxcd/pkg/apis/acl v0.1.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-logr/zapr v1.2.4 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fluxcd/pkg/apis/acl v0.7.0 // indirect
github.com/fluxcd/pkg/apis/kustomize v1.11.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
github.com/go-errors/errors v1.5.1 // indirect
github.com/go-fed/httpsig v1.1.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
github.com/go-openapi/jsonpointer v0.21.1 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.22.0 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-containerregistry v0.20.6 // indirect
github.com/google/go-github/v72 v72.0.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/s2a-go v0.1.5 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/spdystream v0.5.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/nats-io/nkeys v0.4.11 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/package-url/packageurl-go v0.1.1 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.65.0 // indirect
github.com/prometheus/procfs v0.17.0 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/cobra v1.9.1 // indirect
github.com/stoewer/go-strcase v1.3.1 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.starlark.net v0.0.0-20230302034142-4b1e35fe2254 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.37.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.25.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/time v0.3.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect
google.golang.org/grpc v1.57.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
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.40.0 // indirect
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/term v0.33.0 // indirect
golang.org/x/time v0.12.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250715232539-7130f93afb79 // indirect
google.golang.org/grpc v1.73.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.27.3 // indirect
k8s.io/cli-runtime v0.27.2 // indirect
k8s.io/component-base v0.27.4 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230515203736-54b630e78af5 // indirect
k8s.io/kubectl v0.27.2 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kustomize/api v0.13.4 // indirect
sigs.k8s.io/kustomize/kyaml v0.14.2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect
k8s.io/apiextensions-apiserver v0.33.2 // indirect
k8s.io/cli-runtime v0.33.2 // indirect
k8s.io/component-base v0.33.2 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 // indirect
k8s.io/kubectl v0.33.2 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/kustomize/api v0.20.0 // indirect
sigs.k8s.io/kustomize/kyaml v0.20.0 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
)

2103
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
Copyright 2022 The Flux authors
Copyright 2023 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -18,247 +18,77 @@ package controller
import (
"context"
"fmt"
"time"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
kerrors "k8s.io/apimachinery/pkg/util/errors"
kuberecorder "k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/ratelimiter"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/runtime/conditions"
helper "github.com/fluxcd/pkg/runtime/controller"
"github.com/fluxcd/pkg/runtime/patch"
"github.com/fluxcd/pkg/runtime/predicates"
kuberecorder "k8s.io/client-go/tools/record"
apiv1 "github.com/fluxcd/notification-controller/api/v1"
apiv1beta2 "github.com/fluxcd/notification-controller/api/v1beta2"
apiv1beta3 "github.com/fluxcd/notification-controller/api/v1beta3"
"github.com/fluxcd/pkg/runtime/patch"
)
var (
ProviderIndexKey = ".metadata.provider"
)
// +kubebuilder:rbac:groups=notification.toolkit.fluxcd.io,resources=alerts,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
// AlertReconciler reconciles a Alert object
// AlertReconciler reconciles an Alert object to migrate it to static Alert.
type AlertReconciler struct {
client.Client
helper.Metrics
kuberecorder.EventRecorder
ControllerName string
}
type AlertReconcilerOptions struct {
RateLimiter ratelimiter.RateLimiter
}
func (r *AlertReconciler) SetupWithManager(mgr ctrl.Manager) error {
return r.SetupWithManagerAndOptions(mgr, AlertReconcilerOptions{})
}
func (r *AlertReconciler) SetupWithManagerAndOptions(mgr ctrl.Manager, opts AlertReconcilerOptions) error {
if err := mgr.GetFieldIndexer().IndexField(context.TODO(), &apiv1beta2.Alert{}, ProviderIndexKey,
func(o client.Object) []string {
alert := o.(*apiv1beta2.Alert)
return []string{
fmt.Sprintf("%s/%s", alert.GetNamespace(), alert.Spec.ProviderRef.Name),
}
}); err != nil {
return err
}
return ctrl.NewControllerManagedBy(mgr).
For(&apiv1beta2.Alert{}, builder.WithPredicates(
predicate.Or(predicate.GenerationChangedPredicate{}, predicates.ReconcileRequestedPredicate{}),
)).
Watches(
&apiv1beta2.Provider{},
handler.EnqueueRequestsFromMapFunc(r.requestsForProviderChange),
builder.WithPredicates(predicate.GenerationChangedPredicate{}),
).
WithOptions(controller.Options{
RateLimiter: opts.RateLimiter,
}).
For(&apiv1beta3.Alert{}, builder.WithPredicates(finalizerPredicate{})).
Complete(r)
}
// +kubebuilder:rbac:groups=notification.toolkit.fluxcd.io,resources=alerts,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=notification.toolkit.fluxcd.io,resources=alerts/status,verbs=get;update;patch
// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
func (r *AlertReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, retErr error) {
reconcileStart := time.Now()
log := ctrl.LoggerFrom(ctx)
obj := &apiv1beta2.Alert{}
obj := &apiv1beta3.Alert{}
if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// Initialize the runtime patcher with the current version of the object.
patcher := patch.NewSerialPatcher(obj, r.Client)
defer func() {
// Patch finalizers, status and conditions.
if err := r.patch(ctx, obj, patcher); err != nil {
retErr = kerrors.NewAggregate([]error{retErr, err})
}
// Record Prometheus metrics.
r.Metrics.RecordReadiness(ctx, obj)
r.Metrics.RecordDuration(ctx, obj, reconcileStart)
r.Metrics.RecordSuspend(ctx, obj, obj.Spec.Suspend)
// Emit warning event if the reconciliation failed.
if retErr != nil {
r.Event(obj, corev1.EventTypeWarning, meta.FailedReason, retErr.Error())
}
// Log and emit success event.
if retErr == nil && conditions.IsReady(obj) {
msg := "Reconciliation finished"
log.Info(msg)
r.Event(obj, corev1.EventTypeNormal, meta.SucceededReason, msg)
}
}()
if !obj.ObjectMeta.DeletionTimestamp.IsZero() {
controllerutil.RemoveFinalizer(obj, apiv1.NotificationFinalizer)
result = ctrl.Result{}
return
}
// Add finalizer first if not exist to avoid the race condition between init
// and delete.
// Note: Finalizers in general can only be added when the deletionTimestamp
// is not set.
// Early return if no migration is needed.
if !controllerutil.ContainsFinalizer(obj, apiv1.NotificationFinalizer) {
controllerutil.AddFinalizer(obj, apiv1.NotificationFinalizer)
result = ctrl.Result{Requeue: true}
return
}
// Return early if the object is suspended.
if obj.Spec.Suspend {
log.Info("Reconciliation is suspended for this object")
return ctrl.Result{}, nil
}
return r.reconcile(ctx, obj)
}
func (r *AlertReconciler) reconcile(ctx context.Context, alert *apiv1beta2.Alert) (ctrl.Result, error) {
// Mark the resource as under reconciliation.
conditions.MarkReconciling(alert, meta.ProgressingReason, "Reconciliation in progress")
// Check if the provider exist and is ready.
if err := r.isProviderReady(ctx, alert); err != nil {
conditions.MarkFalse(alert, meta.ReadyCondition, meta.FailedReason, err.Error())
return ctrl.Result{Requeue: true}, client.IgnoreNotFound(err)
// Examine if the object is under deletion.
var delete bool
if !obj.ObjectMeta.DeletionTimestamp.IsZero() {
delete = true
}
conditions.MarkTrue(alert, meta.ReadyCondition, meta.SucceededReason, apiv1.InitializedReason)
return ctrl.Result{}, nil
}
func (r *AlertReconciler) isProviderReady(ctx context.Context, alert *apiv1beta2.Alert) error {
provider := &apiv1beta2.Provider{}
providerName := types.NamespacedName{Namespace: alert.Namespace, Name: alert.Spec.ProviderRef.Name}
if err := r.Get(ctx, providerName, provider); err != nil {
// log not found errors since they get filtered out
ctrl.LoggerFrom(ctx).Error(err, "failed to get provider", "provider", providerName.String())
return fmt.Errorf("failed to get provider '%s': %w", providerName.String(), err)
// Skip if it's suspend and not being deleted.
if obj.Spec.Suspend && !delete {
log.Info("reconciliation is suspended for this object")
return ctrl.Result{}, nil
}
if !conditions.IsReady(provider) {
return fmt.Errorf("provider %s is not ready", providerName.String())
patcher, err := patch.NewHelper(obj, r.Client)
if err != nil {
return ctrl.Result{}, err
}
return nil
}
func (r *AlertReconciler) requestsForProviderChange(ctx context.Context, o client.Object) []reconcile.Request {
log := ctrl.LoggerFrom(ctx)
provider, ok := o.(*apiv1beta2.Provider)
if !ok {
log.Error(fmt.Errorf("expected a Provider object; got %T", o),
"failed to get reconcile requests for Provider change")
return nil
}
var list apiv1beta2.AlertList
if err := r.List(ctx, &list, client.MatchingFields{
ProviderIndexKey: client.ObjectKeyFromObject(provider).String(),
}); err != nil {
return nil
}
var reqs []reconcile.Request
for _, i := range list.Items {
reqs = append(reqs, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(&i)})
}
return reqs
}
// patch updates the object status, conditions and finalizers.
func (r *AlertReconciler) patch(ctx context.Context, obj *apiv1beta2.Alert, patcher *patch.SerialPatcher) (retErr error) {
// Configure the runtime patcher.
patchOpts := []patch.Option{}
ownedConditions := []string{
meta.ReadyCondition,
meta.ReconcilingCondition,
meta.StalledCondition,
}
patchOpts = append(patchOpts,
patch.WithOwnedConditions{Conditions: ownedConditions},
patch.WithForceOverwriteConditions{},
patch.WithFieldOwner(r.ControllerName),
)
// Set the value of the reconciliation request in status.
if v, ok := meta.ReconcileAnnotationValue(obj.GetAnnotations()); ok {
obj.Status.LastHandledReconcileAt = v
}
// Remove the Reconciling condition and update the observed generation
// if the reconciliation was successful.
if conditions.IsTrue(obj, meta.ReadyCondition) {
conditions.Delete(obj, meta.ReconcilingCondition)
obj.Status.ObservedGeneration = obj.Generation
}
// Set the Reconciling reason to ProgressingWithRetry if the
// reconciliation has failed.
if conditions.IsFalse(obj, meta.ReadyCondition) &&
conditions.Has(obj, meta.ReconcilingCondition) {
rc := conditions.Get(obj, meta.ReconcilingCondition)
rc.Reason = meta.ProgressingWithRetryReason
conditions.Set(obj, rc)
}
// Patch the object status, conditions and finalizers.
if err := patcher.Patch(ctx, obj, patchOpts...); err != nil {
if !obj.GetDeletionTimestamp().IsZero() {
err = kerrors.FilterOut(err, func(e error) bool { return apierrors.IsNotFound(e) })
defer func() {
if err := patcher.Patch(ctx, obj); err != nil {
retErr = err
}
retErr = kerrors.NewAggregate([]error{retErr, err})
if retErr != nil {
return retErr
}
}
}()
return nil
// Remove the notification-controller finalizer.
controllerutil.RemoveFinalizer(obj, apiv1.NotificationFinalizer)
log.Info("removed finalizer from Alert to migrate to static Alert")
r.Event(obj, corev1.EventTypeNormal, "Migration", "removed finalizer from Alert to migrate to static Alert")
return
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2022 The Flux authors
Copyright 2023 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -17,532 +17,105 @@ limitations under the License.
package controller
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/fluxcd/pkg/ssa"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/runtime/patch"
. "github.com/onsi/gomega"
"github.com/sethvargo/go-limiter/memorystore"
prommetrics "github.com/slok/go-http-metrics/metrics/prometheus"
"github.com/slok/go-http-metrics/middleware"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
logf "sigs.k8s.io/controller-runtime/pkg/log"
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/runtime/conditions"
apiv1 "github.com/fluxcd/notification-controller/api/v1"
apiv1beta2 "github.com/fluxcd/notification-controller/api/v1beta2"
"github.com/fluxcd/notification-controller/internal/server"
apiv1beta3 "github.com/fluxcd/notification-controller/api/v1beta3"
)
func TestAlertReconciler_deleteBeforeFinalizer(t *testing.T) {
func TestAlertReconciler(t *testing.T) {
g := NewWithT(t)
namespaceName := "alert-" + randStringRunes(5)
namespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{Name: namespaceName},
}
g.Expect(k8sClient.Create(ctx, namespace)).ToNot(HaveOccurred())
timeout := 10 * time.Second
testns, err := testEnv.CreateNamespace(ctx, "alert-test")
g.Expect(err).ToNot(HaveOccurred())
t.Cleanup(func() {
g.Expect(k8sClient.Delete(ctx, namespace)).NotTo(HaveOccurred())
g.Expect(testEnv.Cleanup(ctx, testns)).ToNot(HaveOccurred())
})
alert := &apiv1beta2.Alert{}
alert.Name = "test-alert"
alert.Namespace = namespaceName
alert.Spec.EventSources = []apiv1.CrossNamespaceObjectReference{
{Kind: "Bucket", Name: "Foo"},
}
// Add a test finalizer to prevent the object from getting deleted.
alert.SetFinalizers([]string{"test-finalizer"})
g.Expect(k8sClient.Create(ctx, alert)).NotTo(HaveOccurred())
// Add deletion timestamp by deleting the object.
g.Expect(k8sClient.Delete(ctx, alert)).NotTo(HaveOccurred())
r := &AlertReconciler{
Client: k8sClient,
EventRecorder: record.NewFakeRecorder(32),
}
// NOTE: Only a real API server responds with an error in this scenario.
_, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: client.ObjectKeyFromObject(alert)})
g.Expect(err).NotTo(HaveOccurred())
}
func TestAlertReconciler_Reconcile(t *testing.T) {
g := NewWithT(t)
timeout := 5 * time.Second
resultA := &apiv1beta2.Alert{}
namespaceName := "alert-" + randStringRunes(5)
providerName := "provider-" + randStringRunes(5)
g.Expect(createNamespace(namespaceName)).NotTo(HaveOccurred(), "failed to create test namespace")
provider := &apiv1beta2.Provider{
ObjectMeta: metav1.ObjectMeta{
Name: providerName,
Namespace: namespaceName,
},
Spec: apiv1beta2.ProviderSpec{
Type: "generic",
Address: "https://webhook.internal",
},
}
alert := &apiv1beta2.Alert{
alert := &apiv1beta3.Alert{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("alert-%s", randStringRunes(5)),
Namespace: namespaceName,
},
Spec: apiv1beta2.AlertSpec{
ProviderRef: meta.LocalObjectReference{
Name: providerName,
},
EventSeverity: "info",
EventSources: []apiv1.CrossNamespaceObjectReference{
{
Kind: "Bucket",
Name: "*",
},
},
Namespace: testns.Name,
},
}
g.Expect(k8sClient.Create(context.Background(), alert)).To(Succeed())
alertKey := client.ObjectKeyFromObject(alert)
t.Run("fails with provider not found error", func(t *testing.T) {
g := NewWithT(t)
// Remove finalizer at create.
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(alert), resultA)
return conditions.Has(resultA, meta.ReadyCondition)
}, timeout, time.Second).Should(BeTrue())
alert.ObjectMeta.Finalizers = append(alert.ObjectMeta.Finalizers, "foo.bar", apiv1.NotificationFinalizer)
alert.Spec = apiv1beta3.AlertSpec{
ProviderRef: meta.LocalObjectReference{Name: "foo-provider"},
EventSources: []apiv1.CrossNamespaceObjectReference{},
}
g.Expect(testEnv.Create(ctx, alert)).ToNot(HaveOccurred())
g.Expect(conditions.IsReady(resultA)).To(BeFalse())
g.Expect(conditions.GetReason(resultA, meta.ReadyCondition)).To(BeIdenticalTo(meta.FailedReason))
g.Expect(conditions.GetMessage(resultA, meta.ReadyCondition)).To(ContainSubstring(providerName))
g.Eventually(func() bool {
_ = testEnv.Get(ctx, alertKey, alert)
return !controllerutil.ContainsFinalizer(alert, apiv1.NotificationFinalizer)
}, timeout, time.Second).Should(BeTrue())
g.Expect(conditions.Has(resultA, meta.ReconcilingCondition)).To(BeTrue())
g.Expect(conditions.GetReason(resultA, meta.ReconcilingCondition)).To(BeIdenticalTo(meta.ProgressingWithRetryReason))
g.Expect(conditions.GetObservedGeneration(resultA, meta.ReconcilingCondition)).To(BeIdenticalTo(resultA.Generation))
g.Expect(controllerutil.ContainsFinalizer(resultA, apiv1.NotificationFinalizer)).To(BeTrue())
})
// Remove finalizer at update.
t.Run("recovers when provider exists", func(t *testing.T) {
g := NewWithT(t)
patchHelper, err := patch.NewHelper(alert, testEnv.Client)
g.Expect(err).ToNot(HaveOccurred())
alert.ObjectMeta.Finalizers = append(alert.ObjectMeta.Finalizers, apiv1.NotificationFinalizer)
g.Expect(patchHelper.Patch(ctx, alert)).ToNot(HaveOccurred())
g.Expect(k8sClient.Create(context.Background(), provider)).To(Succeed())
g.Eventually(func() bool {
_ = testEnv.Get(ctx, alertKey, alert)
return !controllerutil.ContainsFinalizer(alert, apiv1.NotificationFinalizer)
}, timeout, time.Second).Should(BeTrue())
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(alert), resultA)
return conditions.IsReady(resultA)
}, timeout, time.Second).Should(BeTrue())
// Remove finalizer at delete.
g.Expect(conditions.GetObservedGeneration(resultA, meta.ReadyCondition)).To(BeIdenticalTo(resultA.Generation))
g.Expect(resultA.Status.ObservedGeneration).To(BeIdenticalTo(resultA.Generation))
g.Expect(conditions.Has(resultA, meta.ReconcilingCondition)).To(BeFalse())
})
patchHelper, err = patch.NewHelper(alert, testEnv.Client)
g.Expect(err).ToNot(HaveOccurred())
t.Run("handles reconcileAt", func(t *testing.T) {
g := NewWithT(t)
// Suspend the alert to prevent finalizer from getting removed.
// Ensure only flux finalizer is set to allow the object to be garbage
// collected at the end.
// NOTE: Suspending and updating finalizers are done separately here as
// doing them in a single patch results in flaky test where the finalizer
// update doesn't gets registered with the kube-apiserver, resulting in
// timeout waiting for finalizer to appear on the object below.
alert.Spec.Suspend = true
g.Expect(patchHelper.Patch(ctx, alert)).ToNot(HaveOccurred())
g.Eventually(func() bool {
_ = k8sClient.Get(ctx, alertKey, alert)
return alert.Spec.Suspend == true
}, timeout).Should(BeTrue())
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(alert), resultA)).To(Succeed())
patchHelper, err = patch.NewHelper(alert, testEnv.Client)
g.Expect(err).ToNot(HaveOccurred())
reconcileRequestAt := metav1.Now().String()
resultA.SetAnnotations(map[string]string{
meta.ReconcileRequestAnnotation: reconcileRequestAt,
})
g.Expect(k8sClient.Update(context.Background(), resultA)).To(Succeed())
// Add finalizer and verify that finalizer exists on the object using a live
// client.
alert.ObjectMeta.Finalizers = []string{apiv1.NotificationFinalizer}
g.Expect(patchHelper.Patch(ctx, alert)).ToNot(HaveOccurred())
g.Eventually(func() bool {
_ = k8sClient.Get(ctx, alertKey, alert)
return controllerutil.ContainsFinalizer(alert, apiv1.NotificationFinalizer)
}, timeout).Should(BeTrue())
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(alert), resultA)
return resultA.Status.LastHandledReconcileAt == reconcileRequestAt
}, timeout, time.Second).Should(BeTrue())
})
t.Run("finalizes suspended object", func(t *testing.T) {
g := NewWithT(t)
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(alert), resultA)).To(Succeed())
resultA.Spec.Suspend = true
g.Expect(k8sClient.Update(context.Background(), resultA)).To(Succeed())
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(alert), resultA)
return resultA.Spec.Suspend == true
}, timeout, time.Second).Should(BeTrue())
g.Expect(k8sClient.Delete(context.Background(), resultA)).To(Succeed())
g.Eventually(func() bool {
err := k8sClient.Get(context.Background(), client.ObjectKeyFromObject(alert), resultA)
// Delete the object and verify.
g.Expect(testEnv.Delete(ctx, alert)).ToNot(HaveOccurred())
g.Eventually(func() bool {
if err := testEnv.Get(ctx, alertKey, alert); err != nil {
return apierrors.IsNotFound(err)
}, timeout, time.Second).Should(BeTrue())
})
}
func TestAlertReconciler_EventHandler(t *testing.T) {
g := NewWithT(t)
var (
namespace = "events-" + randStringRunes(5)
req *http.Request
provider *apiv1beta2.Provider
)
g.Expect(createNamespace(namespace)).NotTo(HaveOccurred(), "failed to create test namespace")
eventMdlw := middleware.New(middleware.Config{
Recorder: prommetrics.NewRecorder(prommetrics.Config{
Prefix: "gotk_event",
}),
})
store, err := memorystore.New(&memorystore.Config{
Interval: 5 * time.Minute,
})
if err != nil {
t.Fatalf("failed to create memory storage")
}
eventServer := server.NewEventServer("127.0.0.1:56789", logf.Log, k8sClient, true)
stopCh := make(chan struct{})
go eventServer.ListenAndServe(stopCh, eventMdlw, store)
rcvServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
req = r
w.WriteHeader(200)
}))
defer rcvServer.Close()
defer close(stopCh)
providerKey := types.NamespacedName{
Name: fmt.Sprintf("provider-%s", randStringRunes(5)),
Namespace: namespace,
}
provider = &apiv1beta2.Provider{
ObjectMeta: metav1.ObjectMeta{
Name: providerKey.Name,
Namespace: providerKey.Namespace,
},
Spec: apiv1beta2.ProviderSpec{
Type: "generic",
Address: rcvServer.URL,
},
}
g.Expect(k8sClient.Create(context.Background(), provider)).To(Succeed())
g.Eventually(func() bool {
var obj apiv1beta2.Provider
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), &obj))
return conditions.IsReady(&obj)
}, 30*time.Second, time.Second).Should(BeTrue())
repo, err := readManifest("./testdata/repo.yaml", namespace)
g.Expect(err).ToNot(HaveOccurred())
secondRepo, err := readManifest("./testdata/gitrepo2.yaml", namespace)
g.Expect(err).ToNot(HaveOccurred())
_, err = manager.Apply(context.Background(), repo, ssa.ApplyOptions{
Force: true,
})
g.Expect(err).ToNot(HaveOccurred())
_, err = manager.Apply(context.Background(), secondRepo, ssa.ApplyOptions{
Force: true,
})
g.Expect(err).ToNot(HaveOccurred())
alertKey := types.NamespacedName{
Name: fmt.Sprintf("alert-%s", randStringRunes(5)),
Namespace: namespace,
}
alert := &apiv1beta2.Alert{
ObjectMeta: metav1.ObjectMeta{
Name: alertKey.Name,
Namespace: alertKey.Namespace,
},
Spec: apiv1beta2.AlertSpec{
ProviderRef: meta.LocalObjectReference{
Name: providerKey.Name,
},
EventSeverity: "info",
EventSources: []apiv1.CrossNamespaceObjectReference{
{
Kind: "Bucket",
Name: "hyacinth",
Namespace: namespace,
},
{
Kind: "Kustomization",
Name: "*",
},
{
Kind: "GitRepository",
Name: "*",
MatchLabels: map[string]string{
"app": "podinfo",
},
},
{
Kind: "Kustomization",
Name: "*",
Namespace: "test",
},
},
ExclusionList: []string{
"doesnotoccur", // not intended to match
"excluded",
},
},
}
inclusionAlert := alert.DeepCopy()
inclusionAlert.Spec.InclusionList = []string{"^included"}
g.Expect(k8sClient.Create(context.Background(), alert)).To(Succeed())
// wait for controller to mark the alert as ready
g.Eventually(func() bool {
var obj apiv1beta2.Alert
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(alert), &obj))
return conditions.IsReady(&obj)
}, 30*time.Second, time.Second).Should(BeTrue())
// An event fixture to set the initial fixed state of an Event which is
// modified in the test cases.
eventFixture := eventv1.Event{
InvolvedObject: corev1.ObjectReference{
Kind: "Bucket",
Name: "hyacinth",
Namespace: namespace,
},
Severity: "info",
Timestamp: metav1.Now(),
Message: "well that happened",
Reason: "event-happened",
ReportingController: "source-controller",
}
event := *eventFixture.DeepCopy()
testSent := func(g *WithT) {
g.THelper()
buf := &bytes.Buffer{}
g.Expect(json.NewEncoder(buf).Encode(&event)).To(Succeed())
res, err := http.Post("http://localhost:56789/", "application/json", buf)
g.Expect(err).ToNot(HaveOccurred())
g.Expect(res.StatusCode).To(Equal(202)) // event_server responds with 202 Accepted
}
testForwarded := func(g *WithT) {
g.THelper()
g.Eventually(func() bool {
return req == nil
}, "2s", "0.1s").Should(BeFalse())
}
testFiltered := func(g *WithT) {
g.THelper()
// The event_server does forwarding in a goroutine, after
// responding to the POST of the event. This makes it
// difficult to know whether the provider has filtered the
// event, or just not run the goroutine yet. For now, I'll use
// a timeout (and Consistently so it can fail early)
g.Consistently(func() bool {
return req == nil
}, "1s", "0.1s").Should(BeTrue())
}
tests := []struct {
name string
modifyEventFunc func(e eventv1.Event) eventv1.Event
forwarded bool
}{
{
name: "forwards when source is a match",
modifyEventFunc: func(e eventv1.Event) eventv1.Event { return e },
forwarded: true,
},
{
name: "drops event when source Kind does not match",
modifyEventFunc: func(e eventv1.Event) eventv1.Event {
e.InvolvedObject.Kind = "GitRepository"
return e
},
forwarded: false,
},
{
name: "drops event when source name does not match",
modifyEventFunc: func(e eventv1.Event) eventv1.Event {
e.InvolvedObject.Name = "slop"
return e
},
forwarded: false,
},
{
name: "drops event when source namespace does not match",
modifyEventFunc: func(e eventv1.Event) eventv1.Event {
e.InvolvedObject.Namespace = "all-buckets"
return e
},
forwarded: false,
},
{
name: "drops event that is matched by exclusion",
modifyEventFunc: func(e eventv1.Event) eventv1.Event {
e.Message = "this is excluded"
return e
},
forwarded: false,
},
{
name: "forwards events when name wildcard is used",
modifyEventFunc: func(e eventv1.Event) eventv1.Event {
e.InvolvedObject.Kind = "Kustomization"
e.InvolvedObject.Name = "test"
e.InvolvedObject.Namespace = namespace
e.Message = "test"
return e
},
forwarded: true,
},
{
name: "forwards events when the label matches",
modifyEventFunc: func(e eventv1.Event) eventv1.Event {
e.InvolvedObject.Kind = "GitRepository"
e.InvolvedObject.Name = "podinfo"
e.InvolvedObject.APIVersion = "source.toolkit.fluxcd.io/v1"
e.InvolvedObject.Namespace = namespace
e.Message = "test"
return e
},
forwarded: true,
},
{
name: "drops events when the labels don't match",
modifyEventFunc: func(e eventv1.Event) eventv1.Event {
e.InvolvedObject.Kind = "GitRepository"
e.InvolvedObject.Name = "podinfo-two"
e.InvolvedObject.APIVersion = "source.toolkit.fluxcd.io/v1"
e.InvolvedObject.Namespace = namespace
e.Message = "test"
return e
},
forwarded: false,
},
{
name: "drops events for cross-namespace sources",
modifyEventFunc: func(e eventv1.Event) eventv1.Event {
e.InvolvedObject.Kind = "Kustomization"
e.InvolvedObject.Name = "test"
e.InvolvedObject.Namespace = "test"
e.Message = "test"
return e
},
forwarded: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
// Reset the common variables to their fixture value.
req = nil
event = *eventFixture.DeepCopy()
event = tt.modifyEventFunc(event)
testSent(g)
if tt.forwarded {
testForwarded(g)
} else {
testFiltered(g)
}
})
}
// update alert for testing inclusion list
var obj apiv1beta2.Alert
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(alert), &obj)).To(Succeed())
inclusionAlert.ResourceVersion = obj.ResourceVersion
g.Expect(k8sClient.Update(context.Background(), inclusionAlert)).To(Succeed())
// wait for ready
g.Eventually(func() bool {
var obj apiv1beta2.Alert
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(inclusionAlert), &obj))
return conditions.IsReady(&obj)
}, 30*time.Second, time.Second).Should(BeTrue())
// An event fixture to set the initial fixed state of an Event which is
// modified in the test cases.
eventFixture2 := eventv1.Event{
InvolvedObject: corev1.ObjectReference{
Kind: "Bucket",
Name: "hyacinth",
Namespace: namespace,
},
Severity: "info",
Timestamp: metav1.Now(),
Message: "included",
Reason: "event-happened",
ReportingController: "source-controller",
}
event = *eventFixture2.DeepCopy()
tests = []struct {
name string
modifyEventFunc func(e eventv1.Event) eventv1.Event
forwarded bool
}{
{
name: "forwards when message matches inclusion list",
modifyEventFunc: func(e eventv1.Event) eventv1.Event { return e },
forwarded: true,
},
{
name: "drops when message does not match inclusion list",
modifyEventFunc: func(e eventv1.Event) eventv1.Event {
e.Message = "not included"
return e
},
forwarded: false,
},
{
name: "drops when message matches inclusion list and exclusion list",
modifyEventFunc: func(e eventv1.Event) eventv1.Event {
e.Message = "included excluded"
return e
},
forwarded: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
// Reset the common variables to their fixture value.
req = nil
event = *eventFixture2.DeepCopy()
event = tt.modifyEventFunc(event)
testSent(g)
if tt.forwarded {
testForwarded(g)
} else {
testFiltered(g)
}
})
}
}
return false
}, timeout).Should(BeTrue())
}

View File

@ -0,0 +1,50 @@
/*
Copyright 2023 The Flux authors
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 controller
import (
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/predicate"
apiv1 "github.com/fluxcd/notification-controller/api/v1"
)
// finalizerPredicate implements predicate functions to allow events for objects
// that have the flux finalizer.
type finalizerPredicate struct {
predicate.Funcs
}
// Create allows events for objects with flux finalizer that have beed created.
func (finalizerPredicate) Create(e event.CreateEvent) bool {
return controllerutil.ContainsFinalizer(e.Object, apiv1.NotificationFinalizer)
}
// Update allows events for objects with flux finalizer that have been updated.
func (finalizerPredicate) Update(e event.UpdateEvent) bool {
if e.ObjectNew == nil {
return false
}
return controllerutil.ContainsFinalizer(e.ObjectNew, apiv1.NotificationFinalizer)
}
// Delete allows events for objects with flux finalizer that have been marked
// for deletion.
func (finalizerPredicate) Delete(e event.DeleteEvent) bool {
return controllerutil.ContainsFinalizer(e.Object, apiv1.NotificationFinalizer)
}

View File

@ -0,0 +1,165 @@
/*
Copyright 2023 The Flux authors
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 controller
import (
"testing"
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/event"
apiv1 "github.com/fluxcd/notification-controller/api/v1"
apiv1beta3 "github.com/fluxcd/notification-controller/api/v1beta3"
)
func getAlertWithFinalizers(finalizers []string) *apiv1beta3.Alert {
return &apiv1beta3.Alert{
ObjectMeta: metav1.ObjectMeta{
Finalizers: finalizers,
},
}
}
func TestFinalizerPredicateCreate(t *testing.T) {
tests := []struct {
name string
object client.Object
want bool
}{
{
name: "no finalizer",
object: getAlertWithFinalizers([]string{}),
want: false,
},
{
name: "no flux finalizer",
object: getAlertWithFinalizers([]string{"foo.bar", "baz.bar"}),
want: false,
},
{
name: "has flux finalizer",
object: getAlertWithFinalizers([]string{"foo.bar", apiv1.NotificationFinalizer, "baz.bar"}),
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
event := event.CreateEvent{
Object: tt.object,
}
mp := finalizerPredicate{}
g.Expect(mp.Create(event)).To(Equal(tt.want))
})
}
}
func TestFinalizerPredicateDelete(t *testing.T) {
tests := []struct {
name string
object client.Object
want bool
}{
{
name: "no finalizer",
object: getAlertWithFinalizers([]string{}),
want: false,
},
{
name: "no flux finalizer",
object: getAlertWithFinalizers([]string{"foo.bar", "baz.bar"}),
want: false,
},
{
name: "has flux finalizer",
object: getAlertWithFinalizers([]string{"foo.bar", apiv1.NotificationFinalizer, "baz.bar"}),
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
event := event.DeleteEvent{
Object: tt.object,
}
mp := finalizerPredicate{}
g.Expect(mp.Delete(event)).To(Equal(tt.want))
})
}
}
func TestFinalizerPredicateUpdate(t *testing.T) {
tests := []struct {
name string
oldObject client.Object
newObject client.Object
want bool
}{
{
name: "no new object",
oldObject: getAlertWithFinalizers([]string{apiv1.NotificationFinalizer}),
newObject: nil,
want: false,
},
{
name: "no old object, new object without flux finalizer",
oldObject: nil,
newObject: getAlertWithFinalizers([]string{"foo.bar"}),
want: false,
},
{
name: "no old object, new object with flux finalizer",
oldObject: nil,
newObject: getAlertWithFinalizers([]string{apiv1.NotificationFinalizer}),
want: true,
},
{
name: "old and new objects with flux finalizer",
oldObject: getAlertWithFinalizers([]string{"foo.bar", apiv1.NotificationFinalizer, "baz.bar"}),
newObject: getAlertWithFinalizers([]string{"foo.bar", apiv1.NotificationFinalizer, "baz.bar"}),
want: true,
},
{
name: "old object with flux finalizer, new object without",
oldObject: getAlertWithFinalizers([]string{"foo.bar", apiv1.NotificationFinalizer, "baz.bar"}),
newObject: getAlertWithFinalizers([]string{"foo.bar", "baz.bar"}),
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
event := event.UpdateEvent{
ObjectOld: tt.oldObject,
ObjectNew: tt.newObject,
}
mp := finalizerPredicate{}
g.Expect(mp.Update(event)).To(Equal(tt.want))
})
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2022 The Flux authors
Copyright 2023 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -18,317 +18,81 @@ package controller
import (
"context"
"crypto/x509"
"fmt"
"net/url"
"time"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
kerrors "k8s.io/apimachinery/pkg/util/errors"
kuberecorder "k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/ratelimiter"
"sigs.k8s.io/yaml"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/runtime/conditions"
helper "github.com/fluxcd/pkg/runtime/controller"
"github.com/fluxcd/pkg/runtime/patch"
"github.com/fluxcd/pkg/runtime/predicates"
apiv1 "github.com/fluxcd/notification-controller/api/v1"
apiv1beta2 "github.com/fluxcd/notification-controller/api/v1beta2"
apiv1beta3 "github.com/fluxcd/notification-controller/api/v1beta3"
"github.com/fluxcd/pkg/cache"
"github.com/fluxcd/pkg/runtime/patch"
"github.com/fluxcd/notification-controller/internal/notifier"
)
// ProviderReconciler reconciles a Provider object
// +kubebuilder:rbac:groups=notification.toolkit.fluxcd.io,resources=providers,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
// +kubebuilder:rbac:groups="",resources=serviceaccounts/token,verbs=create
// ProviderReconciler reconciles a Provider object to migrate it to static
// Provider.
type ProviderReconciler struct {
client.Client
helper.Metrics
kuberecorder.EventRecorder
ControllerName string
}
type ProviderReconcilerOptions struct {
RateLimiter ratelimiter.RateLimiter
TokenCache *cache.TokenCache
}
func (r *ProviderReconciler) SetupWithManager(mgr ctrl.Manager) error {
return r.SetupWithManagerAndOptions(mgr, ProviderReconcilerOptions{})
}
func (r *ProviderReconciler) SetupWithManagerAndOptions(mgr ctrl.Manager, opts ProviderReconcilerOptions) error {
return ctrl.NewControllerManagedBy(mgr).
For(&apiv1beta2.Provider{}, builder.WithPredicates(
predicate.Or(predicate.GenerationChangedPredicate{}, predicates.ReconcileRequestedPredicate{}),
)).
WithOptions(controller.Options{
RateLimiter: opts.RateLimiter,
}).
For(&apiv1beta3.Provider{}, builder.WithPredicates(providerPredicate{})).
Complete(r)
}
// +kubebuilder:rbac:groups=notification.toolkit.fluxcd.io,resources=providers,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=notification.toolkit.fluxcd.io,resources=providers/status,verbs=get;update;patch
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
func (r *ProviderReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, retErr error) {
reconcileStart := time.Now()
log := ctrl.LoggerFrom(ctx)
obj := &apiv1beta2.Provider{}
obj := &apiv1beta3.Provider{}
if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// Initialize the runtime patcher with the current version of the object.
patcher := patch.NewSerialPatcher(obj, r.Client)
patcher, err := patch.NewHelper(obj, r.Client)
if err != nil {
return ctrl.Result{}, err
}
defer func() {
// Patch finalizers, status and conditions.
if err := r.patch(ctx, obj, patcher); err != nil {
retErr = kerrors.NewAggregate([]error{retErr, err})
}
// Record Prometheus metrics.
r.Metrics.RecordReadiness(ctx, obj)
r.Metrics.RecordDuration(ctx, obj, reconcileStart)
r.Metrics.RecordSuspend(ctx, obj, obj.Spec.Suspend)
// Emit warning event if the reconciliation failed.
if retErr != nil {
r.Event(obj, corev1.EventTypeWarning, meta.FailedReason, retErr.Error())
}
// Log the staleness error and pause reconciliation until spec changes.
if conditions.IsStalled(obj) {
result = ctrl.Result{Requeue: false}
log.Error(retErr, "Reconciliation has stalled")
retErr = nil
return
}
// Log and emit success event.
if retErr == nil && conditions.IsReady(obj) {
msg := fmt.Sprintf("Reconciliation finished, next run in %s",
obj.GetInterval().String())
log.Info(msg)
r.Event(obj, corev1.EventTypeNormal, meta.SucceededReason, msg)
if err := patcher.Patch(ctx, obj); err != nil {
retErr = err
}
}()
// Examine if the object is under deletion.
if !obj.ObjectMeta.DeletionTimestamp.IsZero() {
controllerutil.RemoveFinalizer(obj, apiv1.NotificationFinalizer)
result = ctrl.Result{}
return
return r.reconcileDelete(obj)
}
// Add finalizer first if not exist to avoid the race condition
// between init and delete.
// Note: Finalizers in general can only be added when the deletionTimestamp
// is not set.
// Add finalizer if it doesn't exist.
if !controllerutil.ContainsFinalizer(obj, apiv1.NotificationFinalizer) {
controllerutil.AddFinalizer(obj, apiv1.NotificationFinalizer)
result = ctrl.Result{Requeue: true}
return
}
// Return early if the object is suspended.
if obj.Spec.Suspend {
log.Info("Reconciliation is suspended for this object")
return ctrl.Result{}, nil
}
return r.reconcile(ctx, obj)
return
}
func (r *ProviderReconciler) reconcile(ctx context.Context, obj *apiv1beta2.Provider) (ctrl.Result, error) {
// Mark the resource as under reconciliation.
conditions.MarkReconciling(obj, meta.ProgressingReason, "Reconciliation in progress")
conditions.Delete(obj, meta.StalledCondition)
// reconcileDelete handles the deletion of the object.
// It cleans up the caches and removes the finalizer.
func (r *ProviderReconciler) reconcileDelete(obj *apiv1beta3.Provider) (ctrl.Result, error) {
// Remove our finalizer from the list
controllerutil.RemoveFinalizer(obj, apiv1.NotificationFinalizer)
// Mark the reconciliation as stalled if the inline URL and/or proxy are invalid.
if err := r.validateURLs(obj); err != nil {
conditions.MarkFalse(obj, meta.ReadyCondition, meta.InvalidURLReason, err.Error())
conditions.MarkTrue(obj, meta.StalledCondition, meta.InvalidURLReason, err.Error())
return ctrl.Result{Requeue: true}, err
}
// Cleanup caches.
r.TokenCache.DeleteEventsForObject(apiv1beta3.ProviderKind,
obj.GetName(), obj.GetNamespace(), notifier.OperationPost)
// Validate the provider credentials.
if err := r.validateCredentials(ctx, obj); err != nil {
conditions.MarkFalse(obj, meta.ReadyCondition, apiv1.ValidationFailedReason, err.Error())
return ctrl.Result{Requeue: true}, err
}
conditions.MarkTrue(obj, meta.ReadyCondition, meta.SucceededReason, apiv1.InitializedReason)
return ctrl.Result{RequeueAfter: obj.GetInterval()}, nil
}
func (r *ProviderReconciler) validateURLs(provider *apiv1beta2.Provider) error {
address := provider.Spec.Address
proxy := provider.Spec.Proxy
if provider.Spec.SecretRef == nil {
if _, err := url.ParseRequestURI(address); err != nil {
return fmt.Errorf("invalid address %s: %w", address, err)
}
if _, err := url.ParseRequestURI(proxy); proxy != "" && err != nil {
return fmt.Errorf("invalid proxy %s: %w", proxy, err)
}
}
return nil
}
func (r *ProviderReconciler) validateCredentials(ctx context.Context, provider *apiv1beta2.Provider) error {
log := ctrl.LoggerFrom(ctx)
address := provider.Spec.Address
proxy := provider.Spec.Proxy
username := provider.Spec.Username
password := ""
token := ""
headers := make(map[string]string)
if provider.Spec.SecretRef != nil {
var secret corev1.Secret
secretName := types.NamespacedName{Namespace: provider.Namespace, Name: provider.Spec.SecretRef.Name}
if err := r.Get(ctx, secretName, &secret); err != nil {
return fmt.Errorf("failed to read secret, error: %w", err)
}
if a, ok := secret.Data["address"]; ok {
address = string(a)
}
if p, ok := secret.Data["password"]; ok {
password = string(p)
}
if p, ok := secret.Data["proxy"]; ok {
proxy = string(p)
}
if t, ok := secret.Data["token"]; ok {
token = string(t)
}
if u, ok := secret.Data["username"]; ok {
username = string(u)
}
if h, ok := secret.Data["headers"]; ok {
err := yaml.Unmarshal(h, headers)
if err != nil {
return fmt.Errorf("failed to read headers from secret, error: %w", err)
}
}
}
if address == "" {
return fmt.Errorf("no address found in 'spec.address' nor in `spec.secretRef`")
}
var certPool *x509.CertPool
if provider.Spec.CertSecretRef != nil {
var secret corev1.Secret
secretName := types.NamespacedName{Namespace: provider.Namespace, Name: provider.Spec.CertSecretRef.Name}
if err := r.Get(ctx, secretName, &secret); err != nil {
return fmt.Errorf("failed to read secret, error: %w", err)
}
switch secret.Type {
case corev1.SecretTypeOpaque, corev1.SecretTypeTLS, "":
default:
return fmt.Errorf("cannot use secret '%s' to get TLS certificate: invalid secret type: '%s'", secret.Name, secret.Type)
}
caFile, ok := secret.Data["ca.crt"]
if !ok {
caFile, ok = secret.Data["caFile"]
if !ok {
return fmt.Errorf("no 'ca.crt' key found in secret '%s'", provider.Spec.CertSecretRef.Name)
}
log.Info("warning: specifying CA cert via 'caFile' is deprecated, please use 'ca.crt' instead")
}
certPool = x509.NewCertPool()
ok = certPool.AppendCertsFromPEM(caFile)
if !ok {
return fmt.Errorf("could not append to cert pool: invalid CA found in %s", provider.Spec.CertSecretRef.Name)
}
}
factory := notifier.NewFactory(address, proxy, username, provider.Spec.Channel, token, headers, certPool, password, string(provider.UID))
if _, err := factory.Notifier(provider.Spec.Type); err != nil {
return fmt.Errorf("failed to initialize provider, error: %w", err)
}
return nil
}
// patch updates the object status, conditions and finalizers.
func (r *ProviderReconciler) patch(ctx context.Context, obj *apiv1beta2.Provider, patcher *patch.SerialPatcher) (retErr error) {
// Configure the runtime patcher.
patchOpts := []patch.Option{}
ownedConditions := []string{
meta.ReadyCondition,
meta.ReconcilingCondition,
meta.StalledCondition,
}
patchOpts = append(patchOpts,
patch.WithOwnedConditions{Conditions: ownedConditions},
patch.WithForceOverwriteConditions{},
patch.WithFieldOwner(r.ControllerName),
)
// Set the value of the reconciliation request in status.
if v, ok := meta.ReconcileAnnotationValue(obj.GetAnnotations()); ok {
obj.Status.LastHandledReconcileAt = v
}
// Remove the Reconciling/Stalled condition and update the observed generation
// if the reconciliation was successful.
if conditions.IsTrue(obj, meta.ReadyCondition) {
conditions.Delete(obj, meta.ReconcilingCondition)
conditions.Delete(obj, meta.StalledCondition)
obj.Status.ObservedGeneration = obj.Generation
}
// Set the Reconciling reason to ProgressingWithRetry if the
// reconciliation has failed.
if conditions.IsFalse(obj, meta.ReadyCondition) &&
conditions.Has(obj, meta.ReconcilingCondition) {
rc := conditions.Get(obj, meta.ReconcilingCondition)
rc.Reason = meta.ProgressingWithRetryReason
conditions.Set(obj, rc)
}
// Remove the Reconciling condition if the reconciliation has stalled.
if conditions.Has(obj, meta.StalledCondition) {
conditions.Delete(obj, meta.ReconcilingCondition)
}
// Patch the object status, conditions and finalizers.
if err := patcher.Patch(ctx, obj, patchOpts...); err != nil {
if !obj.GetDeletionTimestamp().IsZero() {
err = kerrors.FilterOut(err, func(e error) bool { return apierrors.IsNotFound(e) })
}
retErr = kerrors.NewAggregate([]error{retErr, err})
if retErr != nil {
return retErr
}
}
return nil
// Stop reconciliation as the object is being deleted
return ctrl.Result{}, nil
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2022 The Flux authors
Copyright 2023 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -17,320 +17,153 @@ limitations under the License.
package controller
import (
"context"
"fmt"
"os"
"testing"
"time"
"github.com/fluxcd/pkg/runtime/patch"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/runtime/conditions"
"github.com/fluxcd/pkg/runtime/patch"
apiv1 "github.com/fluxcd/notification-controller/api/v1"
apiv1beta2 "github.com/fluxcd/notification-controller/api/v1beta2"
apiv1beta3 "github.com/fluxcd/notification-controller/api/v1beta3"
)
func TestProviderReconciler_deleteBeforeFinalizer(t *testing.T) {
func TestProviderReconciler(t *testing.T) {
g := NewWithT(t)
namespaceName := "provider-" + randStringRunes(5)
namespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{Name: namespaceName},
}
g.Expect(k8sClient.Create(ctx, namespace)).ToNot(HaveOccurred())
timeout := 10 * time.Second
testns, err := testEnv.CreateNamespace(ctx, "provider-test")
g.Expect(err).ToNot(HaveOccurred())
t.Cleanup(func() {
g.Expect(k8sClient.Delete(ctx, namespace)).NotTo(HaveOccurred())
g.Expect(testEnv.Cleanup(ctx, testns)).ToNot(HaveOccurred())
})
provider := &apiv1beta2.Provider{}
provider.Name = "test-provider"
provider.Namespace = namespaceName
provider.Spec.Type = "slack"
// Add a test finalizer to prevent the object from getting deleted.
provider.SetFinalizers([]string{"test-finalizer"})
g.Expect(k8sClient.Create(ctx, provider)).NotTo(HaveOccurred())
// Add deletion timestamp by deleting the object.
g.Expect(k8sClient.Delete(ctx, provider)).NotTo(HaveOccurred())
r := &ProviderReconciler{
Client: k8sClient,
EventRecorder: record.NewFakeRecorder(32),
}
// NOTE: Only a real API server responds with an error in this scenario.
_, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: client.ObjectKeyFromObject(provider)})
g.Expect(err).NotTo(HaveOccurred())
}
func TestProviderReconciler_Reconcile(t *testing.T) {
g := NewWithT(t)
timeout := 5 * time.Second
resultP := &apiv1beta2.Provider{}
namespaceName := "provider-" + randStringRunes(5)
secretName := "secret-" + randStringRunes(5)
g.Expect(createNamespace(namespaceName)).NotTo(HaveOccurred(), "failed to create test namespace")
providerKey := types.NamespacedName{
Name: fmt.Sprintf("provider-%s", randStringRunes(5)),
Namespace: namespaceName,
}
provider := &apiv1beta2.Provider{
provider := &apiv1beta3.Provider{
ObjectMeta: metav1.ObjectMeta{
Name: providerKey.Name,
Namespace: providerKey.Namespace,
},
Spec: apiv1beta2.ProviderSpec{
Type: "generic",
Address: "https://webhook.internal",
Name: fmt.Sprintf("provider-%s", randStringRunes(5)),
Namespace: testns.Name,
},
}
g.Expect(k8sClient.Create(context.Background(), provider)).To(Succeed())
providerKey := client.ObjectKeyFromObject(provider)
t.Run("reports ready status", func(t *testing.T) {
g := NewWithT(t)
// Create without finalizer.
provider.Spec = apiv1beta3.ProviderSpec{
Type: "generic",
}
g.Expect(testEnv.Create(ctx, provider)).ToNot(HaveOccurred())
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)
return resultP.Status.ObservedGeneration == resultP.Generation
}, timeout, time.Second).Should(BeTrue())
// Should eventually have finalizer.
g.Eventually(func() bool {
_ = testEnv.Get(ctx, providerKey, provider)
return controllerutil.ContainsFinalizer(provider, apiv1.NotificationFinalizer)
}, timeout, time.Second).Should(BeTrue())
g.Expect(conditions.IsReady(resultP)).To(BeTrue())
g.Expect(conditions.GetReason(resultP, meta.ReadyCondition)).To(BeIdenticalTo(meta.SucceededReason))
// Remove finalizer.
patchHelper, err := patch.NewHelper(provider, testEnv.Client)
g.Expect(err).ToNot(HaveOccurred())
controllerutil.RemoveFinalizer(provider, apiv1.NotificationFinalizer)
g.Expect(patchHelper.Patch(ctx, provider)).ToNot(HaveOccurred())
g.Expect(conditions.Has(resultP, meta.ReconcilingCondition)).To(BeFalse())
g.Expect(controllerutil.ContainsFinalizer(resultP, apiv1.NotificationFinalizer)).To(BeTrue())
})
// Should eventually have finalizer again.
g.Eventually(func() bool {
_ = testEnv.Get(ctx, providerKey, provider)
return controllerutil.ContainsFinalizer(provider, apiv1.NotificationFinalizer)
}, timeout, time.Second).Should(BeTrue())
t.Run("fails with secret not found error", func(t *testing.T) {
g := NewWithT(t)
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)).To(Succeed())
resultP.Spec.SecretRef = &meta.LocalObjectReference{
Name: secretName,
}
g.Expect(k8sClient.Update(context.Background(), resultP)).To(Succeed())
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)
return !conditions.IsReady(resultP)
}, timeout, time.Second).Should(BeTrue())
g.Expect(conditions.GetReason(resultP, meta.ReadyCondition)).To(BeIdenticalTo(apiv1.ValidationFailedReason))
g.Expect(conditions.GetMessage(resultP, meta.ReadyCondition)).To(ContainSubstring(secretName))
g.Expect(conditions.Has(resultP, meta.ReconcilingCondition)).To(BeTrue())
g.Expect(conditions.GetReason(resultP, meta.ReconcilingCondition)).To(BeIdenticalTo(meta.ProgressingWithRetryReason))
g.Expect(conditions.GetObservedGeneration(resultP, meta.ReconcilingCondition)).To(BeIdenticalTo(resultP.Generation))
g.Expect(resultP.Status.ObservedGeneration).To(BeIdenticalTo(resultP.Generation - 1))
})
t.Run("recovers when secret exists", func(t *testing.T) {
g := NewWithT(t)
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: namespaceName,
},
StringData: map[string]string{
"token": "test",
},
}
g.Expect(k8sClient.Create(context.Background(), secret)).To(Succeed())
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)
return conditions.IsReady(resultP)
}, timeout, time.Second).Should(BeTrue())
g.Expect(conditions.GetObservedGeneration(resultP, meta.ReadyCondition)).To(BeIdenticalTo(resultP.Generation))
g.Expect(resultP.Status.ObservedGeneration).To(BeIdenticalTo(resultP.Generation))
g.Expect(conditions.Has(resultP, meta.ReconcilingCondition)).To(BeFalse())
})
t.Run("handles reconcileAt", func(t *testing.T) {
g := NewWithT(t)
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)).To(Succeed())
reconcileRequestAt := metav1.Now().String()
resultP.SetAnnotations(map[string]string{
meta.ReconcileRequestAnnotation: reconcileRequestAt,
})
g.Expect(k8sClient.Update(context.Background(), resultP)).To(Succeed())
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)
return resultP.Status.LastHandledReconcileAt == reconcileRequestAt
}, timeout, time.Second).Should(BeTrue())
})
t.Run("becomes stalled on invalid proxy", func(t *testing.T) {
g := NewWithT(t)
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)).To(Succeed())
resultP.Spec.SecretRef = nil
resultP.Spec.Proxy = "https://proxy.internal|"
g.Expect(k8sClient.Update(context.Background(), resultP)).To(Succeed())
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)
return !conditions.IsReady(resultP)
}, timeout, time.Second).Should(BeTrue())
g.Expect(conditions.Has(resultP, meta.ReconcilingCondition)).To(BeFalse())
g.Expect(conditions.Has(resultP, meta.StalledCondition)).To(BeTrue())
g.Expect(conditions.GetObservedGeneration(resultP, meta.StalledCondition)).To(BeIdenticalTo(resultP.Generation))
g.Expect(conditions.GetReason(resultP, meta.StalledCondition)).To(BeIdenticalTo(meta.InvalidURLReason))
g.Expect(conditions.GetReason(resultP, meta.ReadyCondition)).To(BeIdenticalTo(meta.InvalidURLReason))
})
t.Run("recovers from staleness", func(t *testing.T) {
g := NewWithT(t)
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)).To(Succeed())
resultP.Spec.Proxy = "https://proxy.internal"
g.Expect(k8sClient.Update(context.Background(), resultP)).To(Succeed())
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)
return conditions.IsReady(resultP)
}, timeout, time.Second).Should(BeTrue())
g.Expect(conditions.Has(resultP, meta.ReconcilingCondition)).To(BeFalse())
g.Expect(conditions.Has(resultP, meta.StalledCondition)).To(BeFalse())
})
t.Run("finalizes suspended object", func(t *testing.T) {
g := NewWithT(t)
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)).To(Succeed())
patchHelper, err := patch.NewHelper(resultP, k8sClient)
g.Expect(err).ToNot(HaveOccurred())
resultP.Spec.Suspend = true
g.Expect(patchHelper.Patch(context.Background(), resultP)).ToNot(HaveOccurred())
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)
return resultP.Spec.Suspend == true
}, timeout, time.Second).Should(BeTrue())
g.Expect(k8sClient.Delete(context.Background(), resultP)).To(Succeed())
g.Eventually(func() bool {
err := k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), resultP)
// Delete the object and verify.
g.Expect(testEnv.Delete(ctx, provider)).ToNot(HaveOccurred())
g.Eventually(func() bool {
if err := testEnv.Get(ctx, providerKey, provider); err != nil {
return apierrors.IsNotFound(err)
}, timeout, time.Second).Should(BeTrue())
})
}
return false
}, timeout).Should(BeTrue())
}
func TestProviderReconciler_Reconcile_cacert(t *testing.T) {
g := NewWithT(t)
namespaceName := "provider-" + randStringRunes(5)
secretName := "ca-secret-" + randStringRunes(5)
caCrt, err := os.ReadFile("./testdata/certs/ca.pem")
g.Expect(err).To(Not(HaveOccurred()))
g.Expect(createNamespace(namespaceName)).NotTo(HaveOccurred(), "failed to create test namespace")
providerKey := types.NamespacedName{
Name: fmt.Sprintf("provider-%s", randStringRunes(5)),
Namespace: namespaceName,
}
provider := &apiv1beta2.Provider{
ObjectMeta: metav1.ObjectMeta{
Name: providerKey.Name,
Namespace: providerKey.Namespace,
func TestProviderReconciler_APIServerValidation(t *testing.T) {
tests := []struct {
name string
providerType string
commitStatusExpr string
err string
}{
{
name: "github provider types can create providers with commitStatusExpr",
providerType: "github",
commitStatusExpr: "event.metadata.namespace + '/' + event.metadata.name + '/' + provider.metadata.uid",
},
Spec: apiv1beta2.ProviderSpec{
Type: "generic",
Address: "https://webhook.internal",
CertSecretRef: &meta.LocalObjectReference{Name: secretName},
{
name: "gitlab provider types can create providers with commitStatusExpr",
providerType: "gitlab",
commitStatusExpr: "event.metadata.namespace + '/' + event.metadata.name + '/' + provider.metadata.uid",
},
{
name: "gitea provider types can create providers with commitStatusExpr",
providerType: "gitea",
commitStatusExpr: "event.metadata.namespace + '/' + event.metadata.name + '/' + provider.metadata.uid",
},
{
name: "bitbucketserver provider types can create providers with commitStatusExpr",
providerType: "bitbucketserver",
commitStatusExpr: "event.metadata.namespace + '/' + event.metadata.name + '/' + provider.metadata.uid",
},
{
name: "bitbucket provider types can create providers with commitStatusExpr",
providerType: "bitbucket",
commitStatusExpr: "event.metadata.namespace + '/' + event.metadata.name + '/' + provider.metadata.uid",
},
{
name: "azuredevops provider types can create providers with commitStatusExpr",
providerType: "azuredevops",
commitStatusExpr: "event.metadata.namespace + '/' + event.metadata.name + '/' + provider.metadata.uid",
},
{
name: "unsupported provider types cannot create providers with commitStatusExpr",
providerType: "slack",
commitStatusExpr: "event.metadata.namespace + '/' + event.metadata.name + '/' + provider.metadata.uid",
err: "spec.commitStatusExpr is only supported for the 'github', 'gitlab', 'gitea', 'bitbucketserver', 'bitbucket', 'azuredevops' provider types",
},
{
name: "github provider types can create providers without commitStatusExpr",
providerType: "github",
commitStatusExpr: "",
},
}
g.Expect(k8sClient.Create(context.Background(), provider)).To(Succeed())
certSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: providerKey.Namespace,
},
Data: map[string][]byte{
"caFile": []byte("invalid byte"),
"ca.crt": caCrt,
},
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
obj := &apiv1beta3.Provider{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "provider-reconcile-",
Namespace: "default",
},
Spec: apiv1beta3.ProviderSpec{
Type: tt.providerType,
CommitStatusExpr: tt.commitStatusExpr,
},
}
err := testEnv.Create(ctx, obj)
if err == nil {
defer func() {
err := testEnv.Delete(ctx, obj)
g.Expect(err).ToNot(HaveOccurred())
}()
}
if tt.err != "" {
g.Expect(err.Error()).To(ContainSubstring(tt.err))
} else {
g.Expect(err).NotTo(HaveOccurred())
}
})
}
g.Expect(k8sClient.Create(context.Background(), certSecret)).To(Succeed())
r := &ProviderReconciler{
Client: k8sClient,
EventRecorder: record.NewFakeRecorder(32),
}
t.Run("uses `ca.crt` instead of deprecated `caFile`", func(t *testing.T) {
g := NewWithT(t)
_, err = r.Reconcile(ctx, ctrl.Request{NamespacedName: client.ObjectKeyFromObject(provider)})
g.Expect(err).NotTo(HaveOccurred())
})
t.Run("works if only deprecated `caFile` is specified", func(t *testing.T) {
g := NewWithT(t)
clusterCertSecret := &corev1.Secret{}
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(certSecret), clusterCertSecret)).To(Succeed())
patchHelper, err := patch.NewHelper(clusterCertSecret, k8sClient)
g.Expect(err).ToNot(HaveOccurred())
clusterCertSecret.Data = map[string][]byte{
"caFile": caCrt,
}
g.Expect(patchHelper.Patch(context.Background(), clusterCertSecret)).ToNot(HaveOccurred())
_, err = r.Reconcile(ctx, ctrl.Request{NamespacedName: client.ObjectKeyFromObject(provider)})
g.Expect(err).NotTo(HaveOccurred())
})
t.Run("returns error with certSecretRef of the wrong type", func(t *testing.T) {
g := NewWithT(t)
dockerSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "docker-secret",
Namespace: providerKey.Namespace,
},
Type: corev1.DockerConfigJsonKey,
}
g.Expect(k8sClient.Create(context.Background(), dockerSecret)).To(Succeed())
clusterProvider := &apiv1beta2.Provider{}
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(provider), clusterProvider)).To(Succeed())
patchHelper, err := patch.NewHelper(clusterProvider, k8sClient)
g.Expect(err).ToNot(HaveOccurred())
clusterProvider.Spec.CertSecretRef = &meta.LocalObjectReference{
Name: dockerSecret.Name,
}
g.Expect(patchHelper.Patch(context.Background(), clusterProvider)).ToNot(HaveOccurred())
_, err = r.Reconcile(ctx, ctrl.Request{NamespacedName: client.ObjectKeyFromObject(provider)})
g.Expect(err).To(HaveOccurred())
g.Expect(err.Error()).To(ContainSubstring("invalid secret type"))
})
}

View File

@ -0,0 +1,48 @@
/*
Copyright 2025 The Flux authors
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 controller
import (
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/event"
apiv1 "github.com/fluxcd/notification-controller/api/v1"
apiv1beta3 "github.com/fluxcd/notification-controller/api/v1beta3"
)
// providerPredicate implements predicate functions for the Provider API.
type providerPredicate struct{}
func (providerPredicate) Create(e event.CreateEvent) bool {
return !controllerutil.ContainsFinalizer(e.Object, apiv1.NotificationFinalizer)
}
func (providerPredicate) Update(e event.UpdateEvent) bool {
if e.ObjectNew == nil {
return false
}
return !controllerutil.ContainsFinalizer(e.ObjectNew, apiv1.NotificationFinalizer) ||
!e.ObjectNew.(*apiv1beta3.Provider).ObjectMeta.DeletionTimestamp.IsZero()
}
func (providerPredicate) Delete(e event.DeleteEvent) bool {
return false
}
func (providerPredicate) Generic(e event.GenericEvent) bool {
return !controllerutil.ContainsFinalizer(e.Object, apiv1.NotificationFinalizer)
}

View File

@ -26,13 +26,15 @@ import (
"k8s.io/apimachinery/pkg/types"
kerrors "k8s.io/apimachinery/pkg/util/errors"
kuberecorder "k8s.io/client-go/tools/record"
"k8s.io/client-go/util/workqueue"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/ratelimiter"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/runtime/conditions"
@ -54,13 +56,20 @@ type ReceiverReconciler struct {
}
type ReceiverReconcilerOptions struct {
RateLimiter ratelimiter.RateLimiter
RateLimiter workqueue.TypedRateLimiter[reconcile.Request]
WatchConfigsPredicate predicate.Predicate
}
func (r *ReceiverReconciler) SetupWithManager(mgr ctrl.Manager) error {
return r.SetupWithManagerAndOptions(mgr, ReceiverReconcilerOptions{})
return r.SetupWithManagerAndOptions(mgr, ReceiverReconcilerOptions{
WatchConfigsPredicate: predicate.Not(predicate.Funcs{}),
})
}
const (
secretRefIndex = ".metadata.secretRef"
)
func (r *ReceiverReconciler) SetupWithManagerAndOptions(mgr ctrl.Manager, opts ReceiverReconcilerOptions) error {
// This index is used to list Receivers by their webhook path after the receiver server
// gets a request.
@ -68,16 +77,60 @@ func (r *ReceiverReconciler) SetupWithManagerAndOptions(mgr ctrl.Manager, opts R
server.WebhookPathIndexKey, server.IndexReceiverWebhookPath); err != nil {
return err
}
// Index receivers by the secret reference, so that we can enqueue
// Receiver requests when the referenced Secret is changed.
if err := mgr.GetFieldIndexer().IndexField(context.Background(), &apiv1.Receiver{},
secretRefIndex, func(obj client.Object) []string {
receiver := obj.(*apiv1.Receiver)
return []string{fmt.Sprintf("%s/%s", receiver.GetNamespace(), receiver.Spec.SecretRef.Name)}
}); err != nil {
}
return ctrl.NewControllerManagedBy(mgr).
For(&apiv1.Receiver{}, builder.WithPredicates(
predicate.Or(predicate.GenerationChangedPredicate{}, predicates.ReconcileRequestedPredicate{}),
)).
WatchesMetadata(
&corev1.Secret{},
handler.EnqueueRequestsFromMapFunc(r.enqueueRequestsForChangeOf),
builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}, opts.WatchConfigsPredicate),
).
WithOptions(controller.Options{
RateLimiter: opts.RateLimiter,
}).
Complete(r)
}
// enqueueRequestsForChangeOf enqueues Receiver requests for changes in referenced Secret objects.
func (r *ReceiverReconciler) enqueueRequestsForChangeOf(ctx context.Context, obj client.Object) []reconcile.Request {
log := ctrl.LoggerFrom(ctx)
// List all Receivers that have the referenced Secret in their spec.
receivers := &apiv1.ReceiverList{}
if err := r.List(ctx, receivers, client.MatchingFields{
secretRefIndex: client.ObjectKeyFromObject(obj).String(),
}); err != nil {
log.Error(err, "failed to list Receivers for change of Secret",
"secretRef", map[string]string{
"name": obj.GetName(),
"namespace": obj.GetNamespace(),
})
return nil
}
requests := make([]reconcile.Request, 0, len(receivers.Items))
for _, receiver := range receivers.Items {
requests = append(requests, reconcile.Request{
NamespacedName: types.NamespacedName{
Name: receiver.Name,
Namespace: receiver.Namespace,
},
})
}
return requests
}
// +kubebuilder:rbac:groups=notification.toolkit.fluxcd.io,resources=receivers,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=notification.toolkit.fluxcd.io,resources=receivers/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=source.fluxcd.io,resources=buckets,verbs=get;list;watch;update;patch
@ -112,9 +165,7 @@ func (r *ReceiverReconciler) Reconcile(ctx context.Context, req ctrl.Request) (r
}
// Record Prometheus metrics.
r.Metrics.RecordReadiness(ctx, obj)
r.Metrics.RecordDuration(ctx, obj, reconcileStart)
r.Metrics.RecordSuspend(ctx, obj, obj.Spec.Suspend)
// Emit warning event if the reconciliation failed.
if retErr != nil {
@ -157,25 +208,40 @@ func (r *ReceiverReconciler) Reconcile(ctx context.Context, req ctrl.Request) (r
// reconcile steps through the actual reconciliation tasks for the object, it returns early on the first step that
// produces an error.
func (r *ReceiverReconciler) reconcile(ctx context.Context, obj *apiv1.Receiver) (ctrl.Result, error) {
log := ctrl.LoggerFrom(ctx)
if filter := obj.Spec.ResourceFilter; filter != "" {
if err := server.ValidateResourceFilter(filter); err != nil {
const msg = "Reconciliation failed terminally due to configuration error"
errMsg := fmt.Sprintf("%s: %v", msg, err)
conditions.MarkFalse(obj, meta.ReadyCondition, meta.InvalidCELExpressionReason, "%s", errMsg)
conditions.MarkStalled(obj, meta.InvalidCELExpressionReason, "%s", errMsg)
obj.Status.ObservedGeneration = obj.Generation
log.Error(err, msg)
r.Event(obj, corev1.EventTypeWarning, meta.InvalidCELExpressionReason, errMsg)
return ctrl.Result{}, nil
}
}
// Mark the resource as under reconciliation.
conditions.MarkReconciling(obj, meta.ProgressingReason, "Reconciliation in progress")
token, err := r.token(ctx, obj)
if err != nil {
conditions.MarkFalse(obj, meta.ReadyCondition, apiv1.TokenNotFoundReason, err.Error())
conditions.MarkFalse(obj, meta.ReadyCondition, apiv1.TokenNotFoundReason, "%s", err)
obj.Status.WebhookPath = ""
return ctrl.Result{Requeue: true}, err
return ctrl.Result{}, err
}
webhookPath := obj.GetWebhookPath(token)
msg := fmt.Sprintf("Receiver initialized for path: %s", webhookPath)
// Mark the resource as ready and set the webhook path in status.
conditions.MarkTrue(obj, meta.ReadyCondition, meta.SucceededReason, msg)
conditions.MarkTrue(obj, meta.ReadyCondition, meta.SucceededReason, "%s", msg)
if obj.Status.WebhookPath != webhookPath {
obj.Status.WebhookPath = webhookPath
ctrl.LoggerFrom(ctx).Info(msg)
log.Info(msg)
}
return ctrl.Result{RequeueAfter: obj.GetInterval()}, nil

View File

@ -144,6 +144,45 @@ func TestReceiverReconciler_Reconcile(t *testing.T) {
g.Expect(resultR.Spec.Interval.Duration).To(BeIdenticalTo(10 * time.Minute))
})
t.Run("fails with invalid CEL resource filter", func(t *testing.T) {
g := NewWithT(t)
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(receiver), resultR)).To(Succeed())
// Incomplete CEL expression
patch := []byte(`{"spec":{"resourceFilter":"has(res.metadata.annotations"}}`)
g.Expect(k8sClient.Patch(context.Background(), resultR, client.RawPatch(types.MergePatchType, patch))).To(Succeed())
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(receiver), resultR)
return !conditions.IsReady(resultR)
}, timeout, time.Second).Should(BeTrue())
g.Expect(resultR.Status.ObservedGeneration).To(Equal(resultR.Generation))
g.Expect(conditions.GetReason(resultR, meta.ReadyCondition)).To(BeIdenticalTo(meta.InvalidCELExpressionReason))
g.Expect(conditions.GetMessage(resultR, meta.ReadyCondition)).To(ContainSubstring("annotations"))
g.Expect(conditions.Has(resultR, meta.StalledCondition)).To(BeTrue())
g.Expect(conditions.GetReason(resultR, meta.StalledCondition)).To(BeIdenticalTo(meta.InvalidCELExpressionReason))
g.Expect(conditions.GetObservedGeneration(resultR, meta.StalledCondition)).To(BeIdenticalTo(resultR.Generation))
})
t.Run("recovers when the CEL expression is valid", func(t *testing.T) {
g := NewWithT(t)
// Incomplete CEL expression
patch := []byte(`{"spec":{"resourceFilter":"has(res.metadata.annotations)"}}`)
g.Expect(k8sClient.Patch(context.Background(), resultR, client.RawPatch(types.MergePatchType, patch))).To(Succeed())
g.Eventually(func() bool {
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(receiver), resultR)
return conditions.IsReady(resultR)
}, timeout, time.Second).Should(BeTrue())
g.Expect(conditions.GetObservedGeneration(resultR, meta.ReadyCondition)).To(BeIdenticalTo(resultR.Generation))
g.Expect(resultR.Status.ObservedGeneration).To(BeIdenticalTo(resultR.Generation))
g.Expect(conditions.Has(resultR, meta.ReconcilingCondition)).To(BeFalse())
})
t.Run("fails with secret not found error", func(t *testing.T) {
g := NewWithT(t)
@ -239,7 +278,7 @@ func TestReceiverReconciler_EventHandler(t *testing.T) {
// Use the client from the manager as the server handler needs to list objects from the cache
// which the "live" k8s client does not have access to.
receiverServer := server.NewReceiverServer("127.0.0.1:56788", logf.Log, testEnv.GetClient())
receiverServer := server.NewReceiverServer("127.0.0.1:56788", logf.Log, testEnv.GetClient(), true, true)
receiverMdlw := middleware.New(middleware.Config{
Recorder: prommetrics.NewRecorder(prommetrics.Config{
Prefix: "gotk_receiver",

View File

@ -31,18 +31,21 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"github.com/fluxcd/cli-utils/pkg/kstatus/polling"
runtimeclient "github.com/fluxcd/pkg/runtime/client"
"github.com/fluxcd/pkg/runtime/controller"
"github.com/fluxcd/pkg/runtime/metrics"
"github.com/fluxcd/pkg/runtime/testenv"
"github.com/fluxcd/pkg/ssa"
ssautil "github.com/fluxcd/pkg/ssa/utils"
apiv1 "github.com/fluxcd/notification-controller/api/v1"
apiv1b2 "github.com/fluxcd/notification-controller/api/v1beta2"
apiv1b3 "github.com/fluxcd/notification-controller/api/v1beta3"
// +kubebuilder:scaffold:imports
)
@ -57,6 +60,7 @@ func TestMain(m *testing.M) {
var err error
utilruntime.Must(apiv1.AddToScheme(scheme.Scheme))
utilruntime.Must(apiv1b2.AddToScheme(scheme.Scheme))
utilruntime.Must(apiv1b3.AddToScheme(scheme.Scheme))
testEnv = testenv.New(testenv.WithCRDPath(
filepath.Join("..", "..", "config", "crd", "bases"),
@ -72,23 +76,16 @@ func TestMain(m *testing.M) {
if err := (&AlertReconciler{
Client: testEnv,
Metrics: testMetricsH,
ControllerName: controllerName,
EventRecorder: testEnv.GetEventRecorderFor(controllerName),
}).SetupWithManagerAndOptions(testEnv, AlertReconcilerOptions{
RateLimiter: controller.GetDefaultRateLimiter(),
}); err != nil {
panic(fmt.Sprintf("Failed to start AlerReconciler: %v", err))
}).SetupWithManager(testEnv); err != nil {
panic(fmt.Sprintf("Failed to start AlertReconciler: %v", err))
}
if err := (&ProviderReconciler{
Client: testEnv,
Metrics: testMetricsH,
ControllerName: controllerName,
EventRecorder: testEnv.GetEventRecorderFor(controllerName),
}).SetupWithManagerAndOptions(testEnv, ProviderReconcilerOptions{
RateLimiter: controller.GetDefaultRateLimiter(),
}); err != nil {
Client: testEnv,
EventRecorder: testEnv.GetEventRecorderFor(controllerName),
}).SetupWithManager(testEnv); err != nil {
panic(fmt.Sprintf("Failed to start ProviderReconciler: %v", err))
}
@ -98,7 +95,8 @@ func TestMain(m *testing.M) {
ControllerName: controllerName,
EventRecorder: testEnv.GetEventRecorderFor(controllerName),
}).SetupWithManagerAndOptions(testEnv, ReceiverReconcilerOptions{
RateLimiter: controller.GetDefaultRateLimiter(),
RateLimiter: controller.GetDefaultRateLimiter(),
WatchConfigsPredicate: predicate.Not(predicate.Funcs{}),
}); err != nil {
panic(fmt.Sprintf("Failed to start ReceiverReconciler: %v", err))
}
@ -159,7 +157,7 @@ func readManifest(manifest, namespace string) (*unstructured.Unstructured, error
}
yml := fmt.Sprintf(string(data), namespace)
object, err := ssa.ReadObject(strings.NewReader(yml))
object, err := ssautil.ReadObject(strings.NewReader(yml))
if err != nil {
return nil, err
}

View File

@ -1,20 +0,0 @@
# Copyright 2023 The Flux authors
#
# 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.
all: ca-key.pem
ca-key.pem: ca-csr.json
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
ca.pem: ca-key.pem
ca.csr: ca-key.pem

View File

@ -1,13 +0,0 @@
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"kubernetes": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "8760h"
}
}
}
}

View File

@ -1,9 +0,0 @@
{
"CN": "example.com CA",
"hosts": [
"127.0.0.1",
"localhost",
"example.com",
"www.example.com"
]
}

View File

@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIEY+R5pZqRQUvD2wrbL4HFl5IKFY84FEGHG5GHW1EojroAoGCCqGSM49
AwEHoUQDQgAEDqdWaSYf2JT7L90ywnuhz2BS4zhy+v5juPLpBI0Indo8mHpOw9m+
LCnMzN2WkcUYt+XLQwhaNNt0RBlfnXRzhw==
-----END EC PRIVATE KEY-----

View File

@ -1,9 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIBHzCBxgIBADAZMRcwFQYDVQQDEw5leGFtcGxlLmNvbSBDQTBZMBMGByqGSM49
AgEGCCqGSM49AwEHA0IABA6nVmkmH9iU+y/dMsJ7oc9gUuM4cvr+Y7jy6QSNCJ3a
PJh6TsPZviwpzMzdlpHFGLfly0MIWjTbdEQZX510c4egSzBJBgkqhkiG9w0BCQ4x
PDA6MDgGA1UdEQQxMC+CCWxvY2FsaG9zdIILZXhhbXBsZS5jb22CD3d3dy5leGFt
cGxlLmNvbYcEfwAAATAKBggqhkjOPQQDAgNIADBFAiEAl0UiOdxlEcuKrNAGh/Pv
CFxMyX5shaeAsdGvq/gyXckCIFlTwheOJZZVRRQl9b0l5LUVeJyIH6mnvitFGyQ7
NRk5
-----END CERTIFICATE REQUEST-----

View File

@ -1,11 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBhzCCAS2gAwIBAgIUXe+UdziaK3dAdwRgwpWa0XPkKLIwCgYIKoZIzj0EAwIw
GTEXMBUGA1UEAxMOZXhhbXBsZS5jb20gQ0EwHhcNMjMwODE2MTcwMDAwWhcNMjgw
ODE0MTcwMDAwWjAZMRcwFQYDVQQDEw5leGFtcGxlLmNvbSBDQTBZMBMGByqGSM49
AgEGCCqGSM49AwEHA0IABA6nVmkmH9iU+y/dMsJ7oc9gUuM4cvr+Y7jy6QSNCJ3a
PJh6TsPZviwpzMzdlpHFGLfly0MIWjTbdEQZX510c4ejUzBRMA4GA1UdDwEB/wQE
AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRSCe96Yb+o/q3kuqBp5IMs
uD9N/DAPBgNVHREECDAGhwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIBw52JoEQ/0Z
Bnz4gXlXLXtVX0C4LvcNohdlwSRGHPlYAiEAnVqcT2kxBs2+E3SqJPU3DUM7ZFOO
n3zfiIVinQNlXPY=
-----END CERTIFICATE-----

View File

@ -18,7 +18,10 @@ limitations under the License.
// and their default states.
package features
import feathelper "github.com/fluxcd/pkg/runtime/features"
import (
"github.com/fluxcd/pkg/auth"
feathelper "github.com/fluxcd/pkg/runtime/features"
)
const (
// CacheSecretsAndConfigMaps controls whether Secrets and ConfigMaps should
@ -35,6 +38,10 @@ var features = map[string]bool{
CacheSecretsAndConfigMaps: false,
}
func init() {
auth.SetFeatureGates(features)
}
// FeatureGates contains a list of all supported feature gates and
// their default values.
func FeatureGates() map[string]bool {

View File

@ -18,36 +18,77 @@ package notifier
import (
"context"
"crypto/x509"
"crypto/tls"
"encoding/json"
"fmt"
"net/url"
"strings"
"time"
"github.com/hashicorp/go-retryablehttp"
"golang.org/x/text/cases"
"golang.org/x/text/language"
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
)
type Alertmanager struct {
URL string
ProxyURL string
CertPool *x509.CertPool
URL string
ProxyURL string
TLSConfig *tls.Config
Token string
Username string
Password string
}
type AlertManagerAlert struct {
Status string `json:"status"`
Labels map[string]string `json:"labels"`
Annotations map[string]string `json:"annotations"`
StartsAt AlertManagerTime `json:"startsAt"`
EndsAt AlertManagerTime `json:"endsAt,omitempty"`
}
func NewAlertmanager(hookURL string, proxyURL string, certPool *x509.CertPool) (*Alertmanager, error) {
// AlertManagerTime takes care of representing time.Time as RFC3339.
// See https://prometheus.io/docs/alerting/0.27/clients/
type AlertManagerTime time.Time
func (a AlertManagerTime) String() string {
return time.Time(a).Format(time.RFC3339)
}
func (a AlertManagerTime) MarshalJSON() ([]byte, error) {
return json.Marshal(a.String())
}
func (a *AlertManagerTime) UnmarshalJSON(jsonRepr []byte) error {
var serializedTime string
if err := json.Unmarshal(jsonRepr, &serializedTime); err != nil {
return err
}
t, err := time.Parse(time.RFC3339, serializedTime)
if err != nil {
return err
}
*a = AlertManagerTime(t)
return nil
}
func NewAlertmanager(hookURL string, proxyURL string, tlsConfig *tls.Config, token, user, pass string) (*Alertmanager, error) {
_, err := url.ParseRequestURI(hookURL)
if err != nil {
return nil, fmt.Errorf("invalid Alertmanager URL %s: '%w'", hookURL, err)
}
return &Alertmanager{
URL: hookURL,
ProxyURL: proxyURL,
CertPool: certPool,
URL: hookURL,
ProxyURL: proxyURL,
Token: token,
Username: user,
Password: pass,
TLSConfig: tlsConfig,
}, nil
}
@ -70,28 +111,57 @@ func (s *Alertmanager) Post(ctx context.Context, event eventv1.Event) error {
if event.Metadata != nil {
labels = event.Metadata
}
labels["alertname"] = "Flux" + event.InvolvedObject.Kind + strings.Title(event.Reason)
labels["alertname"] = "Flux" + event.InvolvedObject.Kind + cases.Title(language.Und).String(event.Reason)
labels["severity"] = event.Severity
labels["reason"] = event.Reason
labels["timestamp"] = event.Timestamp.String()
labels["kind"] = event.InvolvedObject.Kind
labels["name"] = event.InvolvedObject.Name
labels["namespace"] = event.InvolvedObject.Namespace
labels["reportingcontroller"] = event.ReportingController
// The best reasonable `endsAt` value would be multiplying
// InvolvedObject's reconciliation interval by 2 then adding that to
// `startsAt` (the next successful reconciliation would make sure
// the alert is cleared after the timeout). Due to
// event.InvolvedObject only containing the object reference (namely
// the GVKNN) best we can do is leave it unset up to Alertmanager's
// default `resolve_timeout`.
//
// https://prometheus.io/docs/alerting/0.27/configuration/#file-layout-and-global-settings
startsAt := AlertManagerTime(event.Timestamp.Time)
payload := []AlertManagerAlert{
{
Labels: labels,
Annotations: annotations,
Status: "firing",
StartsAt: startsAt,
},
}
err := postMessage(ctx, s.URL, s.ProxyURL, s.CertPool, payload)
var opts []postOption
if s.ProxyURL != "" {
opts = append(opts, withProxy(s.ProxyURL))
}
if s.TLSConfig != nil {
opts = append(opts, withTLSConfig(s.TLSConfig))
}
if s.Token != "" {
opts = append(opts, withRequestModifier(func(request *retryablehttp.Request) {
request.Header.Add("Authorization", "Bearer "+s.Token)
}))
}
if s.Username != "" && s.Password != "" {
opts = append(opts, withRequestModifier(func(request *retryablehttp.Request) {
request.SetBasicAuth(s.Username, s.Password)
}))
}
if err != nil {
if err := postMessage(ctx, s.URL, payload, opts...); err != nil {
return fmt.Errorf("postMessage failed: %w", err)
}
return nil
}

View File

@ -18,7 +18,7 @@ package notifier
import (
"context"
"crypto/x509"
"crypto/tls"
"fmt"
"io"
"net/http"
@ -43,10 +43,10 @@ func Fuzz_AlertManager(f *testing.F) {
}))
defer ts.Close()
var cert x509.CertPool
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
var tlsConfig tls.Config
_ = fuzz.NewConsumer(seed).GenerateStruct(&tlsConfig)
alertmanager, err := NewAlertmanager(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", &cert)
alertmanager, err := NewAlertmanager(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", &tlsConfig, "", "", "")
if err != nil {
return
}

View File

@ -38,7 +38,7 @@ func TestAlertmanager_Post(t *testing.T) {
}))
defer ts.Close()
alertmanager, err := NewAlertmanager(ts.URL, "", nil)
alertmanager, err := NewAlertmanager(ts.URL, "", nil, "", "", "")
require.NoError(t, err)
err = alertmanager.Post(context.TODO(), testEvent())

View File

@ -19,16 +19,18 @@ package notifier
import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"strings"
"github.com/microsoft/azure-devops-go-api/azuredevops/v6"
"github.com/microsoft/azure-devops-go-api/azuredevops/v6/git"
"sigs.k8s.io/controller-runtime/pkg/client"
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/auth/azure"
"github.com/fluxcd/pkg/cache"
)
const genre string = "fluxcd"
@ -40,16 +42,23 @@ type azureDevOpsClient interface {
// AzureDevOps is an Azure DevOps notifier.
type AzureDevOps struct {
Project string
Repo string
ProviderUID string
Client azureDevOpsClient
Project string
Repo string
CommitStatus string
Client azureDevOpsClient
}
// NewAzureDevOps creates and returns a new AzureDevOps notifier.
func NewAzureDevOps(providerUID string, addr string, token string, certPool *x509.CertPool) (*AzureDevOps, error) {
func NewAzureDevOps(ctx context.Context, commitStatus string, addr string, token string,
tlsConfig *tls.Config, proxy, serviceAccountName, providerName, providerNamespace string,
tokenClient client.Client, tokenCache *cache.TokenCache) (*AzureDevOps, error) {
var err error
if len(token) == 0 {
return nil, errors.New("azure devops token cannot be empty")
// if token doesn't exist, try to create a new token using managed identity
token, err = newManagedIdentityToken(ctx, proxy, serviceAccountName, providerName, providerNamespace, azure.ScopeDevOps, tokenClient, tokenCache)
if err != nil {
return nil, fmt.Errorf("failed to acquire azure devops token: %w", err)
}
}
host, id, err := parseGitAddress(addr)
@ -57,6 +66,11 @@ func NewAzureDevOps(providerUID string, addr string, token string, certPool *x50
return nil, err
}
// this should never happen
if commitStatus == "" {
return nil, errors.New("commit status cannot be empty")
}
comp := strings.Split(id, "/")
if len(comp) != 4 {
return nil, fmt.Errorf("invalid repository id %q", id)
@ -67,20 +81,18 @@ func NewAzureDevOps(providerUID string, addr string, token string, certPool *x50
orgURL := fmt.Sprintf("%v/%v", host, org)
connection := azuredevops.NewPatConnection(orgURL, token)
if certPool != nil {
connection.TlsConfig = &tls.Config{
RootCAs: certPool,
}
if tlsConfig != nil {
connection.TlsConfig = tlsConfig
}
client := connection.GetClientByUrl(orgURL)
gitClient := &git.ClientImpl{
Client: *client,
}
return &AzureDevOps{
Project: proj,
Repo: repo,
ProviderUID: providerUID,
Client: gitClient,
Project: proj,
Repo: repo,
CommitStatus: commitStatus,
Client: gitClient,
}, nil
}
@ -91,7 +103,7 @@ func (a AzureDevOps) Post(ctx context.Context, event eventv1.Event) error {
return nil
}
revString, ok := event.Metadata[eventv1.MetaRevisionKey]
revString, ok := event.GetRevision()
if !ok {
return errors.New("missing revision metadata")
}
@ -108,7 +120,7 @@ func (a AzureDevOps) Post(ctx context.Context, event eventv1.Event) error {
g := commitStatusGenre(event)
_, desc := formatNameAndDescription(event)
id := generateCommitStatusID(a.ProviderUID, event)
id := a.CommitStatus
createArgs := git.CreateCommitStatusArgs{
Project: &a.Project,
RepositoryId: &a.Repo,

View File

@ -18,6 +18,7 @@ package notifier
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io"
@ -33,12 +34,12 @@ import (
const apiLocations = `{"count":0,"value":[{"area":"","id":"428dd4fb-fda5-4722-af02-9313b80305da","routeTemplate":"","resourceName":"","maxVersion":"6.0","minVersion":"5.0","releasedVersion":"6.0"}]}`
func Fuzz_AzureDevOps(f *testing.F) {
f.Add("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "alakazam", "org/proj/_git/repo", "revision/dsa123a", "error", "", []byte{}, []byte(`{"count":1,"value":[{"state":"error","description":"","context":{"genre":"fluxcd","name":"/"}}]}`))
f.Add("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "alakazam", "org/proj/_git/repo", "revision/dsa123a", "info", "", []byte{}, []byte(`{"count":1,"value":[{"state":"info","description":"","context":{"genre":"fluxcd","name":"/"}}]}`))
f.Add("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "alakazam", "org/proj/_git/repo", "revision/dsa123a", "info", "", []byte{}, []byte(`{"count":0,"value":[]}`))
f.Add("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "alakazam", "org/proj/_git/repo", "", "", "Progressing", []byte{}, []byte{})
f.Add("kustomization/gitops-system/0c9c2e41", "alakazam", "org/proj/_git/repo", "revision/dsa123a", "error", "", []byte{}, []byte(`{"count":1,"value":[{"state":"error","description":"","context":{"genre":"fluxcd","name":"/"}}]}`))
f.Add("kustomization/gitops-system/0c9c2e41", "alakazam", "org/proj/_git/repo", "revision/dsa123a", "info", "", []byte{}, []byte(`{"count":1,"value":[{"state":"info","description":"","context":{"genre":"fluxcd","name":"/"}}]}`))
f.Add("kustomization/gitops-system/0c9c2e41", "alakazam", "org/proj/_git/repo", "revision/dsa123a", "info", "", []byte{}, []byte(`{"count":0,"value":[]}`))
f.Add("kustomization/gitops-system/0c9c2e41", "alakazam", "org/proj/_git/repo", "", "", "Progressing", []byte{}, []byte{})
f.Fuzz(func(t *testing.T, uuid, token, urlSuffix, revision, severity, reason string, seed, response []byte) {
f.Fuzz(func(t *testing.T, commitStatus, token, urlSuffix, revision, severity, reason string, seed, response []byte) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.HasSuffix(r.URL.Path, "_apis") {
w.Write([]byte(apiLocations))
@ -54,7 +55,8 @@ func Fuzz_AzureDevOps(f *testing.F) {
var cert x509.CertPool
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
azureDevOps, err := NewAzureDevOps(uuid, fmt.Sprintf("%s/%s", ts.URL, urlSuffix), token, &cert)
tlsConfig := &tls.Config{RootCAs: &cert}
azureDevOps, err := NewAzureDevOps(context.TODO(), commitStatus, fmt.Sprintf("%s/%s", ts.URL, urlSuffix), token, tlsConfig, "", "", "", "", nil, nil)
if err != nil {
return
}

View File

@ -27,19 +27,24 @@ import (
)
func TestNewAzureDevOpsBasic(t *testing.T) {
a, err := NewAzureDevOps("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "https://dev.azure.com/foo/bar/_git/baz", "foo", nil)
a, err := NewAzureDevOps(context.TODO(), "kustomization/gitops-system/0c9c2e41", "https://dev.azure.com/foo/bar/_git/baz", "foo", nil, "", "", "", "", nil, nil)
assert.Nil(t, err)
assert.Equal(t, a.Project, "bar")
assert.Equal(t, a.Repo, "baz")
}
func TestNewAzureDevOpsInvalidUrl(t *testing.T) {
_, err := NewAzureDevOps("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "https://dev.azure.com/foo/bar/baz", "foo", nil)
_, err := NewAzureDevOps(context.TODO(), "kustomization/gitops-system/0c9c2e41", "https://dev.azure.com/foo/bar/baz", "foo", nil, "", "", "", "", nil, nil)
assert.NotNil(t, err)
}
func TestNewAzureDevOpsMissingToken(t *testing.T) {
_, err := NewAzureDevOps("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "https://dev.azure.com/foo/bar/baz", "", nil)
_, err := NewAzureDevOps(context.TODO(), "kustomization/gitops-system/0c9c2e41", "https://dev.azure.com/foo/bar/baz", "", nil, "", "", "", "", nil, nil)
assert.NotNil(t, err)
}
func TestNewAzureDevOpsEmptyCommitStatus(t *testing.T) {
_, err := NewAzureDevOps(context.TODO(), "", "https://dev.azure.com/foo/bar/_git/baz", "foo", nil, "", "", "", "", nil, nil)
assert.NotNil(t, err)
}
@ -100,6 +105,34 @@ func TestAzureDevOps_Post(t *testing.T) {
},
},
},
{
name: "event with origin revision",
event: eventv1.Event{
Severity: eventv1.EventSeverityInfo,
InvolvedObject: corev1.ObjectReference{
Kind: "Kustomization",
Name: "gitops-system",
},
Metadata: map[string]string{
eventv1.MetaRevisionKey: "main@sha1:69b59063470310ebbd88a9156325322a124e55a3",
eventv1.MetaOriginRevisionKey: "main@sha1:bd88a9156325322a124e55a369b59063470310eb",
},
Reason: "ApplySucceeded",
},
want: git.CreateCommitStatusArgs{
CommitId: strPtr("bd88a9156325322a124e55a369b59063470310eb"),
Project: strPtr("bar"),
RepositoryId: strPtr("baz"),
GitCommitStatusToCreate: &git.GitStatus{
Description: strPtr("apply succeeded"),
State: &git.GitStatusStateValues.Succeeded,
Context: &git.GitStatusContext{
Genre: strPtr("fluxcd"),
Name: strPtr("kustomization/gitops-system/0c9c2e41"),
},
},
},
},
{
name: "event with summary",
event: eventv1.Event{
@ -132,7 +165,7 @@ func TestAzureDevOps_Post(t *testing.T) {
for _, tt := range postTests {
t.Run(tt.name, func(t *testing.T) {
a, err := NewAzureDevOps("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "https://example.com/foo/bar/_git/baz", "foo", nil)
a, err := NewAzureDevOps(context.TODO(), "kustomization/gitops-system/0c9c2e41", "https://example.com/foo/bar/_git/baz", "foo", nil, "", "", "", "", nil, nil)
fakeClient := &fakeDevOpsClient{}
a.Client = fakeClient
assert.Nil(t, err)

View File

@ -17,37 +17,60 @@ import (
"context"
"encoding/json"
"fmt"
"os"
"strings"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
eventhub "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
"github.com/Azure/azure-amqp-common-go/v4/auth"
eventhub "github.com/Azure/azure-event-hubs-go/v3"
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
"github.com/fluxcd/pkg/auth/azure"
"github.com/fluxcd/pkg/cache"
)
// AzureEventHub holds the eventhub client
type AzureEventHub struct {
Hub *eventhub.Hub
ProducerClient *eventhub.ProducerClient
}
// NewAzureEventHub creates a eventhub client
func NewAzureEventHub(endpointURL, token, eventHubNamespace string) (*AzureEventHub, error) {
var hub *eventhub.Hub
func NewAzureEventHub(ctx context.Context, endpointURL, token, eventHubNamespace, proxy,
serviceAccountName, providerName, providerNamespace string, tokenClient client.Client,
tokenCache *cache.TokenCache) (*AzureEventHub, error) {
var client *eventhub.ProducerClient
var err error
// token should only be defined if JWT is used
if token != "" {
hub, err = newJWTHub(endpointURL, token, eventHubNamespace)
if err := validateAuthOptions(endpointURL, token, serviceAccountName); err != nil {
return nil, fmt.Errorf("invalid authentication options: %v", err)
}
if isSASAuth(endpointURL) {
client, err = newSASHub(endpointURL)
if err != nil {
return nil, fmt.Errorf("failed to create a eventhub using JWT %v", err)
return nil, fmt.Errorf("failed to create a eventhub using SAS: %w", err)
}
} else {
hub, err = newSASHub(endpointURL)
// if token doesn't exist, try to create a new token using managed identity
if token == "" {
token, err = newManagedIdentityToken(ctx, proxy, serviceAccountName, providerName,
providerNamespace, azure.ScopeEventHubs, tokenClient, tokenCache)
if err != nil {
return nil, fmt.Errorf("failed to create a eventhub using managed identity: %w", err)
}
} else {
log.FromContext(ctx).Error(nil, "warning: static JWT authentication is deprecated and will be removed in the future, prefer workload identity: https://fluxcd.io/flux/components/notification/providers/#managed-identity")
}
client, err = newJWTHub(endpointURL, token, eventHubNamespace)
if err != nil {
return nil, fmt.Errorf("failed to create a eventhub using SAS %v", err)
return nil, fmt.Errorf("failed to create a eventhub using authentication token: %w", err)
}
}
return &AzureEventHub{
Hub: hub,
ProducerClient: client,
}, nil
}
@ -60,17 +83,27 @@ func (e *AzureEventHub) Post(ctx context.Context, event eventv1.Event) error {
eventBytes, err := json.Marshal(event)
if err != nil {
return fmt.Errorf("Unable to marshall event: %w", err)
return fmt.Errorf("unable to marshall event: %w", err)
}
err = e.Hub.Send(ctx, eventhub.NewEvent(eventBytes))
eventBatch, err := e.ProducerClient.NewEventDataBatch(ctx, nil)
if err != nil {
return fmt.Errorf("Failed to send msg: %w", err)
return fmt.Errorf("failed to create event data batch: %w", err)
}
err = e.Hub.Close(ctx)
err = eventBatch.AddEventData(&eventhub.EventData{Body: eventBytes}, nil)
if err != nil {
return fmt.Errorf("Unable to close connection: %w", err)
return fmt.Errorf("failed to add event data to batch: %w", err)
}
err = e.ProducerClient.SendEventDataBatch(ctx, eventBatch, nil)
if err != nil {
return fmt.Errorf("failed to send msg: %w", err)
}
err = e.ProducerClient.Close(ctx)
if err != nil {
return fmt.Errorf("unable to close connection: %w", err)
}
return nil
}
@ -81,26 +114,24 @@ type PureJWT struct {
}
// NewJWTProvider create a pureJWT method
func NewJWTProvider(jwt string) *PureJWT {
func NewJWTProvider(jwt string) azcore.TokenCredential {
return &PureJWT{
jwt: jwt,
}
}
// GetToken uses a JWT token, we assume that we will get new tokens when needed, thus no Expiry defined
func (j *PureJWT) GetToken(uri string) (*auth.Token, error) {
return &auth.Token{
TokenType: auth.CBSTokenTypeJWT,
Token: j.jwt,
Expiry: "",
func (j *PureJWT) GetToken(ctx context.Context, options policy.TokenRequestOptions) (azcore.AccessToken, error) {
return azcore.AccessToken{
Token: j.jwt,
}, nil
}
// newJWTHub used when address is a JWT token
func newJWTHub(eventhubName, token, eventHubNamespace string) (*eventhub.Hub, error) {
func newJWTHub(eventhubName, token, eventHubNamespace string) (*eventhub.ProducerClient, error) {
provider := NewJWTProvider(token)
hub, err := eventhub.NewHub(eventHubNamespace, eventhubName, provider)
fullyQualifiedNamespace := ensureFullyQualifiedNamespace(eventHubNamespace)
hub, err := eventhub.NewProducerClient(fullyQualifiedNamespace, eventhubName, provider, nil)
if err != nil {
return nil, err
}
@ -108,11 +139,66 @@ func newJWTHub(eventhubName, token, eventHubNamespace string) (*eventhub.Hub, er
}
// newSASHub used when address is a SAS ConnectionString
func newSASHub(address string) (*eventhub.Hub, error) {
hub, err := eventhub.NewHubFromConnectionString(address)
func newSASHub(address string) (*eventhub.ProducerClient, error) {
client, err := eventhub.NewProducerClientFromConnectionString(address, "", nil)
if err != nil {
return nil, err
}
return hub, nil
return client, nil
}
// validateAuthOptions checks if the authentication options are valid
func validateAuthOptions(endpointURL, token, serviceAccountName string) error {
if endpointURL == "" {
return fmt.Errorf("endpoint URL cannot be empty")
}
if isSASAuth(endpointURL) {
if err := validateSASAuth(token, serviceAccountName); err != nil {
return err
}
} else if serviceAccountName != "" && token != "" {
return fmt.Errorf("serviceAccountName and jwt token authentication cannot be set at the same time")
}
return nil
}
// isSASAuth checks if the endpoint URL contains SAS authentication parameters
func isSASAuth(endpointURL string) bool {
return strings.Contains(endpointURL, "SharedAccessKey")
}
// validateSASAuth checks if SAS authentication is used correctly
func validateSASAuth(token, serviceAccountName string) error {
if serviceAccountName != "" {
return fmt.Errorf("serviceAccountName and SAS authentication cannot be set at the same time")
}
if token != "" {
return fmt.Errorf("jwt token and SAS authentication cannot be set at the same time")
}
return nil
}
// getEventHubSuffixFromAuthorityHost maps AZURE_AUTHORITY_HOST to the correct suffix
func getEventHubSuffixFromAuthorityHost() string {
authorityHost := os.Getenv("AZURE_AUTHORITY_HOST")
switch {
case strings.Contains(authorityHost, "chinacloudapi.cn"):
return ".servicebus.chinacloudapi.cn"
case strings.Contains(authorityHost, "microsoftonline.us"):
return ".servicebus.usgovcloudapi.net"
default:
return ".servicebus.windows.net"
}
}
// ensureFullyQualifiedNamespace appends suffix if not already present
func ensureFullyQualifiedNamespace(namespace string) string {
if strings.Contains(namespace, ".servicebus.") {
return namespace // already fully qualified
}
return namespace + getEventHubSuffixFromAuthorityHost()
}

View File

@ -0,0 +1,103 @@
/*
Copyright 2021 The Flux authors
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 notifier
import (
"context"
"errors"
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewAzureEventHub(t *testing.T) {
tests := []struct {
name string
endpointURL string
token string
eventHubNamespace string
serviceAccountName string
err error
}{
{
name: "JWT Authentication",
endpointURL: "azure-nc-eventhub",
token: "jwt-token",
eventHubNamespace: "namespace",
},
{
name: "SAS Authentication",
endpointURL: "Endpoint=sb://example.com/;SharedAccessKeyName=keyName;SharedAccessKey=key;EntityPath=eventhub",
token: "",
eventHubNamespace: "namespace",
},
{
name: "SAS Authentication without entity path",
endpointURL: "Endpoint=sb://example.com/;SharedAccessKeyName=keyName;SharedAccessKey=key",
token: "",
eventHubNamespace: "namespace",
err: errors.New("failed to create a eventhub using SAS: connection string does not contain an EntityPath. eventHub cannot be an empty string"),
},
{
name: "Default Azure Credential",
endpointURL: "azure-nc-eventhub",
token: "",
eventHubNamespace: "namespace",
err: errors.New("failed to create a eventhub using managed identity: failed to get token: failed to create provider access token for the controller: ManagedIdentityCredential: failed to authenticate a system assigned identity. The endpoint responded with {\"error\":\"invalid_request\",\"error_description\":\"Identity not found\"}"),
},
{
name: "SAS auth with serviceAccountName set",
endpointURL: "Endpoint=sb://example.com/;SharedAccessKeyName=keyName;SharedAccessKey=key;EntityPath=eventhub",
token: "",
serviceAccountName: "test-service-account",
eventHubNamespace: "namespace",
err: errors.New("invalid authentication options: serviceAccountName and SAS authentication cannot be set at the same time"),
},
{
name: "SAS auth with token set",
endpointURL: "Endpoint=sb://example.com/;SharedAccessKeyName=keyName;SharedAccessKey=key;EntityPath=eventhub",
token: "test-token",
eventHubNamespace: "namespace",
err: errors.New("invalid authentication options: jwt token and SAS authentication cannot be set at the same time"),
},
{
name: "token auth with serviceAccountName set",
endpointURL: "azure-nc-eventhub",
token: "test-token",
serviceAccountName: "test-service-account",
eventHubNamespace: "namespace",
err: errors.New("invalid authentication options: serviceAccountName and jwt token authentication cannot be set at the same time"),
},
{
name: "empty endpoint URL",
endpointURL: "",
token: "test-token",
eventHubNamespace: "namespace",
err: errors.New("invalid authentication options: endpoint URL cannot be empty"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client, err := NewAzureEventHub(context.TODO(), tt.endpointURL, tt.token, tt.eventHubNamespace, "", tt.serviceAccountName, "", "", nil, nil)
if tt.err != nil {
assert.Error(t, err)
assert.ErrorContains(t, err, tt.err.Error())
} else {
assert.NoError(t, err)
assert.NotNil(t, client)
}
})
}
}

View File

@ -0,0 +1,69 @@
/*
Copyright 2025 The Flux authors
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 notifier
import (
"context"
"fmt"
"net/url"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/pkg/auth"
"github.com/fluxcd/pkg/auth/azure"
"github.com/fluxcd/pkg/cache"
"github.com/fluxcd/notification-controller/api/v1beta3"
)
// newManagedIdentityToken is used to attempt credential-free authentication.
func newManagedIdentityToken(ctx context.Context, proxy, serviceAccountName, providerName, providerNamespace, scope string, tokenClient client.Client, tokenCache *cache.TokenCache) (string, error) {
opts := []auth.Option{
auth.WithScopes(scope),
auth.WithClient(tokenClient),
auth.WithServiceAccountNamespace(providerNamespace),
}
if proxy != "" {
proxyURL, err := url.Parse(proxy)
if err != nil {
return "", fmt.Errorf("error parsing proxy URL: %w", err)
}
opts = append(opts, auth.WithProxyURL(*proxyURL))
}
if serviceAccountName != "" {
opts = append(opts, auth.WithServiceAccountName(serviceAccountName))
}
if tokenCache != nil {
involvedObject := cache.InvolvedObject{
Kind: v1beta3.ProviderKind,
Name: providerName,
Namespace: providerNamespace,
Operation: OperationPost,
}
opts = append(opts, auth.WithCache(*tokenCache, involvedObject))
}
token, err := auth.GetAccessToken(ctx, azure.Provider{}, opts...)
if err != nil {
return "", fmt.Errorf("failed to get token: %w", err)
}
return token.(*azure.Token).Token, nil
}

View File

@ -19,7 +19,6 @@ package notifier
import (
"context"
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"fmt"
@ -34,18 +33,23 @@ import (
// Bitbucket is a Bitbucket Server notifier.
type Bitbucket struct {
Owner string
Repo string
ProviderUID string
Client *bitbucket.Client
Owner string
Repo string
CommitStatus string
Client *bitbucket.Client
}
// NewBitbucket creates and returns a new Bitbucket notifier.
func NewBitbucket(providerUID string, addr string, token string, certPool *x509.CertPool) (*Bitbucket, error) {
func NewBitbucket(commitStatus string, addr string, token string, tlsConfig *tls.Config) (*Bitbucket, error) {
if len(token) == 0 {
return nil, errors.New("bitbucket token cannot be empty")
}
// this should never happen
if commitStatus == "" {
return nil, errors.New("commit status cannot be empty")
}
_, id, err := parseGitAddress(addr)
if err != nil {
return nil, err
@ -66,21 +70,19 @@ func NewBitbucket(providerUID string, addr string, token string, certPool *x509.
repo := comp[1]
client := bitbucket.NewBasicAuth(username, password)
if certPool != nil {
if tlsConfig != nil {
tr := &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certPool,
},
TLSClientConfig: tlsConfig,
}
hc := &http.Client{Transport: tr}
client.HttpClient = hc
}
return &Bitbucket{
Owner: owner,
Repo: repo,
ProviderUID: providerUID,
Client: client,
Owner: owner,
Repo: repo,
CommitStatus: commitStatus,
Client: client,
}, nil
}
@ -91,7 +93,7 @@ func (b Bitbucket) Post(ctx context.Context, event eventv1.Event) error {
return nil
}
revString, ok := event.Metadata[eventv1.MetaRevisionKey]
revString, ok := event.GetRevision()
if !ok {
return errors.New("missing revision metadata")
}
@ -105,7 +107,7 @@ func (b Bitbucket) Post(ctx context.Context, event eventv1.Event) error {
}
name, desc := formatNameAndDescription(event)
id := generateCommitStatusID(b.ProviderUID, event)
id := b.CommitStatus
// key has a limitation of 40 characters in bitbucket api
key := sha1String(id)

View File

@ -18,6 +18,7 @@ package notifier
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io"
@ -31,10 +32,10 @@ import (
)
func Fuzz_Bitbucket(f *testing.F) {
f.Add("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "user:pass", "org/repo", "revision/dsa123a", "info", []byte{}, []byte(`{"state":"SUCCESSFUL","description":"","key":"","name":"","url":""}`))
f.Add("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "user:pass", "org/repo", "revision/dsa123a", "error", []byte{}, []byte(`{}`))
f.Add("kustomization/gitops-system/0c9c2e41", "user:pass", "org/repo", "revision/dsa123a", "info", []byte{}, []byte(`{"state":"SUCCESSFUL","description":"","key":"","name":"","url":""}`))
f.Add("kustomization/gitops-system/0c9c2e41", "user:pass", "org/repo", "revision/dsa123a", "error", []byte{}, []byte(`{}`))
f.Fuzz(func(t *testing.T, uuid, token, urlSuffix, revision, severity string, seed, response []byte) {
f.Fuzz(func(t *testing.T, commitStatus, token, urlSuffix, revision, severity string, seed, response []byte) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
io.Copy(io.Discard, r.Body)
w.Write(response)
@ -45,7 +46,8 @@ func Fuzz_Bitbucket(f *testing.F) {
var cert x509.CertPool
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
bitbucket, err := NewBitbucket(uuid, fmt.Sprintf("%s/%s", ts.URL, urlSuffix), token, &cert)
tlsConfig := &tls.Config{RootCAs: &cert}
bitbucket, err := NewBitbucket(commitStatus, fmt.Sprintf("%s/%s", ts.URL, urlSuffix), token, tlsConfig)
if err != nil {
return
}

View File

@ -23,18 +23,24 @@ import (
)
func TestNewBitbucketBasic(t *testing.T) {
b, err := NewBitbucket("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "https://bitbucket.org/foo/bar", "foo:bar", nil)
b, err := NewBitbucket("kustomization/gitops-system/0c9c2e41", "https://bitbucket.org/foo/bar", "foo:bar", nil)
assert.Nil(t, err)
assert.Equal(t, b.Owner, "foo")
assert.Equal(t, b.Repo, "bar")
assert.Equal(t, b.CommitStatus, "kustomization/gitops-system/0c9c2e41")
}
func TestNewBitbucketEmptyCommitStatus(t *testing.T) {
_, err := NewBitbucket("", "https://bitbucket.org/foo/bar", "foo:bar", nil)
assert.NotNil(t, err)
}
func TestNewBitbucketInvalidUrl(t *testing.T) {
_, err := NewBitbucket("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "https://bitbucket.org/foo/bar/baz", "foo:bar", nil)
_, err := NewBitbucket("kustomization/gitops-system/0c9c2e41", "https://bitbucket.org/foo/bar/baz", "foo:bar", nil)
assert.NotNil(t, err)
}
func TestNewBitbucketInvalidToken(t *testing.T) {
_, err := NewBitbucket("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "https://bitbucket.org/foo/bar", "bar", nil)
_, err := NewBitbucket("kustomization/gitops-system/0c9c2e41", "https://bitbucket.org/foo/bar", "bar", nil)
assert.NotNil(t, err)
}

View File

@ -0,0 +1,312 @@
/*
Copyright 2023 The Flux authors
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 notifier
import (
"bytes"
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
"github.com/fluxcd/pkg/apis/meta"
"github.com/hashicorp/go-retryablehttp"
)
// BitbucketServer is a notifier for BitBucket Server and Data Center.
type BitbucketServer struct {
CommitStatus string
Url *url.URL
ProviderAddress string
Username string
Password string
Token string
Client *retryablehttp.Client
}
const (
bbServerEndPointCommitsTmpl = "%[1]s/rest/api/latest/projects/%[2]s/repos/%[3]s/commits"
bbServerEndPointBuildsTmpl = "%[1]s/builds"
bbServerGetBuildStatusQueryString = "key"
bbServerSourceCodeMgmtString = "/scm/"
)
type bbServerBuildStatus struct {
Name string `json:"name,omitempty"`
Key string `json:"key,omitempty"`
Parent string `json:"parent,omitempty"`
State string `json:"state,omitempty"`
Ref string `json:"ref,omitempty"`
BuildNumber string `json:"buildNumber,omitempty"`
Description string `json:"description,omitempty"`
Duration int64 `json:"duration,omitempty"`
UpdatedDate int64 `json:"updatedDate,omitempty"`
CreatedDate int64 `json:"createdDate,omitempty"`
Url string `json:"url,omitempty"`
}
type bbServerBuildStatusSetRequest struct {
BuildNumber string `json:"buildNumber,omitempty"`
Description string `json:"description,omitempty"`
Duration int64 `json:"duration,omitempty"`
Key string `json:"key"`
LastUpdated int64 `json:"lastUpdated,omitempty"`
Name string `json:"name,omitempty"`
Parent string `json:"parent,omitempty"`
Ref string `json:"ref,omitempty"`
State string `json:"state"`
Url string `json:"url"`
}
// NewBitbucketServer creates and returns a new BitbucketServer notifier.
func NewBitbucketServer(commitStatus string, addr string, token string, tlsConfig *tls.Config, username string, password string) (*BitbucketServer, error) {
url, err := parseBitbucketServerGitAddress(addr)
if err != nil {
return nil, err
}
// this should never happen
if commitStatus == "" {
return nil, errors.New("commit status cannot be empty")
}
httpClient := retryablehttp.NewClient()
if tlsConfig != nil {
httpClient.HTTPClient.Transport = &http.Transport{
TLSClientConfig: tlsConfig,
}
}
httpClient.HTTPClient.Timeout = 15 * time.Second
httpClient.RetryWaitMin = 2 * time.Second
httpClient.RetryWaitMax = 30 * time.Second
httpClient.RetryMax = 4
httpClient.Logger = nil
if len(token) == 0 && (len(username) == 0 || len(password) == 0) {
return nil, errors.New("invalid credentials, expected to be one of username/password or API Token")
}
return &BitbucketServer{
CommitStatus: commitStatus,
Url: url,
ProviderAddress: addr,
Token: token,
Username: username,
Password: password,
Client: httpClient,
}, nil
}
// Post Bitbucket Server build status
func (b BitbucketServer) Post(ctx context.Context, event eventv1.Event) error {
// Skip progressing events
if event.HasReason(meta.ProgressingReason) {
return nil
}
revString, ok := event.GetRevision()
if !ok {
return errors.New("missing revision metadata")
}
rev, err := parseRevision(revString)
if err != nil {
return fmt.Errorf("could not parse revision: %w", err)
}
state, err := b.state(event.Severity)
if err != nil {
return fmt.Errorf("couldn't convert to bitbucket server state: %w", err)
}
name, desc := formatNameAndDescription(event)
name = name + " [" + desc + "]" //Bitbucket server displays this data on browser. Thus adding description here.
id := b.CommitStatus
// key has a limitation of 40 characters in bitbucket api
key := sha1String(id)
u := b.Url.JoinPath(b.createBuildPath(rev)).String()
dupe, err := b.duplicateBitbucketServerStatus(ctx, state, name, desc, key, u)
if err != nil {
return fmt.Errorf("could not get existing commit status: %w", err)
}
if !dupe {
_, err = b.postBuildStatus(ctx, state, name, desc, key, u)
if err != nil {
return fmt.Errorf("could not post build status: %w", err)
}
}
return nil
}
func (b BitbucketServer) state(severity string) (string, error) {
switch severity {
case eventv1.EventSeverityInfo:
return "SUCCESSFUL", nil
case eventv1.EventSeverityError:
return "FAILED", nil
default:
return "", errors.New("bitbucket server state generated on info or error events only")
}
}
func (b BitbucketServer) duplicateBitbucketServerStatus(ctx context.Context, state, name, desc, key, u string) (bool, error) {
// Prepare request object
req, err := b.prepareCommonRequest(ctx, u, nil, http.MethodGet)
if err != nil {
return false, fmt.Errorf("could not check duplicate commit status: %w", err)
}
// Set query string
q := url.Values{}
q.Add(bbServerGetBuildStatusQueryString, key)
req.URL.RawQuery = q.Encode()
// Make a GET call
d, err := b.Client.Do(req)
if err != nil {
return false, fmt.Errorf("failed api call to check duplicate commit status: %w", err)
}
if d != nil && isError(d) && d.StatusCode != http.StatusNotFound {
defer d.Body.Close()
return false, fmt.Errorf("failed api call to check duplicate commit status: %d - %s", d.StatusCode, http.StatusText(d.StatusCode))
}
defer d.Body.Close()
if d.StatusCode == http.StatusOK {
bd, err := io.ReadAll(d.Body)
if err != nil {
return false, fmt.Errorf("could not read response body for duplicate commit status: %w", err)
}
var existingCommitStatus bbServerBuildStatus
err = json.Unmarshal(bd, &existingCommitStatus)
if err != nil {
return false, fmt.Errorf("could not unmarshal json response body for duplicate commit status: %w", err)
}
// Do not post duplicate build status
if existingCommitStatus.Key == key && existingCommitStatus.State == state && existingCommitStatus.Description == desc && existingCommitStatus.Name == name {
return true, nil
}
}
return false, nil
}
func (b BitbucketServer) postBuildStatus(ctx context.Context, state, name, desc, key, url string) (*http.Response, error) {
//Prepare json body
j := &bbServerBuildStatusSetRequest{
Key: key,
State: state,
Url: b.ProviderAddress,
Description: desc,
Name: name,
}
p := new(bytes.Buffer)
err := json.NewEncoder(p).Encode(j)
if err != nil {
return nil, fmt.Errorf("failed preparing request for post build commit status, could not encode request body to json: %w", err)
}
//Prepare request
req, err := b.prepareCommonRequest(ctx, url, p, http.MethodPost)
if err != nil {
return nil, fmt.Errorf("failed preparing request for post build commit status: %w", err)
}
// Add Content type header
req.Header.Add("Content-Type", "application/json")
// Make a POST call
resp, err := b.Client.Do(req)
if err != nil {
return nil, fmt.Errorf("could not post build commit status: %w", err)
}
// Note: A non-2xx status code doesn't cause an error: https://pkg.go.dev/net/http#Client.Do
if isError(resp) {
defer resp.Body.Close()
return nil, fmt.Errorf("could not post build commit status: %d - %s", resp.StatusCode, http.StatusText(resp.StatusCode))
}
defer resp.Body.Close()
return resp, nil
}
func (b BitbucketServer) createBuildPath(rev string) string {
return fmt.Sprintf(bbServerEndPointBuildsTmpl, rev)
}
func parseBitbucketServerGitAddress(s string) (*url.URL, error) {
u, err := url.Parse(s)
if err != nil {
return nil, fmt.Errorf("could not parse git address: %w", err)
}
if u.Scheme != "http" && u.Scheme != "https" {
return nil, fmt.Errorf("could not parse git address: unsupported scheme type in address: %s. Must be http or https", u.Scheme)
}
idWithContext := strings.TrimSuffix(u.Path, ".git")
// /scm/ is always part of http/https clone urls : https://community.atlassian.com/t5/Bitbucket-questions/remote-url-in-Bitbucket-server-what-does-scm-represent-is-it/qaq-p/2060987
lastIndex := strings.LastIndex(idWithContext, bbServerSourceCodeMgmtString)
if lastIndex < 0 {
return nil, fmt.Errorf("could not parse git address: supplied provider address is not http(s) git clone url")
}
// Handle context scenarios --> https://confluence.atlassian.com/bitbucketserver/change-bitbucket-s-context-path-776640153.html
cntxtPath := idWithContext[:lastIndex] // Context path is anything that comes before last /scm/
id := idWithContext[lastIndex+len(bbServerSourceCodeMgmtString):] // Remove last `/scm/` from id as it is not used in API calls
comp := strings.Split(id, "/")
if len(comp) != 2 {
return nil, fmt.Errorf("could not parse git address: invalid repository id %q", id)
}
projectkey := comp[0]
reposlug := comp[1]
// Update the path till commits endpoint. The final builds endpoint would be added in Post function.
u.Path = fmt.Sprintf(bbServerEndPointCommitsTmpl, cntxtPath, projectkey, reposlug)
return u, nil
}
func (b BitbucketServer) prepareCommonRequest(ctx context.Context, path string, body io.Reader, method string) (*retryablehttp.Request, error) {
req, err := retryablehttp.NewRequestWithContext(ctx, method, path, body)
if err != nil {
return nil, fmt.Errorf("could not prepare request: %w", err)
}
if b.Token != "" {
req.Header.Set("Authorization", "Bearer "+b.Token)
} else {
req.Header.Add("Authorization", "Basic "+basicAuth(b.Username, b.Password))
}
req.Header.Add("x-atlassian-token", "no-check")
req.Header.Add("x-requested-with", "XMLHttpRequest")
return req, nil
}
// isError method returns true if HTTP status `code >= 400` otherwise false.
func isError(r *http.Response) bool {
return r.StatusCode > 399
}

View File

@ -0,0 +1,454 @@
/*
Copyright 2023 The Flux authors
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 notifier
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"testing"
"net/http"
"net/http/httptest"
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestNewBitbucketServerBasicNoContext(t *testing.T) {
b, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/scm/projectfoo/repobar.git", "", nil, "dummyuser", "testpassword")
assert.Nil(t, err)
assert.Equal(t, b.Username, "dummyuser")
assert.Equal(t, b.Password, "testpassword")
assert.Equal(t, b.Url.Scheme, "https")
assert.Equal(t, b.Url.Host, "example.com:7990")
}
func TestNewBitbucketServerBasicWithContext(t *testing.T) {
b, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/context/scm/projectfoo/repobar.git", "", nil, "dummyuser", "testpassword")
assert.Nil(t, err)
assert.Equal(t, b.Username, "dummyuser")
assert.Equal(t, b.Password, "testpassword")
assert.Equal(t, b.Url.Scheme, "https")
assert.Equal(t, b.Url.Host, "example.com:7990")
}
func TestBitbucketServerApiPathNoContext(t *testing.T) {
b, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/scm/projectfoo/repobar.git", "", nil, "dummyuser", "testpassword")
assert.Nil(t, err)
u := b.Url.JoinPath(b.createBuildPath("00151b98e303e19610378e6f1c49e31e5e80cd3b")).String()
assert.Equal(t, u, "https://example.com:7990/rest/api/latest/projects/projectfoo/repos/repobar/commits/00151b98e303e19610378e6f1c49e31e5e80cd3b/builds")
}
func TestBitbucketServerApiPathOneWordContext(t *testing.T) {
b, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/context1/scm/projectfoo/repobar.git", "", nil, "dummyuser", "testpassword")
assert.Nil(t, err)
u := b.Url.JoinPath(b.createBuildPath("00151b98e303e19610378e6f1c49e31e5e80cd3b")).String()
assert.Equal(t, u, "https://example.com:7990/context1/rest/api/latest/projects/projectfoo/repos/repobar/commits/00151b98e303e19610378e6f1c49e31e5e80cd3b/builds")
}
func TestBitbucketServerApiPathMultipleWordContext(t *testing.T) {
b, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/context1/context2/context3/scm/projectfoo/repobar.git", "", nil, "dummyuser", "testpassword")
assert.Nil(t, err)
u := b.Url.JoinPath(b.createBuildPath("00151b98e303e19610378e6f1c49e31e5e80cd3b")).String()
assert.Equal(t, u, "https://example.com:7990/context1/context2/context3/rest/api/latest/projects/projectfoo/repos/repobar/commits/00151b98e303e19610378e6f1c49e31e5e80cd3b/builds")
}
func TestBitbucketServerApiPathOneWordScmInContext(t *testing.T) {
b, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/scm/scm/projectfoo/repobar.git", "", nil, "dummyuser", "testpassword")
assert.Nil(t, err)
u := b.Url.JoinPath(b.createBuildPath("00151b98e303e19610378e6f1c49e31e5e80cd3b")).String()
assert.Equal(t, u, "https://example.com:7990/scm/rest/api/latest/projects/projectfoo/repos/repobar/commits/00151b98e303e19610378e6f1c49e31e5e80cd3b/builds")
}
func TestBitbucketServerApiPathMultipleWordScmInContext(t *testing.T) {
b, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/scm/context2/scm/scm/projectfoo/repobar.git", "", nil, "dummyuser", "testpassword")
assert.Nil(t, err)
u := b.Url.JoinPath(b.createBuildPath("00151b98e303e19610378e6f1c49e31e5e80cd3b")).String()
assert.Equal(t, u, "https://example.com:7990/scm/context2/scm/rest/api/latest/projects/projectfoo/repos/repobar/commits/00151b98e303e19610378e6f1c49e31e5e80cd3b/builds")
}
func TestBitbucketServerApiPathScmAlreadyRemovedInInput(t *testing.T) {
_, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/context1/context2/context3/projectfoo/repobar.git", "", nil, "dummyuser", "testpassword")
assert.NotNil(t, err)
assert.Equal(t, err.Error(), "could not parse git address: supplied provider address is not http(s) git clone url")
}
func TestBitbucketServerSshAddress(t *testing.T) {
_, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "ssh://git@mybitbucket:2222/ap/fluxcd-sandbox.git", "", nil, "", "")
assert.NotNil(t, err)
assert.Equal(t, err.Error(), "could not parse git address: unsupported scheme type in address: ssh. Must be http or https")
}
func TestNewBitbucketServerToken(t *testing.T) {
b, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/scm/projectfoo/repobar.git", "BBDC-ODIxODYxMzIyNzUyOttorMjO059P2rYTb6EH7mP", nil, "", "")
assert.Nil(t, err)
assert.Equal(t, b.Token, "BBDC-ODIxODYxMzIyNzUyOttorMjO059P2rYTb6EH7mP")
}
func TestNewBitbucketServerInvalidCreds(t *testing.T) {
_, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/scm/projectfoo/repobar.git", "", nil, "", "")
assert.NotNil(t, err)
assert.Equal(t, err.Error(), "invalid credentials, expected to be one of username/password or API Token")
}
func TestNewBitbucketServerInvalidRepo(t *testing.T) {
_, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/scm/projectfoo/repobar/invalid.git", "BBDC-ODIxODYxMzIyNzUyOttorMjO059P2rYTb6EH7mP", nil, "", "")
assert.NotNil(t, err)
assert.Equal(t, err.Error(), "could not parse git address: invalid repository id \"projectfoo/repobar/invalid\"")
}
func TestPostBitbucketServerMissingRevision(t *testing.T) {
b, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/scm/projectfoo/repobar.git", "BBDC-ODIxODYxMzIyNzUyOttorMjO059P2rYTb6EH7mP", nil, "", "")
assert.Nil(t, err)
//Validate missing revision
err = b.Post(context.TODO(), generateTestEventKustomization("info", map[string]string{
"dummybadrevision": "bad",
}))
assert.NotNil(t, err)
assert.Equal(t, err.Error(), "missing revision metadata")
}
func TestNewBitbucketServerEmptyCommitStatus(t *testing.T) {
_, err := NewBitbucketServer("", "https://example.com:7990/scm/projectfoo/repobar.git", "BBDC-ODIxODYxMzIyNzUyOttorMjO059P2rYTb6EH7mP", nil, "", "")
assert.NotNil(t, err)
assert.Equal(t, err.Error(), "commit status cannot be empty")
}
func TestPostBitbucketServerBadCommitHash(t *testing.T) {
b, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/scm/projectfoo/repobar.git", "BBDC-ODIxODYxMzIyNzUyOttorMjO059P2rYTb6EH7mP", nil, "", "")
assert.Nil(t, err)
//Validate extract commit hash
err = b.Post(context.TODO(), generateTestEventKustomization("info", map[string]string{
eventv1.MetaRevisionKey: "badhash",
}))
assert.NotNil(t, err)
assert.Equal(t, err.Error(), "could not parse revision: failed to extract commit hash from 'badhash' revision")
}
func TestPostBitbucketServerBadBitbucketState(t *testing.T) {
b, err := NewBitbucketServer("kustomization/gitops-system/0c9c2e41", "https://example.com:7990/scm/projectfoo/repobar.git", "BBDC-ODIxODYxMzIyNzUyOttorMjO059P2rYTb6EH7mP", nil, "", "")
assert.Nil(t, err)
//Validate conversion to bitbucket state
err = b.Post(context.TODO(), generateTestEventKustomization("badserveritystate", map[string]string{
eventv1.MetaRevisionKey: "main@sha1:5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
}))
assert.NotNil(t, err)
assert.Equal(t, err.Error(), "couldn't convert to bitbucket server state: bitbucket server state generated on info or error events only")
}
func generateTestEventKustomization(severity string, metadata map[string]string) eventv1.Event {
return eventv1.Event{
InvolvedObject: corev1.ObjectReference{
Kind: "Kustomization",
Namespace: "flux-system",
Name: "hello-world",
},
Severity: severity,
Timestamp: metav1.Now(),
Message: "message",
Reason: "reason",
Metadata: metadata,
ReportingController: "kustomize-controller",
ReportingInstance: "kustomize-controller-xyz",
}
}
func TestBitBucketServerPostValidateRequest(t *testing.T) {
tests := []struct {
name string
errorString string
testFailReason string
headers map[string]string
username string
password string
token string
event eventv1.Event
commitStatus string
key string
uriHash string
}{
{
name: "Validate Token Auth ",
token: "goodtoken",
commitStatus: "kustomization/gitops-system/0c9c2e41",
headers: map[string]string{
"Authorization": "Bearer goodtoken",
"x-atlassian-token": "no-check",
"x-requested-with": "XMLHttpRequest",
},
event: generateTestEventKustomization("info", map[string]string{
eventv1.MetaRevisionKey: "main@sha1:5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
}),
key: sha1String("kustomization/gitops-system/0c9c2e41"),
uriHash: "5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
},
{
name: "Event with origin revision",
token: "goodtoken",
commitStatus: "kustomization/gitops-system/0c9c2e41",
headers: map[string]string{
"Authorization": "Bearer goodtoken",
"x-atlassian-token": "no-check",
"x-requested-with": "XMLHttpRequest",
},
event: generateTestEventKustomization("info", map[string]string{
eventv1.MetaRevisionKey: "main@sha1:5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
eventv1.MetaOriginRevisionKey: "main@sha1:e7c17dd8b8384bbc84b7e7385394cb7f48332b2d",
}),
key: sha1String("kustomization/gitops-system/0c9c2e41"),
uriHash: "e7c17dd8b8384bbc84b7e7385394cb7f48332b2d",
},
{
name: "Validate Basic Auth and Post State=Successful",
username: "hello",
password: "password",
commitStatus: "kustomization/gitops-system/0c9c2e41",
headers: map[string]string{
"Authorization": "Basic " + base64.StdEncoding.EncodeToString([]byte("hello"+":"+"password")),
"x-atlassian-token": "no-check",
"x-requested-with": "XMLHttpRequest",
},
event: generateTestEventKustomization("info", map[string]string{
eventv1.MetaRevisionKey: "main@sha1:5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
}),
key: sha1String("kustomization/gitops-system/0c9c2e41"),
uriHash: "5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
},
{
name: "Validate Post State=Failed",
username: "hello",
password: "password",
commitStatus: "kustomization/gitops-system/0c9c2e41",
headers: map[string]string{
"Authorization": "Basic " + base64.StdEncoding.EncodeToString([]byte("hello"+":"+"password")),
"x-atlassian-token": "no-check",
"x-requested-with": "XMLHttpRequest",
},
event: generateTestEventKustomization("error", map[string]string{
eventv1.MetaRevisionKey: "main@sha1:5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
}),
key: sha1String("kustomization/gitops-system/0c9c2e41"),
uriHash: "5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
},
{
name: "Fail if bad json response in existing commit status",
testFailReason: "badjson",
errorString: "could not get existing commit status: could not unmarshal json response body for duplicate commit status: unexpected end of JSON input",
username: "hello",
password: "password",
commitStatus: "kustomization/gitops-system/0c9c2e41",
headers: map[string]string{
"Authorization": "Basic " + base64.StdEncoding.EncodeToString([]byte("hello"+":"+"password")),
"x-atlassian-token": "no-check",
"x-requested-with": "XMLHttpRequest",
},
event: generateTestEventKustomization("error", map[string]string{
eventv1.MetaRevisionKey: "main@sha1:5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
}),
key: sha1String("kustomization/gitops-system/0c9c2e41"),
uriHash: "5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
},
{
name: "Fail if status code is non-200 in existing commit status",
testFailReason: "badstatuscode",
errorString: "could not get existing commit status: failed api call to check duplicate commit status: 400 - Bad Request",
username: "hello",
password: "password",
commitStatus: "kustomization/gitops-system/0c9c2e41",
headers: map[string]string{
"Authorization": "Basic " + base64.StdEncoding.EncodeToString([]byte("hello"+":"+"password")),
"x-atlassian-token": "no-check",
"x-requested-with": "XMLHttpRequest",
},
event: generateTestEventKustomization("error", map[string]string{
eventv1.MetaRevisionKey: "main@sha1:5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
}),
key: sha1String("kustomization/gitops-system/0c9c2e41"),
uriHash: "5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
},
{
name: "Bad post- Unauthorized",
testFailReason: "badpost",
errorString: "could not post build status: could not post build commit status: 401 - Unauthorized",
username: "hello",
password: "password",
commitStatus: "kustomization/gitops-system/0c9c2e41",
headers: map[string]string{
"Authorization": "Basic " + base64.StdEncoding.EncodeToString([]byte("hello"+":"+"password")),
"x-atlassian-token": "no-check",
"x-requested-with": "XMLHttpRequest",
},
event: generateTestEventKustomization("error", map[string]string{
eventv1.MetaRevisionKey: "main@sha1:5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
}),
key: sha1String("kustomization/gitops-system/0c9c2e41"),
uriHash: "5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
},
{
name: "Validate duplicate commit status successful match",
username: "hello",
password: "password",
commitStatus: "kustomization/gitops-system/0c9c2e41",
headers: map[string]string{
"Authorization": "Basic " + base64.StdEncoding.EncodeToString([]byte("hello"+":"+"password")),
"x-atlassian-token": "no-check",
"x-requested-with": "XMLHttpRequest",
},
event: generateTestEventKustomization("info", map[string]string{
eventv1.MetaRevisionKey: "main@sha1:5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
}),
key: sha1String("kustomization/gitops-system/0c9c2e41"),
uriHash: "5394cb7f48332b2de7c17dd8b8384bbc84b7e738",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Validate Headers
for key, value := range tt.headers {
require.Equal(t, value, r.Header.Get(key))
}
// Validate URI
path := fmt.Sprintf("/rest/api/latest/projects/projectfoo/repos/repobar/commits/%s/builds", tt.uriHash)
require.Equal(t, r.URL.Path, path)
// Validate Get Build Status call
if r.Method == http.MethodGet {
//Validate that this GET request has a query string with "key" as the query paraneter
require.Equal(t, r.URL.Query().Get(bbServerGetBuildStatusQueryString), tt.key)
// Validate that this GET request has no body
require.Equal(t, http.NoBody, r.Body)
if tt.name == "Validate duplicate commit status successful match" {
w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "application/json")
name, desc := formatNameAndDescription(tt.event)
name = name + " [" + desc + "]"
jsondata, _ := json.Marshal(&bbServerBuildStatus{
Name: name,
Description: desc,
Key: sha1String(tt.commitStatus),
State: "SUCCESSFUL",
Url: "https://example.com:7990/scm/projectfoo/repobar.git",
})
w.Write(jsondata)
}
if tt.testFailReason == "badstatuscode" {
w.WriteHeader(http.StatusBadRequest)
} else if tt.testFailReason == "badjson" {
w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "application/json")
//Do nothing here and an empty/null body will be returned
} else {
if tt.name != "Validate duplicate commit status successful match" {
w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "application/json")
w.Write([]byte(`{
"description": "reconciliation succeeded",
"key": "TEST2",
"state": "SUCCESSFUL",
"name": "kustomization/helloworld-yaml-2-bitbucket-server [reconciliation succeeded]",
"url": "https://example.com:7990/scm/projectfoo/repobar.git"
}`))
}
}
}
// Validate Post BuildStatus call
if r.Method == http.MethodPost {
// Validate that this POST request has no query string
require.Equal(t, len(r.URL.Query()), 0)
// Validate that this POST request has Content-Type: application/json header
require.Equal(t, "application/json", r.Header.Get("Content-Type"))
// Read json body of the request
b, err := io.ReadAll(r.Body)
require.NoError(t, err)
// Parse json request into Payload Request body struct
var payload bbServerBuildStatusSetRequest
err = json.Unmarshal(b, &payload)
require.NoError(t, err)
// Validate Key
require.Equal(t, payload.Key, tt.key)
// Validate that state can be only SUCCESSFUL or FAILED
if payload.State != "SUCCESSFUL" && payload.State != "FAILED" {
require.Fail(t, "Invalid state")
}
// If severity of event is info, state should be SUCCESSFUL
if tt.event.Severity == "info" {
require.Equal(t, "SUCCESSFUL", payload.State)
}
// If severity of event is error, state should be FAILED
if tt.event.Severity == "error" {
require.Equal(t, "FAILED", payload.State)
}
// Validate description
require.Equal(t, "reason", payload.Description)
// Validate name(with description appended)
require.Equal(t, "kustomization/hello-world"+" ["+payload.Description+"]", payload.Name)
require.Contains(t, payload.Url, "/scm/projectfoo/repobar.git")
if tt.testFailReason == "badpost" {
w.WriteHeader(http.StatusUnauthorized)
}
// Sending a bad response here
// This proves that the duplicate commit status is never posted
if tt.name == "Validate duplicate commit status successful match" {
w.WriteHeader(http.StatusUnauthorized)
}
}
}))
defer ts.Close()
c, err := NewBitbucketServer(tt.commitStatus, ts.URL+"/scm/projectfoo/repobar.git", tt.token, nil, tt.username, tt.password)
require.NoError(t, err)
err = c.Post(context.TODO(), tt.event)
if tt.testFailReason == "" {
require.NoError(t, err)
} else {
assert.NotNil(t, err)
assert.Equal(t, err.Error(), tt.errorString)
}
})
}
}

View File

@ -19,91 +19,130 @@ package notifier
import (
"context"
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"net/url"
"runtime"
"time"
"github.com/hashicorp/go-retryablehttp"
)
type requestOptFunc func(*retryablehttp.Request)
type postOptions struct {
proxy string
tlsConfig *tls.Config
requestModifier func(*retryablehttp.Request)
responseValidator func(statusCode int, body []byte) error
}
func postMessage(ctx context.Context, address, proxy string, certPool *x509.CertPool, payload interface{}, reqOpts ...requestOptFunc) error {
httpClient := retryablehttp.NewClient()
if certPool != nil {
httpClient.HTTPClient.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certPool,
},
}
}
type postOption func(*postOptions)
if proxy != "" {
proxyURL, err := url.Parse(proxy)
if err != nil {
return fmt.Errorf("unable to parse proxy URL '%s', error: %w", proxy, err)
}
var tlsConfig *tls.Config
if certPool != nil {
tlsConfig = &tls.Config{
RootCAs: certPool,
func postMessage(ctx context.Context, address string, payload interface{}, opts ...postOption) error {
options := &postOptions{
// Default validateResponse function verifies that the response status code is 200, 202 or 201.
responseValidator: func(statusCode int, body []byte) error {
if statusCode == http.StatusOK ||
statusCode == http.StatusAccepted ||
statusCode == http.StatusCreated {
return nil
}
}
httpClient.HTTPClient.Transport = &http.Transport{
Proxy: http.ProxyURL(proxyURL),
TLSClientConfig: tlsConfig,
DialContext: (&net.Dialer{
Timeout: 15 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1,
}
return fmt.Errorf("request failed with status code %d, %s", statusCode, string(body))
},
}
httpClient.HTTPClient.Timeout = 15 * time.Second
httpClient.RetryWaitMin = 2 * time.Second
httpClient.RetryWaitMax = 30 * time.Second
httpClient.RetryMax = 4
httpClient.Logger = nil
for _, o := range opts {
o(options)
}
httpClient, err := newHTTPClient(options)
if err != nil {
return err
}
data, err := json.Marshal(payload)
if err != nil {
return fmt.Errorf("marshalling notification payload failed: %w", err)
}
req, err := retryablehttp.NewRequest(http.MethodPost, address, data)
req, err := retryablehttp.NewRequestWithContext(ctx, http.MethodPost, address, data)
if err != nil {
return fmt.Errorf("failed to create a new request: %w", err)
}
if ctx != nil {
req = req.WithContext(ctx)
}
req.Header.Set("Content-Type", "application/json")
for _, o := range reqOpts {
o(req)
if options.requestModifier != nil {
options.requestModifier(req)
}
resp, err := httpClient.Do(req)
if err != nil {
return fmt.Errorf("failed to execute request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted && resp.StatusCode != http.StatusCreated {
b, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("unable to read response body, %s", err)
}
return fmt.Errorf("request failed with status code %d, %s", resp.StatusCode, string(b))
body, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("failed to read response body: %w", err)
}
if err := options.responseValidator(resp.StatusCode, body); err != nil {
return fmt.Errorf("request failed: %w", err)
}
return nil
}
func withProxy(proxy string) postOption {
return func(opts *postOptions) {
opts.proxy = proxy
}
}
func withTLSConfig(tlsConfig *tls.Config) postOption {
return func(opts *postOptions) {
opts.tlsConfig = tlsConfig
}
}
func withRequestModifier(reqModifier func(*retryablehttp.Request)) postOption {
return func(opts *postOptions) {
opts.requestModifier = reqModifier
}
}
func withResponseValidator(respValidator func(statusCode int, body []byte) error) postOption {
return func(opts *postOptions) {
opts.responseValidator = respValidator
}
}
func newHTTPClient(opts *postOptions) (*retryablehttp.Client, error) {
httpClient := retryablehttp.NewClient()
transport := httpClient.HTTPClient.Transport.(*http.Transport)
if opts.tlsConfig != nil {
transport.TLSClientConfig = opts.tlsConfig
}
if opts.proxy != "" {
proxyURL, err := url.Parse(opts.proxy)
if err != nil {
return nil, fmt.Errorf("unable to parse proxy URL: %w", err)
}
transport.Proxy = http.ProxyURL(proxyURL)
}
// Disable the timeout for the HTTP client,
// as we set the provider timeout on the context.
httpClient.HTTPClient.Timeout = 0
httpClient.RetryWaitMin = 2 * time.Second
httpClient.RetryWaitMax = 30 * time.Second
httpClient.RetryMax = 4
httpClient.Logger = nil
return httpClient, nil
}

View File

@ -18,14 +18,19 @@ package notifier
import (
"context"
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
"github.com/hashicorp/go-retryablehttp"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -44,10 +49,21 @@ func Test_postMessage(t *testing.T) {
require.Equal(t, "success", payload["status"])
}))
defer ts.Close()
err := postMessage(context.Background(), ts.URL, "", nil, map[string]string{"status": "success"})
err := postMessage(context.Background(), ts.URL, map[string]string{"status": "success"})
require.NoError(t, err)
}
func Test_postMessage_timeout(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(2 * time.Second)
}))
defer ts.Close()
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
err := postMessage(ctx, ts.URL, map[string]string{"status": "success"})
require.Error(t, err, "context deadline exceeded")
}
func Test_postSelfSignedCert(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
b, err := io.ReadAll(r.Body)
@ -65,10 +81,43 @@ func Test_postSelfSignedCert(t *testing.T) {
require.NoError(t, err)
certpool := x509.NewCertPool()
certpool.AddCert(cert)
err = postMessage(context.Background(), ts.URL, "", certpool, map[string]string{"status": "success"})
tlsConfig := &tls.Config{RootCAs: certpool}
err = postMessage(context.Background(), ts.URL, map[string]string{"status": "success"}, withTLSConfig(tlsConfig))
require.NoError(t, err)
}
func Test_postMessage_requestModifier(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
require.Equal(t, "Bearer token", r.Header.Get("Authorization"))
}))
defer ts.Close()
err := postMessage(context.Background(), ts.URL, map[string]string{"status": "success"}, withRequestModifier(func(req *retryablehttp.Request) {
req.Header.Set("Authorization", "Bearer token")
}))
require.NoError(t, err)
}
func Test_postMessage_responseValidator(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Default response validator determines success, but the custom validator below will determine failure .
w.WriteHeader(http.StatusOK)
w.Write([]byte("error: bad request"))
}))
defer ts.Close()
err := postMessage(context.Background(), ts.URL, map[string]string{"status": "success"})
require.NoError(t, err)
err = postMessage(context.Background(), ts.URL, map[string]string{"status": "success"}, withResponseValidator(func(_ int, body []byte) error {
if strings.HasPrefix(string(body), "error:") {
return errors.New(string(body))
}
return nil
}))
require.ErrorContains(t, err, "request failed: error: bad request")
}
func testEvent() eventv1.Event {
return eventv1.Event{
InvolvedObject: corev1.ObjectReference{

View File

@ -19,7 +19,6 @@ package notifier
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"net/url"
@ -41,7 +40,7 @@ type DataDog struct {
// url: The DataDog API endpoint to use. Examples: https://api.datadoghq.com, https://api.datadoghq.eu, etc.
// token: The DataDog API key (not the application key).
// headers: A map of extra tags to add to the event
func NewDataDog(address string, proxyUrl string, certPool *x509.CertPool, token string) (*DataDog, error) {
func NewDataDog(address string, proxyUrl string, tlsConfig *tls.Config, token string) (*DataDog, error) {
conf := datadog.NewConfiguration()
if token == "" {
@ -56,7 +55,7 @@ func NewDataDog(address string, proxyUrl string, certPool *x509.CertPool, token
conf.Host = baseUrl.Host
conf.Scheme = baseUrl.Scheme
if proxyUrl != "" || certPool != nil {
if proxyUrl != "" || tlsConfig != nil {
transport := &http.Transport{}
if proxyUrl != "" {
@ -68,10 +67,8 @@ func NewDataDog(address string, proxyUrl string, certPool *x509.CertPool, token
transport.Proxy = http.ProxyURL(proxy)
}
if certPool != nil {
transport.TLSClientConfig = &tls.Config{
RootCAs: certPool,
}
if tlsConfig != nil {
transport.TLSClientConfig = tlsConfig
}
conf.HTTPClient = &http.Client{

View File

@ -2,6 +2,7 @@ package notifier
import (
"context"
"crypto/tls"
"crypto/x509"
"io"
"net/http"
@ -33,7 +34,8 @@ func Fuzz_DataDog(f *testing.F) {
var cert x509.CertPool
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
dd, err := NewDataDog(ts.URL, "", &cert, apiKey)
tlsConfig := &tls.Config{RootCAs: &cert}
dd, err := NewDataDog(ts.URL, "", tlsConfig, apiKey)
if err != nil {
return
}

View File

@ -90,8 +90,12 @@ func (s *Discord) Post(ctx context.Context, event eventv1.Event) error {
payload.Attachments = []SlackAttachment{a}
err := postMessage(ctx, s.URL, s.ProxyURL, nil, payload)
if err != nil {
var opts []postOption
if s.ProxyURL != "" {
opts = append(opts, withProxy(s.ProxyURL))
}
if err := postMessage(ctx, s.URL, payload, opts...); err != nil {
return fmt.Errorf("postMessage failed: %w", err)
}

View File

@ -17,110 +17,341 @@ limitations under the License.
package notifier
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
apiv1 "github.com/fluxcd/notification-controller/api/v1beta2"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/pkg/cache"
apiv1 "github.com/fluxcd/notification-controller/api/v1beta3"
)
type Factory struct {
URL string
ProxyURL string
Username string
Channel string
Token string
Headers map[string]string
CertPool *x509.CertPool
Password string
ProviderUID string
var (
// notifiers is a map of notifier names to factory functions.
notifiers = notifierMap{
// GenericProvider is the default notifier
apiv1.GenericProvider: genericNotifierFunc,
apiv1.GenericHMACProvider: genericHMACNotifierFunc,
apiv1.SlackProvider: slackNotifierFunc,
apiv1.DiscordProvider: discordNotifierFunc,
apiv1.RocketProvider: rocketNotifierFunc,
apiv1.MSTeamsProvider: msteamsNotifierFunc,
apiv1.GoogleChatProvider: googleChatNotifierFunc,
apiv1.GooglePubSubProvider: googlePubSubNotifierFunc,
apiv1.WebexProvider: webexNotifierFunc,
apiv1.SentryProvider: sentryNotifierFunc,
apiv1.AzureEventHubProvider: azureEventHubNotifierFunc,
apiv1.TelegramProvider: telegramNotifierFunc,
apiv1.LarkProvider: larkNotifierFunc,
apiv1.Matrix: matrixNotifierFunc,
apiv1.OpsgenieProvider: opsgenieNotifierFunc,
apiv1.AlertManagerProvider: alertmanagerNotifierFunc,
apiv1.GrafanaProvider: grafanaNotifierFunc,
apiv1.PagerDutyProvider: pagerDutyNotifierFunc,
apiv1.DataDogProvider: dataDogNotifierFunc,
apiv1.NATSProvider: natsNotifierFunc,
apiv1.GitHubProvider: gitHubNotifierFunc,
apiv1.GitHubDispatchProvider: gitHubDispatchNotifierFunc,
apiv1.GitLabProvider: gitLabNotifierFunc,
apiv1.GiteaProvider: giteaNotifierFunc,
apiv1.BitbucketServerProvider: bitbucketServerNotifierFunc,
apiv1.BitbucketProvider: bitbucketNotifierFunc,
apiv1.AzureDevOpsProvider: azureDevOpsNotifierFunc,
}
)
// notifierMap is a map of provider names to notifier factory functions
type notifierMap map[string]factoryFunc
// factoryFunc is a factory function that creates a new notifier
type factoryFunc func(opts notifierOptions) (Interface, error)
type notifierOptions struct {
Context context.Context
URL string
ProxyURL string
Username string
Channel string
Token string
Headers map[string]string
// CertPool is kept for Git platform providers (GitHub, GitLab, etc.) that use third-party SDKs.
// TODO: Remove this field once all notifiers support client certificate authentication via TLSConfig.
CertPool *x509.CertPool
TLSConfig *tls.Config
Password string
CommitStatus string
ProviderName string
ProviderNamespace string
SecretData map[string][]byte
ServiceAccountName string
TokenCache *cache.TokenCache
TokenClient client.Client
}
func NewFactory(url string,
proxy string,
username string,
channel string,
token string,
headers map[string]string,
certPool *x509.CertPool,
password string,
providerUID string) *Factory {
type Factory struct {
notifierOptions
}
// Option represents a functional option for configuring a notifier.
type Option func(*notifierOptions)
// WithProxyURL sets the proxy URL for the notifier.
func WithProxyURL(url string) Option {
return func(o *notifierOptions) {
o.ProxyURL = url
}
}
// WithUsername sets the username for the notifier.
func WithUsername(username string) Option {
return func(o *notifierOptions) {
o.Username = username
}
}
// WithChannel sets the channel for the notifier.
func WithChannel(channel string) Option {
return func(o *notifierOptions) {
o.Channel = channel
}
}
// WithToken sets the token for the notifier.
func WithToken(token string) Option {
return func(o *notifierOptions) {
o.Token = token
}
}
// WithHeaders sets the headers for the notifier.
func WithHeaders(headers map[string]string) Option {
return func(o *notifierOptions) {
o.Headers = headers
}
}
// WithCertPool sets the certificate pool for the notifier.
func WithCertPool(certPool *x509.CertPool) Option {
return func(o *notifierOptions) {
o.CertPool = certPool
}
}
// WithTLSConfig sets the TLS configuration for the notifier.
func WithTLSConfig(tlsConfig *tls.Config) Option {
return func(o *notifierOptions) {
o.TLSConfig = tlsConfig
}
}
// WithPassword sets the password for the notifier.
func WithPassword(password string) Option {
return func(o *notifierOptions) {
o.Password = password
}
}
// WithCommitStatus sets the custom commit status for the notifier.
func WithCommitStatus(commitStatus string) Option {
return func(o *notifierOptions) {
o.CommitStatus = commitStatus
}
}
// WithProviderName sets the provider name for the notifier.
func WithProviderName(name string) Option {
return func(o *notifierOptions) {
o.ProviderName = name
}
}
// WithProviderNamespace sets the provider namespace for the notifier.
func WithProviderNamespace(namespace string) Option {
return func(o *notifierOptions) {
o.ProviderNamespace = namespace
}
}
// WithSecretData sets the secret data for the notifier.
func WithSecretData(data map[string][]byte) Option {
return func(o *notifierOptions) {
o.SecretData = data
}
}
// WithTokenCache sets the token cache for the notifier.
func WithTokenCache(cache *cache.TokenCache) Option {
return func(o *notifierOptions) {
o.TokenCache = cache
}
}
// WithTokenClient sets the token client for the notifier.
func WithTokenClient(kubeClient client.Client) Option {
return func(o *notifierOptions) {
o.TokenClient = kubeClient
}
}
// WithServiceAccount sets the service account for the notifier.
func WithServiceAccount(serviceAccountName string) Option {
return func(o *notifierOptions) {
o.ServiceAccountName = serviceAccountName
}
}
// WithURL sets the webhook URL for the notifier.
func WithURL(url string) Option {
return func(o *notifierOptions) {
o.URL = url
}
}
// NewFactory creates a new notifier factory with optional configurations.
func NewFactory(ctx context.Context, opts ...Option) *Factory {
options := notifierOptions{
Context: ctx,
}
for _, opt := range opts {
opt(&options)
}
return &Factory{
URL: url,
ProxyURL: proxy,
Channel: channel,
Username: username,
Token: token,
Headers: headers,
CertPool: certPool,
Password: password,
ProviderUID: providerUID,
notifierOptions: options,
}
}
func (f Factory) Notifier(provider string) (Interface, error) {
if f.URL == "" {
return &NopNotifier{}, nil
notifier, ok := notifiers[provider]
if !ok {
return nil, fmt.Errorf("provider %s not supported", provider)
}
var n Interface
var err error
switch provider {
case apiv1.GenericProvider:
n, err = NewForwarder(f.URL, f.ProxyURL, f.Headers, f.CertPool, nil)
case apiv1.GenericHMACProvider:
n, err = NewForwarder(f.URL, f.ProxyURL, f.Headers, f.CertPool, []byte(f.Token))
case apiv1.SlackProvider:
n, err = NewSlack(f.URL, f.ProxyURL, f.Token, f.CertPool, f.Username, f.Channel)
case apiv1.DiscordProvider:
n, err = NewDiscord(f.URL, f.ProxyURL, f.Username, f.Channel)
case apiv1.RocketProvider:
n, err = NewRocket(f.URL, f.ProxyURL, f.CertPool, f.Username, f.Channel)
case apiv1.MSTeamsProvider:
n, err = NewMSTeams(f.URL, f.ProxyURL, f.CertPool)
case apiv1.GitHubProvider:
n, err = NewGitHub(f.ProviderUID, f.URL, f.Token, f.CertPool)
case apiv1.GitHubDispatchProvider:
n, err = NewGitHubDispatch(f.URL, f.Token, f.CertPool)
case apiv1.GitLabProvider:
n, err = NewGitLab(f.ProviderUID, f.URL, f.Token, f.CertPool)
case apiv1.GiteaProvider:
n, err = NewGitea(f.ProviderUID, f.URL, f.Token, f.CertPool)
case apiv1.BitbucketProvider:
n, err = NewBitbucket(f.ProviderUID, f.URL, f.Token, f.CertPool)
case apiv1.AzureDevOpsProvider:
n, err = NewAzureDevOps(f.ProviderUID, f.URL, f.Token, f.CertPool)
case apiv1.GoogleChatProvider:
n, err = NewGoogleChat(f.URL, f.ProxyURL)
case apiv1.GooglePubSubProvider:
n, err = NewGooglePubSub(f.URL, f.Channel, f.Token, f.Headers)
case apiv1.WebexProvider:
n, err = NewWebex(f.URL, f.ProxyURL, f.CertPool, f.Channel, f.Token)
case apiv1.SentryProvider:
n, err = NewSentry(f.CertPool, f.URL, f.Channel)
case apiv1.AzureEventHubProvider:
n, err = NewAzureEventHub(f.URL, f.Token, f.Channel)
case apiv1.TelegramProvider:
n, err = NewTelegram(f.Channel, f.Token)
case apiv1.LarkProvider:
n, err = NewLark(f.URL)
case apiv1.Matrix:
n, err = NewMatrix(f.URL, f.Token, f.Channel, f.CertPool)
case apiv1.OpsgenieProvider:
n, err = NewOpsgenie(f.URL, f.ProxyURL, f.CertPool, f.Token)
case apiv1.AlertManagerProvider:
n, err = NewAlertmanager(f.URL, f.ProxyURL, f.CertPool)
case apiv1.GrafanaProvider:
n, err = NewGrafana(f.URL, f.ProxyURL, f.Token, f.CertPool, f.Username, f.Password)
case apiv1.PagerDutyProvider:
n, err = NewPagerDuty(f.URL, f.ProxyURL, f.CertPool, f.Channel)
case apiv1.DataDogProvider:
n, err = NewDataDog(f.URL, f.ProxyURL, f.CertPool, f.Token)
default:
err = fmt.Errorf("provider %s not supported", provider)
}
if err != nil {
n = &NopNotifier{}
}
return n, err
return notifier(f.notifierOptions)
}
func genericNotifierFunc(opts notifierOptions) (Interface, error) {
return NewForwarder(opts.URL, opts.ProxyURL, opts.Headers, opts.TLSConfig, nil)
}
func genericHMACNotifierFunc(opts notifierOptions) (Interface, error) {
return NewForwarder(opts.URL, opts.ProxyURL, opts.Headers, opts.TLSConfig, []byte(opts.Token))
}
func slackNotifierFunc(opts notifierOptions) (Interface, error) {
return NewSlack(opts.URL, opts.ProxyURL, opts.Token, opts.TLSConfig, opts.Username, opts.Channel)
}
func discordNotifierFunc(opts notifierOptions) (Interface, error) {
return NewDiscord(opts.URL, opts.ProxyURL, opts.Username, opts.Channel)
}
func rocketNotifierFunc(opts notifierOptions) (Interface, error) {
return NewRocket(opts.URL, opts.ProxyURL, opts.TLSConfig, opts.Username, opts.Channel)
}
func msteamsNotifierFunc(opts notifierOptions) (Interface, error) {
return NewMSTeams(opts.URL, opts.ProxyURL, opts.TLSConfig)
}
func googleChatNotifierFunc(opts notifierOptions) (Interface, error) {
return NewGoogleChat(opts.URL, opts.ProxyURL)
}
func googlePubSubNotifierFunc(opts notifierOptions) (Interface, error) {
return NewGooglePubSub(&opts)
}
func webexNotifierFunc(opts notifierOptions) (Interface, error) {
return NewWebex(opts.URL, opts.ProxyURL, opts.TLSConfig, opts.Channel, opts.Token)
}
func sentryNotifierFunc(opts notifierOptions) (Interface, error) {
return NewSentry(opts.TLSConfig, opts.URL, opts.Channel)
}
func azureEventHubNotifierFunc(opts notifierOptions) (Interface, error) {
return NewAzureEventHub(opts.Context, opts.URL, opts.Token, opts.Channel, opts.ProxyURL, opts.ServiceAccountName, opts.ProviderName, opts.ProviderNamespace, opts.TokenClient, opts.TokenCache)
}
func telegramNotifierFunc(opts notifierOptions) (Interface, error) {
return NewTelegram(opts.ProxyURL, opts.Channel, opts.Token)
}
func larkNotifierFunc(opts notifierOptions) (Interface, error) {
return NewLark(opts.URL)
}
func matrixNotifierFunc(opts notifierOptions) (Interface, error) {
return NewMatrix(opts.URL, opts.Token, opts.Channel, opts.TLSConfig)
}
func opsgenieNotifierFunc(opts notifierOptions) (Interface, error) {
return NewOpsgenie(opts.URL, opts.ProxyURL, opts.TLSConfig, opts.Token)
}
func alertmanagerNotifierFunc(opts notifierOptions) (Interface, error) {
return NewAlertmanager(opts.URL, opts.ProxyURL, opts.TLSConfig, opts.Token, opts.Username, opts.Password)
}
func grafanaNotifierFunc(opts notifierOptions) (Interface, error) {
return NewGrafana(opts.URL, opts.ProxyURL, opts.Token, opts.TLSConfig, opts.Username, opts.Password)
}
func pagerDutyNotifierFunc(opts notifierOptions) (Interface, error) {
return NewPagerDuty(opts.URL, opts.ProxyURL, opts.TLSConfig, opts.Channel)
}
func dataDogNotifierFunc(opts notifierOptions) (Interface, error) {
return NewDataDog(opts.URL, opts.ProxyURL, opts.TLSConfig, opts.Token)
}
func natsNotifierFunc(opts notifierOptions) (Interface, error) {
return NewNATS(opts.URL, opts.Channel, opts.Username, opts.Password)
}
func gitHubNotifierFunc(opts notifierOptions) (Interface, error) {
if opts.Token == "" && opts.Password != "" {
opts.Token = opts.Password
}
return NewGitHub(opts.CommitStatus, opts.URL, opts.Token, opts.TLSConfig, opts.ProxyURL, opts.ProviderName, opts.ProviderNamespace, opts.SecretData, opts.TokenCache)
}
func gitHubDispatchNotifierFunc(opts notifierOptions) (Interface, error) {
if opts.Token == "" && opts.Password != "" {
opts.Token = opts.Password
}
return NewGitHubDispatch(opts.URL, opts.Token, opts.TLSConfig, opts.ProxyURL, opts.ProviderName, opts.ProviderNamespace, opts.SecretData, opts.TokenCache)
}
func gitLabNotifierFunc(opts notifierOptions) (Interface, error) {
if opts.Token == "" && opts.Password != "" {
opts.Token = opts.Password
}
return NewGitLab(opts.CommitStatus, opts.URL, opts.Token, opts.TLSConfig)
}
func giteaNotifierFunc(opts notifierOptions) (Interface, error) {
if opts.Token == "" && opts.Password != "" {
opts.Token = opts.Password
}
return NewGitea(opts.CommitStatus, opts.URL, opts.ProxyURL, opts.Token, opts.TLSConfig)
}
func bitbucketServerNotifierFunc(opts notifierOptions) (Interface, error) {
return NewBitbucketServer(opts.CommitStatus, opts.URL, opts.Token, opts.TLSConfig, opts.Username, opts.Password)
}
func bitbucketNotifierFunc(opts notifierOptions) (Interface, error) {
return NewBitbucket(opts.CommitStatus, opts.URL, opts.Token, opts.TLSConfig)
}
func azureDevOpsNotifierFunc(opts notifierOptions) (Interface, error) {
return NewAzureDevOps(opts.Context, opts.CommitStatus, opts.URL, opts.Token,
opts.TLSConfig, opts.ProxyURL, opts.ServiceAccountName, opts.ProviderName,
opts.ProviderNamespace, opts.TokenClient, opts.TokenCache)
}

View File

@ -20,7 +20,7 @@ import (
"context"
"crypto/hmac"
"crypto/sha256"
"crypto/x509"
"crypto/tls"
"encoding/json"
"fmt"
"net/url"
@ -37,14 +37,14 @@ const NotificationHeader = "gotk-component"
// Forwarder is an implementation of the notification Interface that posts the
// body as an HTTP request using an optional proxy.
type Forwarder struct {
URL string
ProxyURL string
Headers map[string]string
CertPool *x509.CertPool
HMACKey []byte
URL string
ProxyURL string
Headers map[string]string
TLSConfig *tls.Config
HMACKey []byte
}
func NewForwarder(hookURL string, proxyURL string, headers map[string]string, certPool *x509.CertPool, hmacKey []byte) (*Forwarder, error) {
func NewForwarder(hookURL string, proxyURL string, headers map[string]string, tlsConfig *tls.Config, hmacKey []byte) (*Forwarder, error) {
if _, err := url.ParseRequestURI(hookURL); err != nil {
return nil, fmt.Errorf("invalid hook URL %s: %w", hookURL, err)
}
@ -54,11 +54,11 @@ func NewForwarder(hookURL string, proxyURL string, headers map[string]string, ce
}
return &Forwarder{
URL: hookURL,
ProxyURL: proxyURL,
Headers: headers,
CertPool: certPool,
HMACKey: hmacKey,
URL: hookURL,
ProxyURL: proxyURL,
Headers: headers,
HMACKey: hmacKey,
TLSConfig: tlsConfig,
}, nil
}
@ -77,18 +77,28 @@ func (f *Forwarder) Post(ctx context.Context, event eventv1.Event) error {
}
sig = fmt.Sprintf("sha256=%s", sign(eventJSON, f.HMACKey))
}
err := postMessage(ctx, f.URL, f.ProxyURL, f.CertPool, event, func(req *retryablehttp.Request) {
req.Header.Set(NotificationHeader, event.ReportingController)
for key, val := range f.Headers {
req.Header.Set(key, val)
}
if sig != "" {
req.Header.Set("X-Signature", sig)
}
})
if err != nil {
opts := []postOption{
withRequestModifier(func(req *retryablehttp.Request) {
req.Header.Set(NotificationHeader, event.ReportingController)
for key, val := range f.Headers {
req.Header.Set(key, val)
}
if sig != "" {
req.Header.Set("X-Signature", sig)
}
}),
}
if f.ProxyURL != "" {
opts = append(opts, withProxy(f.ProxyURL))
}
if f.TLSConfig != nil {
opts = append(opts, withTLSConfig(f.TLSConfig))
}
if err := postMessage(ctx, f.URL, event, opts...); err != nil {
return fmt.Errorf("postMessage failed: %w", err)
}
return nil
}

View File

@ -18,7 +18,7 @@ package notifier
import (
"context"
"crypto/x509"
"crypto/tls"
"fmt"
"io"
"net/http"
@ -41,13 +41,13 @@ func Fuzz_Forwarder(f *testing.F) {
}))
defer ts.Close()
var cert x509.CertPool
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
var tlsConfig tls.Config
_ = fuzz.NewConsumer(seed).GenerateStruct(&tlsConfig)
header := make(map[string]string)
_ = fuzz.NewConsumer(seed).FuzzMap(&header)
forwarder, err := NewForwarder(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", header, &cert, hmacKey)
forwarder, err := NewForwarder(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", header, &tlsConfig, hmacKey)
if err != nil {
return
}

View File

@ -19,7 +19,6 @@ package notifier
import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"net/http"
@ -34,22 +33,27 @@ import (
)
type Gitea struct {
BaseURL string
Token string
Owner string
Repo string
ProviderUID string
Client *gitea.Client
Debug bool
BaseURL string
Token string
Owner string
Repo string
CommitStatus string
Client *gitea.Client
Debug bool
}
var _ Interface = &Gitea{}
func NewGitea(providerUID string, addr string, token string, certPool *x509.CertPool) (*Gitea, error) {
func NewGitea(commitStatus string, addr string, proxyURL string, token string, tlsConfig *tls.Config) (*Gitea, error) {
if len(token) == 0 {
return nil, errors.New("gitea token cannot be empty")
}
// this should never happen
if commitStatus == "" {
return nil, errors.New("commit status cannot be empty")
}
host, id, err := parseGitAddress(addr)
if err != nil {
return nil, fmt.Errorf("failed parsing Git URL: %w", err)
@ -64,33 +68,37 @@ func NewGitea(providerUID string, addr string, token string, certPool *x509.Cert
return nil, fmt.Errorf("invalid repository id %q", id)
}
client, err := gitea.NewClient(host, gitea.SetToken(token))
tr := &http.Transport{}
if tlsConfig != nil {
tr.TLSClientConfig = tlsConfig
}
if proxyURL != "" {
parsedProxyURL, err := url.Parse(proxyURL)
if err != nil {
return nil, errors.New("invalid proxy URL")
}
tr.Proxy = http.ProxyURL(parsedProxyURL)
}
client, err := gitea.NewClient(host, gitea.SetToken(token), gitea.SetHTTPClient(&http.Client{Transport: tr}))
if err != nil {
return nil, fmt.Errorf("failed creating Gitea client: %w", err)
}
if certPool != nil {
tr := &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certPool,
},
}
client.SetHTTPClient(&http.Client{Transport: tr})
}
return &Gitea{
BaseURL: host,
Token: token,
Owner: idComponents[0],
Repo: idComponents[1],
ProviderUID: providerUID,
Client: client,
Debug: os.Getenv("NOTIFIER_GITEA_DEBUG") == "true",
BaseURL: host,
Token: token,
Owner: idComponents[0],
Repo: idComponents[1],
CommitStatus: commitStatus,
Client: client,
Debug: os.Getenv("NOTIFIER_GITEA_DEBUG") == "true",
}, nil
}
func (g *Gitea) Post(ctx context.Context, event eventv1.Event) error {
revString, ok := event.Metadata[eventv1.MetaRevisionKey]
revString, ok := event.GetRevision()
if !ok {
return errors.New("missing revision metadata")
}
@ -104,7 +112,7 @@ func (g *Gitea) Post(ctx context.Context, event eventv1.Event) error {
}
_, desc := formatNameAndDescription(event)
id := generateCommitStatusID(g.ProviderUID, event)
id := g.CommitStatus
status := gitea.CreateStatusOption{
State: state,

View File

@ -18,7 +18,10 @@ package notifier
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
testproxy "github.com/fluxcd/notification-controller/tests/proxy"
"net/http"
"net/http/httptest"
"testing"
@ -31,10 +34,20 @@ import (
"github.com/stretchr/testify/assert"
)
// newTestServer returns an HTTP server mimicking parts of Gitea's API so that tests don't
// newTestHTTPServer returns an HTTP server mimicking parts of Gitea's API so that tests don't
// need to rely on 3rd-party components to be available (like the try.gitea.io server).
func newTestServer(t *testing.T) *httptest.Server {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
func newTestHTTPServer(t *testing.T) *httptest.Server {
return httptest.NewServer(newGiteaStubHandler(t))
}
// newTestHTTPSServer returns an HTTPS server mimicking parts of Gitea's API so that tests don't
// need to rely on 3rd-party components to be available (like the try.gitea.io server).
func newTestHTTPSServer(t *testing.T) *httptest.Server {
return httptest.NewTLSServer(newGiteaStubHandler(t))
}
func newGiteaStubHandler(t *testing.T) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api/v1/version":
fmt.Fprintf(w, `{"version":"1.18.3"}`)
@ -42,18 +55,79 @@ func newTestServer(t *testing.T) *httptest.Server {
fmt.Fprintf(w, "[]")
case "/api/v1/repos/foo/bar/statuses/69b59063470310ebbd88a9156325322a124e55a3":
fmt.Fprintf(w, "{}")
case "/api/v1/repos/foo/bar/commits/8a9156325322a124e55a369b59063470310ebbd8/statuses":
fmt.Fprintf(w, "[]")
case "/api/v1/repos/foo/bar/statuses/8a9156325322a124e55a369b59063470310ebbd8":
fmt.Fprintf(w, "{}")
default:
t.Logf("unknown %s request at %s", r.Method, r.URL.Path)
}
}))
return srv
})
}
func TestNewGiteaBasic(t *testing.T) {
srv := newTestServer(t)
srv := newTestHTTPServer(t)
defer srv.Close()
g, err := NewGitea("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", srv.URL+"/foo/bar", "foobar", nil)
g, err := NewGitea("kustomization/gitops-system/0c9c2e41", srv.URL+"/foo/bar", "", "foobar", nil)
assert.NoError(t, err)
assert.Equal(t, g.Owner, "foo")
assert.Equal(t, g.Repo, "bar")
assert.Equal(t, g.BaseURL, srv.URL)
}
func TestNewGiteaWithCertPool(t *testing.T) {
srv := newTestHTTPSServer(t)
defer srv.Close()
certPool := x509.NewCertPool()
certPool.AddCert(srv.Certificate())
tlsConfig := &tls.Config{RootCAs: certPool}
g, err := NewGitea("kustomization/gitops-system/0c9c2e41", srv.URL+"/foo/bar", "", "foobar", tlsConfig)
assert.NoError(t, err)
assert.Equal(t, g.Owner, "foo")
assert.Equal(t, g.Repo, "bar")
assert.Equal(t, g.BaseURL, srv.URL)
}
func TestNewGiteaNoCertificate(t *testing.T) {
srv := newTestHTTPSServer(t)
defer srv.Close()
certPool := x509.NewCertPool()
tlsConfig := &tls.Config{RootCAs: certPool}
_, err := NewGitea("kustomization/gitops-system/0c9c2e41", srv.URL+"/foo/bar", "", "foobar", tlsConfig)
assert.Error(t, err)
assert.ErrorContains(t, err, "tls: failed to verify certificate: x509: certificate signed by unknown authority")
}
func TestNewGiteaWithProxyURL(t *testing.T) {
srv := newTestHTTPServer(t)
defer srv.Close()
proxyAddr, _ := testproxy.New(t)
proxyURL := fmt.Sprintf("http://%s", proxyAddr)
g, err := NewGitea("kustomization/gitops-system/0c9c2e41", srv.URL+"/foo/bar", proxyURL, "foobar", nil)
assert.NoError(t, err)
assert.Equal(t, g.Owner, "foo")
assert.Equal(t, g.Repo, "bar")
assert.Equal(t, g.BaseURL, srv.URL)
}
func TestNewGiteaWithProxyURLAndCertPool(t *testing.T) {
srv := newTestHTTPSServer(t)
defer srv.Close()
certPool := x509.NewCertPool()
certPool.AddCert(srv.Certificate())
tlsConfig := &tls.Config{RootCAs: certPool}
proxyAddr, _ := testproxy.New(t)
proxyURL := fmt.Sprintf("http://%s", proxyAddr)
g, err := NewGitea("kustomization/gitops-system/0c9c2e41", srv.URL+"/foo/bar", proxyURL, "foobar", tlsConfig)
assert.NoError(t, err)
assert.Equal(t, g.Owner, "foo")
assert.Equal(t, g.Repo, "bar")
@ -61,44 +135,88 @@ func TestNewGiteaBasic(t *testing.T) {
}
func TestNewGiteaInvalidUrl(t *testing.T) {
srv := newTestServer(t)
srv := newTestHTTPServer(t)
defer srv.Close()
_, err := NewGitea("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", srv.URL+"/foo/bar/baz", "foobar", nil)
_, err := NewGitea("kustomization/gitops-system/0c9c2e41", srv.URL+"/foo/bar/baz", "", "foobar", nil)
assert.ErrorContains(t, err, "invalid repository id")
}
func TestNewGiteaInvalidProxyUrl(t *testing.T) {
_, err := NewGitea("kustomization/gitops-system/0c9c2e41", "/foo/bar", "wrong\nURL", "foobar", nil)
assert.ErrorContains(t, err, "invalid proxy URL")
}
func TestNewGiteaEmptyToken(t *testing.T) {
srv := newTestServer(t)
srv := newTestHTTPServer(t)
defer srv.Close()
_, err := NewGitea("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", srv.URL+"/foo/bar", "", nil)
_, err := NewGitea("kustomization/gitops-system/0c9c2e41", srv.URL+"/foo/bar", "", "", nil)
assert.ErrorContains(t, err, "gitea token cannot be empty")
}
func TestGitea_Post(t *testing.T) {
srv := newTestServer(t)
func TestNewGiteaEmptyCommitStatus(t *testing.T) {
srv := newTestHTTPServer(t)
defer srv.Close()
g, err := NewGitea("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", srv.URL+"/foo/bar", "foobar", nil)
_, err := NewGitea("", srv.URL+"/foo/bar", "", "foobar", nil)
assert.ErrorContains(t, err, "commit status cannot be empty")
}
func TestGitea_Post(t *testing.T) {
srv := newTestHTTPServer(t)
defer srv.Close()
g, err := NewGitea("kustomization/gitops-system/0c9c2e41", srv.URL+"/foo/bar", "", "foobar", nil)
assert.Nil(t, err)
event := eventv1.Event{
InvolvedObject: corev1.ObjectReference{
Kind: "Kustomization",
Namespace: "flux-system",
Name: "podinfo-repo",
for _, tt := range []struct {
name string
event eventv1.Event
}{
{
name: "revision key",
event: eventv1.Event{
InvolvedObject: corev1.ObjectReference{
Kind: "Kustomization",
Namespace: "flux-system",
Name: "podinfo-repo",
},
Severity: "info",
Timestamp: metav1.Time{
Time: time.Now(),
},
Metadata: map[string]string{
eventv1.MetaRevisionKey: "main@sha1:69b59063470310ebbd88a9156325322a124e55a3",
},
Message: "Service/podinfo/podinfo configured",
Reason: "",
},
},
Severity: "info",
Timestamp: metav1.Time{
Time: time.Now(),
{
name: "origin revision key",
event: eventv1.Event{
InvolvedObject: corev1.ObjectReference{
Kind: "Kustomization",
Namespace: "flux-system",
Name: "podinfo-repo",
},
Severity: "info",
Timestamp: metav1.Time{
Time: time.Now(),
},
Metadata: map[string]string{
eventv1.MetaRevisionKey: "main@sha1:69b59063470310ebbd88a9156325322a124e55a3",
eventv1.MetaOriginRevisionKey: "main@sha1:8a9156325322a124e55a369b59063470310ebbd8",
},
Message: "Service/podinfo/podinfo configured",
Reason: "",
},
},
Metadata: map[string]string{
eventv1.MetaRevisionKey: "main@sha1:69b59063470310ebbd88a9156325322a124e55a3",
},
Message: "Service/podinfo/podinfo configured",
Reason: "",
} {
t.Run(tt.name, func(t *testing.T) {
err := g.Post(context.Background(), tt.event)
assert.NoError(t, err)
})
}
err = g.Post(context.Background(), event)
assert.NoError(t, err)
}

View File

@ -19,73 +19,43 @@ package notifier
import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"github.com/google/go-github/v53/github"
"golang.org/x/oauth2"
"github.com/google/go-github/v64/github"
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/cache"
)
type GitHub struct {
Owner string
Repo string
ProviderUID string
Client *github.Client
Owner string
Repo string
CommitStatus string
Client *github.Client
}
func NewGitHub(providerUID string, addr string, token string, certPool *x509.CertPool) (*GitHub, error) {
if len(token) == 0 {
return nil, errors.New("github token cannot be empty")
func NewGitHub(commitStatus string, addr string, token string, tlsConfig *tls.Config,
proxyURL string, providerName string, providerNamespace string, secretData map[string][]byte,
tokenCache *cache.TokenCache) (*GitHub, error) {
// this should never happen
if commitStatus == "" {
return nil, errors.New("commit status cannot be empty")
}
host, id, err := parseGitAddress(addr)
repoInfo, err := getRepoInfoAndGithubClient(addr, token, tlsConfig,
proxyURL, providerName, providerNamespace, secretData, tokenCache)
if err != nil {
return nil, err
}
baseUrl, err := url.Parse(host)
if err != nil {
return nil, err
}
comp := strings.Split(id, "/")
if len(comp) != 2 {
return nil, fmt.Errorf("invalid repository id %q", id)
}
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
tc := oauth2.NewClient(context.Background(), ts)
client := github.NewClient(tc)
if baseUrl.Host != "github.com" {
if certPool != nil {
tr := &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certPool,
},
}
hc := &http.Client{Transport: tr}
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, hc)
tc = oauth2.NewClient(ctx, ts)
}
client, err = github.NewEnterpriseClient(host, host, tc)
if err != nil {
return nil, fmt.Errorf("could not create enterprise GitHub client: %v", err)
}
}
return &GitHub{
Owner: comp[0],
Repo: comp[1],
ProviderUID: providerUID,
Client: client,
Owner: repoInfo.owner,
Repo: repoInfo.repo,
CommitStatus: commitStatus,
Client: repoInfo.client,
}, nil
}
@ -96,7 +66,7 @@ func (g *GitHub) Post(ctx context.Context, event eventv1.Event) error {
return nil
}
revString, ok := event.Metadata[eventv1.MetaRevisionKey]
revString, ok := event.GetRevision()
if !ok {
return errors.New("missing revision metadata")
}
@ -110,7 +80,7 @@ func (g *GitHub) Post(ctx context.Context, event eventv1.Event) error {
}
_, desc := formatNameAndDescription(event)
id := generateCommitStatusID(g.ProviderUID, event)
id := g.CommitStatus
status := &github.RepoStatus{
State: &state,
Context: &id,

Some files were not shown because too many files have changed in this diff Show More