Un-fork operator-cloud: bring cloud differences behind a runtime Cloud gate - #4980
Conversation
| }) | ||
| } | ||
|
|
||
| if cloudOpts.Cloud { |
There was a problem hiding this comment.
Is this real? I'm a bit surprised this would be needed for CC and not for everyone else who uses the operator 🤷
There was a problem hiding this comment.
It probably wouldn't hurt to use it for everybody.
There was a problem hiding this comment.
I think it would potentially slow down rolling update?
There was a problem hiding this comment.
Ohh right, ya it would. It seems like there's a better solution to this issue, how long is the apiserver taking that we need this sort of duration?
There was a problem hiding this comment.
how long is the apiserver taking that we need this sort of duration?
Indeed, that's basically my question. This smells a lot like code that was added to fix a symptom rather than a root cause and that might not be needed any more.
There was a problem hiding this comment.
@Brian-McM bumping this one - did you get a chance to dig into the apiserver latency numbers? Still want to make sure these longer durations aren't just papering over a slow apiserver rather than fixing the actual cause.
There was a problem hiding this comment.
Just looking into this now, this was something added a long time ago so might not be relevant anymore, cc @tmjd.
There was a problem hiding this comment.
Chatted with @tmjd and I'm going to remove the hard coded override but put in flags to update these values in case we need to quickly override these again in cloud.
Sound good @caseydavenport ?
| KeyValidatorConfig: keyValidatorConfig, | ||
| KubernetesVersion: r.opts.KubernetesVersion, | ||
| ClusterDomain: r.opts.ClusterDomain, | ||
| Cloud: r.opts.Cloud, |
There was a problem hiding this comment.
I've already started doing this in other places - I'll handle it in my own refactoring but worth calling out that I'm moving to just having the ControllerOptions as a field on the controller instead of copying each var individually.
| var mcr render.ManagerCloudResources | ||
| if r.opts.Cloud { | ||
| var reconcileResult *reconcile.Result | ||
| bundleMaker, mcr, tenant, reconcileResult, err = r.handleCloudReconcile( |
There was a problem hiding this comment.
This is probably fine, but I think we probably only structure the code this way because it used to be a fork and we didn't want to interleave merge conflicts - we should probably unpack this as a follow on to clean it up instead of overwriting / recalculating what was done above.
There was a problem hiding this comment.
Oh I fully intend on doing that right now, this is the initial pass.
|
|
||
| // GetCloudConfig retrieves the config map containing the configuration values needed to set up communications with | ||
| // external Elasticsearch and Kibana, such as the externalESDomain and externalKibanaDomain. | ||
| func GetCloudConfig(ctx context.Context, cli client.Client) (*cloudconfig.CloudConfig, error) { |
There was a problem hiding this comment.
Does it make sense for this to be separate from the other utility functions in pkg/cloud/ ?
There was a problem hiding this comment.
@Brian-McM any thoughts here? Feels like it'd sit more naturally alongside the other helpers in pkg/cloud/.
There was a problem hiding this comment.
Might be splitting hairs here but this logic is pretty controller centric, while the pkg/cloud is used for initial setup.
…val, cloud release version fix Follow-up to review comments from @radTuti and @tmjd: - CI registry cred isolation (radTuti): each job now authenticates only to the registry it pushes to — quay login in the enterprise Build/Publish Release jobs, gcloud/GCR in the Build Cloud/Publish Cloud Release jobs — instead of both in the shared block prologue (push_images.yml, release.yml). - Remove dead cloud version/image machinery (tmjd): the operator does not deploy cc-rbac-api, and ComponentCloudRBACAPI / CloudImages / CloudRegistry were never consumed. Drop config/cloud_versions.yml, pkg/components/cloud.go, pkg/components/cloud_images.go, and the gen-versions-cloud target + CLOUD_VERSIONS. CalicoCloudImage() (used by kube-controllers) is unrelated and stays. - Reference TSLA-11650 for possible removal of CalicoCloudImage() (tmjd). - Fix the cloud tagged-release path (radTuti): the cloud image/version keeps a -cloud suffix (vX.Y.Z-cloud) but rides the enterprise git tag (vX.Y.Z), so the version no longer matches git describe. checkVersionMatchesGitVersion now strips -cloud before matching, and the release tool passes GIT_VERSION=VERSION for cloud so the Makefile's VERSION==GIT_VERSION guard passes and the binary reports the -cloud version. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…val, cloud release version fix Follow-up to review comments from @radTuti and @tmjd: - CI registry cred isolation (radTuti): each job now authenticates only to the registry it pushes to — quay login in the enterprise Build/Publish Release jobs, gcloud/GCR in the Build Cloud/Publish Cloud Release jobs — instead of both in the shared block prologue (push_images.yml, release.yml). - Remove dead cloud version/image machinery (tmjd): the operator does not deploy cc-rbac-api, and ComponentCloudRBACAPI / CloudImages / CloudRegistry were never consumed. Drop config/cloud_versions.yml, pkg/components/cloud.go, pkg/components/cloud_images.go, and the gen-versions-cloud target + CLOUD_VERSIONS. CalicoCloudImage() (used by kube-controllers) is unrelated and stays. - Reference TSLA-11650 for possible removal of CalicoCloudImage() (tmjd). - Fix the cloud tagged-release path (radTuti): the cloud image/version keeps a -cloud suffix (vX.Y.Z-cloud) but rides the enterprise git tag (vX.Y.Z), so the version no longer matches git describe. checkVersionMatchesGitVersion now strips -cloud before matching, and the release tool passes GIT_VERSION=VERSION for cloud so the Makefile's VERSION==GIT_VERSION guard passes and the binary reports the -cloud version. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
a262857 to
d10356a
Compare
… is known Resolves the cloud trusted-bundle TODO (PR tigera#4980 review, @caseydavenport). Previously the bundle was created early, then re-created for Calico Cloud management clusters once the authenticationCR was available. Since the bundle isn't consumed until later in Reconcile, move its creation down past the authenticationCR fetch and build it once — standard, multi-tenant, or the Calico Cloud system-root variant (for external OIDC verification) — dropping the re-creation. The auth-gating order is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| }) | ||
| } | ||
|
|
||
| if cloudOpts.Cloud { |
There was a problem hiding this comment.
@Brian-McM bumping this one - did you get a chance to dig into the apiserver latency numbers? Still want to make sure these longer durations aren't just papering over a slow apiserver rather than fixing the actual cause.
|
|
||
| // GetCloudConfig retrieves the config map containing the configuration values needed to set up communications with | ||
| // external Elasticsearch and Kibana, such as the externalESDomain and externalKibanaDomain. | ||
| func GetCloudConfig(ctx context.Context, cli client.Client) (*cloudconfig.CloudConfig, error) { |
There was a problem hiding this comment.
@Brian-McM any thoughts here? Feels like it'd sit more naturally alongside the other helpers in pkg/cloud/.
…na global, consolidate cloud startup
Review follow-ups:
- kibana: thread the Calico Cloud Kibana config overrides through Configuration
(CloudConfigOverrides) instead of a package global. The map is now a per-reconcile
local, so a deleted cloud-kibana-config ConfigMap no longer leaves stale overrides.
- logstorage dashboards/linseed: document that the `!cloud` clause is load-bearing —
for any non-cloud install it collapses to the original pre-cloud check, so EE
behavior is unchanged.
- main.go: replace the cloud-only 4x leader-election overrides with
--leader-election-{lease-duration,renew-deadline,retry-period} flags defaulting to
the controller-runtime (and EE) values. No separate cloud code path.
Dismantle pkg/cloud:
- Fold the build-variant stamp (buildVariant/isCloudBuild) and cloud startup into
cmd (package main); delete the pkg/cloud package and the dead ToPtr helper.
- Cloud startup now reads the operator bootstrap ConfigMap (ELASTIC_EXTERNAL /
ELASTIC_MIGRATION) via discovery and reuses utils.MonitorConfigMap, removing the
duplicate cloud-operator-config load and bespoke config watch. Use %w when wrapping
the startup errors.
- Makefile: CLOUD_LDFLAGS becomes `-X main.buildVariant=cloud` (the linker addresses
package main as "main", not by import path).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
caseydavenport
left a comment
There was a problem hiding this comment.
Just a few more thoughts / questions. Probably the last round though!
| // buildVariant is injected at build time via -ldflags "-X main.buildVariant=cloud" when building the | ||
| // Calico Cloud operator image (see CLOUD_LDFLAGS in the Makefile). It is empty for the regular | ||
| // Calico/Calico Enterprise image. Baking it into the binary means cloud mode is immutable: it cannot | ||
| // be disabled by editing the operator Deployment's environment. |
There was a problem hiding this comment.
Baking it into the binary means cloud mode is immutable: it cannot be disabled by editing the operator Deployment's environment.
Just a bit of a pressure test... why is this important?
There was a problem hiding this comment.
I don't want us to somehow have some weird backdoor of setting a operator cloud image into EE mode.
There was a problem hiding this comment.
I'm generally against having two builds of this code if we can avoid it.
I don't see there being a huge risk of someone having a backdoor, and if they do it's not actually a problem? It just won't work, right?
There was a problem hiding this comment.
The risk is that a cloud environment gets turned into an ee environment and cloud production cluster is hosed, even worse if it's a multi tenant one.
I don't like uneccessarily having multiple builds, but I'll stand by it being worth it in this case.
There was a problem hiding this comment.
Yeah, I just don't see why that's a risk worth propagating into our build + code, rather than just having CI that catches misconfigurations before merging manifest changes. A CLI argument would be pretty hard to mess up, especially if we had some pre-flight checks that caught a misconfiguration and prevented the operator from taking action.
There was a problem hiding this comment.
I sort of think the opposite, why push it to testing when you can just make it not possible. I'm not sure this is huge burden having two builds here tbh, but I'd just like to roll with this for my peace of mind and if it is for some reason actual issue then maybe we can just revisit then.
…als, trim comments
Restructure the external-ES tenant-source conditional in the dashboards and
linseed controllers to `if multiTenant { } else if cloud { }`. EE single-tenant
external ES does not exist, so the previously-handled third state is
unreachable; this drops the load-bearing explainer comment.
Trim verbose comments across cmd/main.go, the release setup package, and the
kibana/elastic logstorage code.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…d gate
Migrate the tigera/operator-cloud fork's differences into tigera/operator,
gated by the CALICO_CLOUD env var so enterprise/OSS behavior is unchanged
unless cloud mode is active.
- Foundation: pkg/cloud (CALICO_CLOUD gate, tolerant Load), render/common/cloudconfig,
controller/utils/cloudconfig, options.{Cloud,ESMigration}, cmd/main wiring.
- Shared helpers: key_validator cloud tenancy claim (self-gating), auth_cloud,
GetKeyValidatorConfig addTenancyClaim param, meta.DefaultCertificateDuration,
elasticsearch.AddTenantId.
- Per-component cloud paths (all gated): manager, logstorage (linseed/esgateway/
kibana/elastic/external-elastic/dashboards/kubecontrollers + ES ILM), compliance,
fluentd, tiers, intrusiondetection, policyrecommendation, monitor, packetcapture.
- apiserver + kube-controllers RBAC divergences gated behind Cloud.
- Intrusion detection: clean up orphaned Image Assurance resources.
- Cloud version-gen wiring: -cloud-versions flag, cloud.go.tpl, gen-versions-cloud
target, generated pkg/components/cloud.go.
- Cloud-path tests for manager/fluentd/kibana render and elastic/compliance/manager
controllers. Plan + status in docs/cloud-unfork-migration-plan.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the Calico Cloud release tooling, gated by the `cloud` build tag so the enterprise/OSS release tool is unaffected. - hack/release/cloud.go + internal/versions/cloud.go (//go:build cloud): init() wraps the OSS release commands (GCR/tesla image defaults, cloud-vX.Y.Z version format, hashrelease support, CI output files). checks.go/flags.go are NOT changed (cloud.go reassigns isValidReleaseVersion at init). - Makefile: `make release-cloud` / `release-publish-cloud` build with -tags cloud; a gated `ifeq ($(VARIANT),cloud)` block switches image identity to gcr.io/tigera-tesla/operator-cloud (amd64) without affecting enterprise builds. - hack/release/CLOUD.md documents the flow. Verified: untagged release tool builds + tests unchanged; tagged build + cloud test pass; Makefile VARIANT gating switches vars correctly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bring the Calico Cloud CI from the fork, adapted to tigera/operator and made to coexist with the enterprise CI. Semaphore (additive — enterprise pipelines untouched): - push_images_cloud.yml / release_cloud.yml: new pipelines that push the operator-cloud image to GCR via VARIANT=cloud (amd64 only); release triggers on cloud-v* tags. - semaphore.yml: two additive promotions (Push Cloud Images, Release Cloud); the enterprise promotions and multi-arch build are unchanged. - Makefile: release-tag-cloud target (uses the -tags cloud release tool). ArgoCI (.argoci/, new to this repo): build-hashrelease + update-cluster-with- hashrelease workflows and hack/hashrelease/*.py cluster updaters. Source-repo references retargeted operator-cloud -> tigera/operator (clone URL/dir, labels, branch param, build command -> make release-cloud release-publish-cloud); the published image name (operator-cloud), GCR project, secrets, Slack and cluster infra are kept as-is. Fork-maintenance machinery (fork-sync crons/templates, update_fork.sh, approve_check.yml) is intentionally dropped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cloud-only changes that landed on operator-cloud after the initial un-fork snapshot (or were missed by it), all behind the runtime Cloud gate so enterprise/OSS behavior is unchanged: - TSLA-11182: disable ui-apis Kibana login for all Calico Cloud (not just multi-tenant) via a cloud-gated decorateCloudUIAPIsContainer decorator. - TSLA-11580 (tigera#1111): run cloud kube-controllers from the tesla-tagged calico image (components.CalicoCloudImage); gated on Config.Cloud, plumbed into both the calico- and es-kube-controllers render configs. - TSLA-11553 (tigera#1103): pin the policy-activity index base name only for single-tenant external-ES (Tenant.SingleTenant()), not all tenants. - TSLA-11547: point enterprise images at the cloud registry in the build-hashrelease ArgoCI template so hashrelease images resolve. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Casey flagged that ElasticExternal (cloud) and discovery.UseExternalElastic (enterprise bootstrap configmap) are the same knob read from two configmaps, OR'd together in main.go. Collapse to a single source: the operator now reads external-ES only from operator-bootstrap-config via discovery.UseExternalElastic. Calico Cloud provisions ELASTIC_EXTERNAL into operator-bootstrap-config too (in addition to cloud-operator-config, which cloud.Load still reads for its own startup verify), so cloud and enterprise share one downstream gate. Requires the cc-mgmt-config helm chart to populate operator-bootstrap-config (separate change). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
setupLog.Info takes key/value pairs, not printf verbs; passing a lone err
after a "%v" message string is an odd argument count that trips zap's dpanic
("odd number of arguments passed as key-value pairs for logging"). Use a
proper "error", err pair.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Master replaced fluentd with fluent-bit, which dropped the DISABLE_ES_*_LOG
env toggles the un-fork's cloud path used (they died with the fluentd ES
output; fluent-bit ships to Linseed). Reimplement the same cloud/enterprise
split natively: a Cloud gate omits the Linseed outputs for the log types cloud
does not store — DNS, EE/kube audit and BGP always, and flow logs unless this
is a multi-tenant management cluster (matching the old
DISABLE_ES_{DNS,AUDIT_EE,AUDIT_KUBE,BGP,FLOW}_LOG behavior). Non-cluster host
variants follow their base tag. Enterprise behavior is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…handling Make the Calico Cloud variant easy to tell apart from enterprise and collapse the cloud release/CI machinery down to the minimal set of runtime-resolved differences. Binary / version markers: - Build the cloud operator binary as operator-cloud-<arch> via a new BINARY_NAME make var (VARIANT=cloud); Dockerfile copies it by name. - --version (and the startup log) print "Variant: Calico Cloud" for a cloud build, as a separate line so hack/release parsing is unaffected. Release tool: - Replace hack/release/cloud.go (and the -tags-style overrides) with a single internal/setup package that resolves the variant-dependent defaults (registry, image, release-version validator, github-release default) once at init, keyed off VARIANT. This runs before the main package's flag vars initialize, so flag defaults capture the correct cloud/enterprise values with no fix-up. - Cloud releases use the operator's own version scheme with a -cloud suffix (vX.Y.Z-cloud) instead of a bespoke format. - Drop the Argo hashrelease flow and its pinned-components/cloud-registry machinery (build-hashrelease.yaml, internal/versions/cloud.go). - Remove CLOUD.md; document the variant briefly in README instead. Semaphore CI: - Fold cloud build/publish into the enterprise pipelines as parallel jobs (Build Cloud in push_images.yml, Publish Cloud Release in release.yml) off the same branches/tags, differing only by VARIANT=cloud and the -cloud image/version. GCR auth is added to the shared block prologues (required for the operator-cloud GCR push). - Delete the separate release_cloud.yml / push_images_cloud.yml pipelines and their promotions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…val, cloud release version fix Follow-up to review comments from @radTuti and @tmjd: - CI registry cred isolation (radTuti): each job now authenticates only to the registry it pushes to — quay login in the enterprise Build/Publish Release jobs, gcloud/GCR in the Build Cloud/Publish Cloud Release jobs — instead of both in the shared block prologue (push_images.yml, release.yml). - Remove dead cloud version/image machinery (tmjd): the operator does not deploy cc-rbac-api, and ComponentCloudRBACAPI / CloudImages / CloudRegistry were never consumed. Drop config/cloud_versions.yml, pkg/components/cloud.go, pkg/components/cloud_images.go, and the gen-versions-cloud target + CLOUD_VERSIONS. CalicoCloudImage() (used by kube-controllers) is unrelated and stays. - Reference TSLA-11650 for possible removal of CalicoCloudImage() (tmjd). - Fix the cloud tagged-release path (radTuti): the cloud image/version keeps a -cloud suffix (vX.Y.Z-cloud) but rides the enterprise git tag (vX.Y.Z), so the version no longer matches git describe. checkVersionMatchesGitVersion now strips -cloud before matching, and the release tool passes GIT_VERSION=VERSION for cloud so the Makefile's VERSION==GIT_VERSION guard passes and the binary reports the -cloud version. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… is known Resolves the cloud trusted-bundle TODO (PR tigera#4980 review, @caseydavenport). Previously the bundle was created early, then re-created for Calico Cloud management clusters once the authenticationCR was available. Since the bundle isn't consumed until later in Reconcile, move its creation down past the authenticationCR fetch and build it once — standard, multi-tenant, or the Calico Cloud system-root variant (for external OIDC verification) — dropping the re-creation. The auth-gating order is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…na global, consolidate cloud startup
Review follow-ups:
- kibana: thread the Calico Cloud Kibana config overrides through Configuration
(CloudConfigOverrides) instead of a package global. The map is now a per-reconcile
local, so a deleted cloud-kibana-config ConfigMap no longer leaves stale overrides.
- logstorage dashboards/linseed: document that the `!cloud` clause is load-bearing —
for any non-cloud install it collapses to the original pre-cloud check, so EE
behavior is unchanged.
- main.go: replace the cloud-only 4x leader-election overrides with
--leader-election-{lease-duration,renew-deadline,retry-period} flags defaulting to
the controller-runtime (and EE) values. No separate cloud code path.
Dismantle pkg/cloud:
- Fold the build-variant stamp (buildVariant/isCloudBuild) and cloud startup into
cmd (package main); delete the pkg/cloud package and the dead ToPtr helper.
- Cloud startup now reads the operator bootstrap ConfigMap (ELASTIC_EXTERNAL /
ELASTIC_MIGRATION) via discovery and reuses utils.MonitorConfigMap, removing the
duplicate cloud-operator-config load and bespoke config watch. Use %w when wrapping
the startup errors.
- Makefile: CLOUD_LDFLAGS becomes `-X main.buildVariant=cloud` (the linker addresses
package main as "main", not by import path).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sReleaseVersionFormat Consolidates release-version format checks onto setup.IsValidReleaseVersion and removes the now-redundant local isReleaseVersionFormat helper (radTuti review comment on hack/release/utils.go). In the default (non-cloud) variant the setup validator uses the identical ^vX.Y.Z regex, so behavior is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Calico version is validated on the cloud path (the build command sets CALICO_VERSION with VARIANT=cloud), but setup.IsValidReleaseVersion is variant-aware and requires a -cloud suffix in cloud mode — which the Calico version never carries. Add setup.IsValidCalicoReleaseVersion (always plain vX.Y.Z) and use it for the Calico version flag and release-prep, leaving the variant-aware validator for the operator version. Also drop the now-unused releaseFormat const from utils.go (superseded by setup's formats). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…als, trim comments
Restructure the external-ES tenant-source conditional in the dashboards and
linseed controllers to `if multiTenant { } else if cloud { }`. EE single-tenant
external ES does not exist, so the previously-handled third state is
unreachable; this drops the load-bearing explainer comment.
Trim verbose comments across cmd/main.go, the release setup package, and the
kibana/elastic logstorage code.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
f2f0b40 to
4030b58
Compare
| // Calico Cloud additionally grants access to runtime logs. | ||
| resourceNames := []string{"flows", "audit*", "l7", "events", "dns", "waf", "kibana_login", "recommendations"} | ||
| if c.cfg.Cloud { | ||
| resourceNames = append([]string{"runtime"}, resourceNames...) |
There was a problem hiding this comment.
Do we even need to include this anymore?
There was a problem hiding this comment.
ooof, I'm not sure, I would think not....
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Description
Type of change: new feature (Calico Cloud support / un-fork of
tigera/operator-cloud).This brings the differences carried by the long-lived
tigera/operator-cloudfork back intotigera/operator, so the fork can be retired. All cloud behavior is gated behind theCALICO_CLOUDenvironment variable (
cloud.EnableCloudEnvVar), set on the operator Deployment by the cloudinstaller. When the gate is off (every Calico / Calico Enterprise install), behavior is unchanged —
the cloud code paths are inert.
Why merge this: it removes the maintenance burden of a separate fork that had to be continually
re-synced with this repo, and makes Calico Cloud a first-class, gated mode of the upstream operator.
How it works:
pkg/cloudparsesCALICO_CLOUDat startup and returnsCloud=false(no-op) unless it is set,threading
options.ControllerOptions.Cloudto controllers.render.ManagerCloudResources)only when
opts.Cloudis true; render decorators are no-ops otherwise.config/cloud_versions.ymlintopkg/components/cloud.govia anew standalone
make gen-versions-cloudtarget (not part of the defaultgen-versionsaggregate, soenterprise generated output is byte-identical).
Components affected (all gated): manager, logstorage (linseed / esgateway / kibana / elastic /
external-elastic / dashboards / kube-controllers + ES ILM), api-server RBAC, compliance, fluentd, tiers,
intrusion-detection, policy-recommendation, monitor, packet-capture. Intrusion-detection additionally
cleans up orphaned Image Assurance resources.
Testing:
make build/go build ./pkg/... ./cmd/...succeed.esgateway / linseed render and elastic / compliance / manager controllers), each with cloud-on and
cloud-off (negative) cases confirming enterprise output is unchanged.
master; cloud version generation is idempotent.A full migration map and rationale is in
docs/cloud-unfork-migration-plan.md.Prerequisite context:
tigera/operator-cloud#1059(removal of dead Image Assurance / runtime security)landed in the fork first.
Release Note
For PR author
make gen-files(noapi/v1/ CRD changes in this PR)make gen-versions(make gen-versions-cloud→pkg/components/cloud.go)For PR reviewers
A note for code reviewers - all pull requests must have the following:
kind/bugif this is a bugfix.kind/enhancementif this is a a new feature.enterpriseif this PR applies to Calico Enterprise only.🤖 Generated with Claude Code