From 32d0c2177d5cdb678516f7ed6cc86dc001036715 Mon Sep 17 00:00:00 2001 From: caseydavenport <1944093+caseydavenport@users.noreply.github.com> Date: Mon, 8 Jun 2026 22:38:10 +0000 Subject: [PATCH] Automatic API update from tigera/calico-private master --- config/.gitattributes | 1 + ...er.projectcalico.org_globalwafplugins.yaml | 182 ++++ ...r.projectcalico.org_globalwafpolicies.yaml | 253 +++++ ...alico.org_globalwafvalidationpolicies.yaml | 306 ++++++ ...ionlayer.projectcalico.org_wafplugins.yaml | 236 +++++ ...onlayer.projectcalico.org_wafpolicies.yaml | 375 ++++++++ ...ojectcalico.org_wafvalidationpolicies.yaml | 227 +++++ .../projectcalico.org_alertexceptions.yaml | 2 + .../projectcalico.org_bgpconfigurations.yaml | 10 +- config/crd/projectcalico.org_bgppeers.yaml | 14 +- ...projectcalico.org_felixconfigurations.yaml | 48 + .../crd/projectcalico.org_globalalerts.yaml | 2 + .../crd/projectcalico.org_globalreports.yaml | 2 + config/crd/projectcalico.org_ippools.yaml | 4 +- ...ico.org_kubecontrollersconfigurations.yaml | 49 + config/crd/projectcalico.org_licensekeys.yaml | 8 +- .../projectcalico.org_managedclusters.yaml | 15 +- config/crd/projectcalico.org_networks.yaml | 247 +++++ .../crd/projectcalico.org_packetcaptures.yaml | 2 + ...ojectcalico.org_securityeventwebhooks.yaml | 2 + deps.txt | 34 +- go.mod | 86 +- go.sum | 68 +- hack/openapi-violations-known.list | 1 + lib.Makefile | 629 ++++++++----- metadata.mk | 41 +- pkg/.gitattributes | 1 + .../v3/doc.go | 22 + .../v3/groupversion_info.go | 58 ++ .../v3/types.go | 888 ++++++++++++++++++ .../v3/types_test.go | 122 +++ pkg/apis/projectcalico/v3/alertexception.go | 1 + pkg/apis/projectcalico/v3/bgpconfig.go | 10 +- pkg/apis/projectcalico/v3/bgppeer.go | 7 +- pkg/apis/projectcalico/v3/constants.go | 7 +- pkg/apis/projectcalico/v3/felixconfig.go | 37 + pkg/apis/projectcalico/v3/globalalert.go | 2 +- pkg/apis/projectcalico/v3/globalreport.go | 3 +- pkg/apis/projectcalico/v3/ippool.go | 5 +- .../projectcalico/v3/kubecontrollersconfig.go | 23 + .../v3/kubecontrollersconfig_test.go | 70 ++ pkg/apis/projectcalico/v3/licensekey.go | 7 +- pkg/apis/projectcalico/v3/managedcluster.go | 10 +- pkg/apis/projectcalico/v3/network.go | 192 ++++ pkg/apis/projectcalico/v3/packetcapture.go | 1 + pkg/apis/projectcalico/v3/register.go | 2 + .../projectcalico/v3/securityeventwebhook.go | 4 +- .../projectcalico/v3/zz_generated.deepcopy.go | 299 ++++++ .../v3/zz_generated.model_name.go | 60 ++ pkg/client/.gitattributes | 4 + .../internal/internal.go | 10 + .../v3/applicationlayercontrollerconfig.go | 32 + .../projectcalico/v3/bgppeerspec.go | 12 +- .../projectcalico/v3/controllersconfig.go | 24 + .../v3/felixconfigurationspec.go | 62 ++ .../projectcalico/v3/interfacematch.go | 30 + .../projectcalico/v3/licensekeystatus.go | 12 +- .../projectcalico/v3/network.go | 275 ++++++ .../projectcalico/v3/networkspec.go | 30 + .../projectcalico/v3/networkstatus.go | 37 + .../v3/rbacsynccontrollerconfig.go | 33 + .../projectcalico/v3/staticrouteaction.go | 30 + .../projectcalico/v3/vrfhostconfig.go | 80 ++ .../projectcalico/v3/vrfnetworkspec.go | 52 + .../projectcalico/v3/vrfrouting.go | 36 + .../projectcalico/v3/vrfstaticroute.go | 40 + .../applyconfiguration_generated/utils.go | 22 + .../projectcalico/v3/fake/fake_network.go | 35 + .../v3/fake/fake_projectcalico_client.go | 4 + .../projectcalico/v3/generated_expansion.go | 2 + .../typed/projectcalico/v3/network.go | 60 ++ .../projectcalico/v3/projectcalico_client.go | 5 + .../externalversions/generic.go | 2 + .../projectcalico/v3/interface.go | 7 + .../projectcalico/v3/network.go | 87 ++ .../projectcalico/v3/expansion_generated.go | 4 + .../projectcalico/v3/network.go | 34 + pkg/openapi/generated.openapi.go | 483 +++++++++- 78 files changed, 5869 insertions(+), 350 deletions(-) create mode 100644 config/.gitattributes create mode 100644 config/crd/applicationlayer.projectcalico.org_globalwafplugins.yaml create mode 100644 config/crd/applicationlayer.projectcalico.org_globalwafpolicies.yaml create mode 100644 config/crd/applicationlayer.projectcalico.org_globalwafvalidationpolicies.yaml create mode 100644 config/crd/applicationlayer.projectcalico.org_wafplugins.yaml create mode 100644 config/crd/applicationlayer.projectcalico.org_wafpolicies.yaml create mode 100644 config/crd/applicationlayer.projectcalico.org_wafvalidationpolicies.yaml create mode 100644 config/crd/projectcalico.org_networks.yaml create mode 100644 pkg/.gitattributes create mode 100644 pkg/apis/applicationlayer.projectcalico.org/v3/doc.go create mode 100644 pkg/apis/applicationlayer.projectcalico.org/v3/groupversion_info.go create mode 100644 pkg/apis/applicationlayer.projectcalico.org/v3/types.go create mode 100644 pkg/apis/applicationlayer.projectcalico.org/v3/types_test.go create mode 100644 pkg/apis/projectcalico/v3/kubecontrollersconfig_test.go create mode 100644 pkg/apis/projectcalico/v3/network.go create mode 100644 pkg/client/.gitattributes create mode 100644 pkg/client/applyconfiguration_generated/projectcalico/v3/applicationlayercontrollerconfig.go create mode 100644 pkg/client/applyconfiguration_generated/projectcalico/v3/interfacematch.go create mode 100644 pkg/client/applyconfiguration_generated/projectcalico/v3/network.go create mode 100644 pkg/client/applyconfiguration_generated/projectcalico/v3/networkspec.go create mode 100644 pkg/client/applyconfiguration_generated/projectcalico/v3/networkstatus.go create mode 100644 pkg/client/applyconfiguration_generated/projectcalico/v3/rbacsynccontrollerconfig.go create mode 100644 pkg/client/applyconfiguration_generated/projectcalico/v3/staticrouteaction.go create mode 100644 pkg/client/applyconfiguration_generated/projectcalico/v3/vrfhostconfig.go create mode 100644 pkg/client/applyconfiguration_generated/projectcalico/v3/vrfnetworkspec.go create mode 100644 pkg/client/applyconfiguration_generated/projectcalico/v3/vrfrouting.go create mode 100644 pkg/client/applyconfiguration_generated/projectcalico/v3/vrfstaticroute.go create mode 100644 pkg/client/clientset_generated/clientset/typed/projectcalico/v3/fake/fake_network.go create mode 100644 pkg/client/clientset_generated/clientset/typed/projectcalico/v3/network.go create mode 100644 pkg/client/informers_generated/externalversions/projectcalico/v3/network.go create mode 100644 pkg/client/listers_generated/projectcalico/v3/network.go diff --git a/config/.gitattributes b/config/.gitattributes new file mode 100644 index 00000000..17d842d0 --- /dev/null +++ b/config/.gitattributes @@ -0,0 +1 @@ +crd/*.yaml linguist-generated=true diff --git a/config/crd/applicationlayer.projectcalico.org_globalwafplugins.yaml b/config/crd/applicationlayer.projectcalico.org_globalwafplugins.yaml new file mode 100644 index 00000000..66ace9e0 --- /dev/null +++ b/config/crd/applicationlayer.projectcalico.org_globalwafplugins.yaml @@ -0,0 +1,182 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: globalwafplugins.applicationlayer.projectcalico.org +spec: + group: applicationlayer.projectcalico.org + names: + kind: GlobalWAFPlugin + listKind: GlobalWAFPluginList + plural: globalwafplugins + shortNames: + - gwafplugin + singular: globalwafplugin + preserveUnknownFields: false + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.description + name: Description + type: string + - jsonPath: .status.ruleCount + name: Rules + type: integer + - jsonPath: .status.namespaceCount + name: Namespaces + type: integer + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v3 + schema: + openAPIV3Schema: + description: GlobalWAFPlugin is the Schema for cluster-wide custom WAF plugins + 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: GlobalWAFPluginSpec defines a cluster-wide custom WAF plugin + properties: + after: + description: |- + After contains raw SecAction/SecRule directives that run AFTER CRS rules. + Use for post-processing, logging, or cleanup. + Equivalent to CRS *-after.conf files. + maxLength: 65536 + type: string + before: + description: |- + Before contains raw SecAction/SecRule directives that run BEFORE CRS rules. + Use for pre-processing, initialization, or early blocking. + Equivalent to CRS *-before.conf files. + maxLength: 65536 + type: string + config: + description: |- + Config contains raw SecAction/SecRule directives for plugin configuration. + These run first and typically set tx.* variables. + Equivalent to CRS *-config.conf files. + maxLength: 65536 + type: string + description: + description: + Description is a human-readable description of what this + plugin does + maxLength: 1024 + type: string + rules: + description: |- + Rules contains the main SecAction/SecRule directives for this plugin. + These run alongside CRS rules. Ordering across plugins follows array + position in the consuming policy's spec.plugins[]. + maxLength: 65536 + type: string + type: object + x-kubernetes-validations: + - message: plugin must define at least one of config, before, rules, after + rule: + (has(self.config) && size(self.config) > 0) || (has(self.before) + && size(self.before) > 0) || (has(self.rules) && size(self.rules) + > 0) || (has(self.after) && size(self.after) > 0) + status: + description: |- + GlobalWAFPluginStatus defines the observed state. + + Conditions emitted by the controller: + - Accepted (DirectivesValid / InvalidDirectives) + properties: + conditions: + description: Conditions represent the latest available observations + 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 + namespaceCount: + description: |- + NamespaceCount is the number of namespaces with at least one WAFPolicy + referencing this plugin. Kept as a bounded aggregate (not a + ReferencedBy list) because a Global plugin can fan out to many + namespaces; a list would churn the status payload as policies come + and go. Different denominator from GlobalWAFPolicyStatus.NamespaceCount + (which counts namespaces using the policy itself). + type: integer + ruleCount: + description: + RuleCount is the number of SecRule directives in this + plugin + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/applicationlayer.projectcalico.org_globalwafpolicies.yaml b/config/crd/applicationlayer.projectcalico.org_globalwafpolicies.yaml new file mode 100644 index 00000000..966ca50f --- /dev/null +++ b/config/crd/applicationlayer.projectcalico.org_globalwafpolicies.yaml @@ -0,0 +1,253 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: globalwafpolicies.applicationlayer.projectcalico.org +spec: + group: applicationlayer.projectcalico.org + names: + kind: GlobalWAFPolicy + listKind: GlobalWAFPolicyList + plural: globalwafpolicies + shortNames: + - gwafp + singular: globalwafpolicy + preserveUnknownFields: false + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.defaultAction + name: Action + type: string + - jsonPath: .spec.coreRuleSet.state + name: CRS + type: string + - jsonPath: .spec.coreRuleSet.paranoiaLevel + name: Paranoia + type: integer + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v3 + schema: + openAPIV3Schema: + description: GlobalWAFPolicy is the Schema for cluster-wide WAF configuration + 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: GlobalWAFPolicySpec defines the desired state + properties: + coreRuleSet: + description: CoreRuleSet configures the OWASP Core Rule Set + properties: + enabled: + description: |- + Enabled is the deprecated boolean form. Read for backward compatibility + with v0.2.x CRs; new CRs should set State. If both fields are set, + State wins. + + Deprecated: use State. + type: boolean + paranoiaLevel: + default: 1 + description: ParanoiaLevel sets the CRS paranoia level (1-4) + maximum: 4 + minimum: 1 + type: integer + state: + default: Enabled + description: State enables or disables the OWASP CRS baseline. + enum: + - Enabled + - Disabled + type: string + type: object + defaultAction: + default: Detect + description: DefaultAction specifies what happens when a rule matches + enum: + - Detect + - Block + type: string + plugins: + description: |- + Plugins references GlobalWAFPlugins + These plugins are applied to all namespaces + items: + description: |- + PluginRef references a plugin by kind + name. Kind makes the + reference target explicit; without it, "is this naming a Global or a + namespace plugin?" had to be inferred from which policy's spec.plugins[] + the reference appeared in. The default is WAFPlugin (namespace-scoped) for + backward-compat with v0.2.x CRs that omit Kind. + + Note: in this release the resolved scope still follows the parent policy + (GlobalWAFPolicy.spec.plugins[] resolves as Global; WAFPolicy.spec.plugins[] + resolves as namespace-scoped). Cross-scope lookup (e.g. WAFPolicy + referencing a GlobalWAFPlugin) is a future addition; the Kind field + here is type-level disclosure of intent that the reconciler can validate + against in a later release. + properties: + kind: + default: WAFPlugin + description: |- + Kind selects between namespace-scoped (WAFPlugin) and cluster-scoped + (GlobalWAFPlugin) plugin types. + enum: + - WAFPlugin + - GlobalWAFPlugin + type: string + name: + description: Name is the name of the plugin resource. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 64 + type: array + type: object + status: + description: |- + GlobalWAFPolicyStatus defines the observed state. + + Conditions emitted by the controller: + - Licensed (LicenseValid / LicenseBlocked) + - Accepted (Accepted / Invalid / PluginNotFound) + - Ready (Ready / NotReady / ConflictingGlobalPolicy) + properties: + conditions: + description: Conditions represent the latest available observations + 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 + inheritedFromGlobal: + description: |- + InheritedFromGlobal is always nil for GlobalWAFPolicy. The field is + declared for symmetry with WAFPolicyStatus so generated clients (Go, + TS) can share a single attribution shape across scopes. + type: string + lastApplied: + description: LastApplied is the timestamp of the last successful application + format: date-time + type: string + namespaceCount: + description: |- + NamespaceCount is the number of namespaces in which a WAFPolicy targets + resources covered by this Global policy. Different denominator from + GlobalWAFPluginStatus.NamespaceCount (which counts namespaces where a + policy references the plugin). + type: integer + renderedConfigMapRefs: + description: |- + RenderedConfigMapRefs enumerates ConfigMaps the controller has emitted + from this GlobalWAFPolicy, one per namespace that consumed it. Capped + at 50 entries; see RenderedConfigMapRefsTruncated. When the cap is + exceeded, the surfaced entries are the lexically-first 50 namespace + names (sorted ascending by namespace), so the truncation is + deterministic across reconciles; use NamespaceCount to recover the + untruncated total. + items: + description: |- + RenderedConfigMapRef identifies the ConfigMap into which the controller + materialised the merged WAF rule set for a policy. CLI tools and status + consumers resolve this reference instead of reconstructing the name. + properties: + name: + maxLength: 253 + type: string + namespace: + maxLength: 253 + type: string + resourceVersion: + maxLength: 253 + type: string + required: + - name + - namespace + type: object + type: array + renderedConfigMapRefsTruncated: + description: |- + RenderedConfigMapRefsTruncated is true when the full set exceeded the + 50-entry status cap. Consumers should use NamespaceCount for totals. + type: boolean + type: object + type: object + x-kubernetes-validations: + - message: GlobalWAFPolicy is a singleton; the only permitted name is 'default' + rule: self.metadata.name == 'default' + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/applicationlayer.projectcalico.org_globalwafvalidationpolicies.yaml b/config/crd/applicationlayer.projectcalico.org_globalwafvalidationpolicies.yaml new file mode 100644 index 00000000..b2007a4b --- /dev/null +++ b/config/crd/applicationlayer.projectcalico.org_globalwafvalidationpolicies.yaml @@ -0,0 +1,306 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: globalwafvalidationpolicies.applicationlayer.projectcalico.org +spec: + group: applicationlayer.projectcalico.org + names: + kind: GlobalWAFValidationPolicy + listKind: GlobalWAFValidationPolicyList + plural: globalwafvalidationpolicies + shortNames: + - gwafvp + singular: globalwafvalidationpolicy + preserveUnknownFields: false + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.enforcementMode + name: Mode + type: string + - jsonPath: .status.passingCount + name: Passing + type: integer + - jsonPath: .status.violatingPolicies + name: Violating + type: integer + - jsonPath: .status.summary + name: Summary + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v3 + schema: + openAPIV3Schema: + description: |- + GlobalWAFValidationPolicy defines cluster-wide validation rules that merged + WAF configurations must pass. Used by Cluster Operators to enforce security + requirements across all namespaces. + 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: + GlobalWAFValidationPolicySpec defines cluster-wide validation + rules + properties: + enforcementMode: + default: Audit + description: |- + EnforcementMode determines how validation failures are handled + - Audit: Log warnings but generate EnvoyExtensionPolicy anyway + - Enforce: Block EnvoyExtensionPolicy generation on critical failures + enum: + - Audit + - Enforce + type: string + namespaceSelector: + description: |- + NamespaceSelector limits which namespaces this validation policy applies to. + If empty, applies to all namespaces. + + Standard metav1.LabelSelector semantics: every namespace — including + `default` — is matched against the selector's labels, with no implicit + special-casing. Since k8s 1.21 every namespace carries an auto-applied + `kubernetes.io/metadata.name=` label, so the canonical way to + scope down to specific namespaces (including `default`) is a + matchExpressions on that label. + properties: + matchExpressions: + description: + matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: + key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + type: object + x-kubernetes-map-type: atomic + rules: + description: Rules defines the validation rules to apply + items: + description: + ValidationRule defines a single Rego-based validation + rule + properties: + message: + description: Message is displayed when validation fails + maxLength: 1024 + type: string + name: + description: Name is a unique identifier for this rule + maxLength: 63 + minLength: 1 + type: string + rego: + description: |- + Rego is a Rego module that decides violations against the merged WAF + configuration. The module must declare `package waf` and produce a + `violations` set; an empty set means the rule passed. Each violation + may be a plain string message, or an object carrying a `msg` string. + The `input` document available to the module: + - input.directives: []string - the final merged directive list + - input.config.action: string - effective action ("Detect" or "Block") + - input.config.crsState: string - CRS state ("Enabled" or "Disabled") + - input.config.paranoiaLevel: int - effective paranoia level (1-4) + - input.source.globalPolicy: string - name of GlobalWAFPolicy + - input.source.namespacePolicy: string - name of WAFPolicy (if any) + - input.source.globalPlugins: []string - names of global plugins applied + - input.source.namespacePlugins: []string - names of namespace plugins applied + maxLength: 16384 + minLength: 1 + type: string + severity: + default: warning + description: Severity determines the impact of this rule failing + enum: + - info + - warning + - critical + type: string + required: + - name + - rego + type: object + minItems: 1 + type: array + required: + - rules + type: object + status: + description: |- + GlobalWAFValidationPolicyStatus defines the observed state. + + Conditions emitted by the controller: + - Ready (Evaluated) + properties: + conditions: + description: Conditions represent the latest available observations + 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 + evaluatedCount: + description: EvaluatedCount is the number of WAF policies evaluated + type: integer + lastEvaluated: + description: LastEvaluated is the timestamp of the last evaluation + format: date-time + type: string + passingCount: + description: PassingCount is the number of policies passing all rules + type: integer + summary: + description: Summary provides a quick overview of validation state + maxLength: 1024 + type: string + violatingPolicies: + description: |- + ViolatingPolicies lists all WAF policies that failed validation. + Useful for COs to centrally see which namespaces need attention. + items: + description: + ViolatingPolicy identifies a WAF policy that failed + validation + properties: + action: + description: "Action taken: Audited or Rejected" + maxLength: 253 + type: string + failedRules: + description: FailedRules lists the rules that this policy violated + items: + type: string + type: array + name: + description: Name is the name of the WAFPolicy + maxLength: 253 + type: string + namespace: + description: Namespace is the namespace of the violating policy + maxLength: 253 + type: string + severity: + description: Severity is the highest severity of the failures + enum: + - info + - warning + - critical + type: string + required: + - name + - namespace + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/applicationlayer.projectcalico.org_wafplugins.yaml b/config/crd/applicationlayer.projectcalico.org_wafplugins.yaml new file mode 100644 index 00000000..d88e6646 --- /dev/null +++ b/config/crd/applicationlayer.projectcalico.org_wafplugins.yaml @@ -0,0 +1,236 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: wafplugins.applicationlayer.projectcalico.org +spec: + group: applicationlayer.projectcalico.org + names: + kind: WAFPlugin + listKind: WAFPluginList + plural: wafplugins + shortNames: + - wafplugin + singular: wafplugin + preserveUnknownFields: false + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.description + name: Description + type: string + - jsonPath: .status.ruleCount + name: Rules + type: integer + - jsonPath: .status.referencedByCount + name: Refs + type: integer + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v3 + schema: + openAPIV3Schema: + description: WAFPlugin is the Schema for namespace-scoped custom WAF plugins + 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: + WAFPluginSpec defines a custom WAF plugin with CRS 4-style + structure + properties: + after: + description: |- + After contains raw SecAction/SecRule directives that run AFTER CRS rules. + Use for post-processing, logging, or cleanup. + Equivalent to CRS *-after.conf files. + maxLength: 65536 + type: string + before: + description: |- + Before contains raw SecAction/SecRule directives that run BEFORE CRS rules. + Use for pre-processing, initialization, or early blocking. + Equivalent to CRS *-before.conf files. + maxLength: 65536 + type: string + config: + description: |- + Config contains raw SecAction/SecRule directives for plugin configuration. + These run first and typically set tx.* variables. + Equivalent to CRS *-config.conf files. + maxLength: 65536 + type: string + description: + description: + Description is a human-readable description of what this + plugin does + maxLength: 1024 + type: string + rules: + description: |- + Rules contains the main SecAction/SecRule directives for this plugin. + These run alongside CRS rules. Ordering across plugins follows array + position in the consuming policy's spec.plugins[]. + maxLength: 65536 + type: string + type: object + x-kubernetes-validations: + - message: plugin must define at least one of config, before, rules, after + rule: + (has(self.config) && size(self.config) > 0) || (has(self.before) + && size(self.before) > 0) || (has(self.rules) && size(self.rules) + > 0) || (has(self.after) && size(self.after) > 0) + status: + description: |- + WAFPluginStatus defines the observed state. + + Conditions emitted by the controller: + - Accepted (DirectivesValid / InvalidDirectives) + properties: + conditions: + description: Conditions represent the latest available observations + 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 + referencedBy: + description: |- + ReferencedBy enumerates the policies that name this plugin in their + spec.plugins[]. Sorted: namespace asc, name asc, kind asc. Updated + every reconcile so client-side filtering is unnecessary. Capped at + 50 entries (matching RenderedConfigMapRefs on GlobalWAFPolicy) so a + runaway WAFPolicy population can't blow up the status payload; when + the cap is hit ReferencedByTruncated is set and the scalar + ReferencedByCount above remains authoritative for "how many + actually reference me". + items: + description: |- + PolicyRef identifies a policy that references a plugin. Used by plugin + status.referencedBy to give kubectl-readable reverse-index entries + without packing identifiers into a single string. + + Current scope-binding (this release): the plugin reconciler resolves + references from the parent policy's scope — WAFPolicy.spec.plugins[] + resolves namespace-scoped, GlobalWAFPolicy.spec.plugins[] resolves + cluster-scoped. Cross-scope lookup is a future addition; the Kind field + below is type-level disclosure of intent for a later release. + properties: + kind: + description: Kind identifies the referencing policy kind. + enum: + - WAFPolicy + - GlobalWAFPolicy + type: string + name: + description: Name is the name of the referencing policy. + maxLength: 253 + type: string + namespace: + description: |- + Namespace is the namespace of the referencing policy. Unset for + cluster-scoped GlobalWAFPolicy entries (pointer so unset is + distinguishable from explicit empty, per the optional-fields-are- + pointers convention). + maxLength: 253 + type: string + required: + - kind + - name + type: object + maxItems: 50 + type: array + referencedByCount: + description: |- + ReferencedByCount is the total number of policies referencing this + plugin — always the true population size, never bounded by the + 50-entry list cap on ReferencedBy. Backs the `Refs` printcolumn so + `kubectl get wafplugin` shows the real fan-in even when ReferencedBy + is truncated. + type: integer + referencedByTruncated: + description: |- + ReferencedByTruncated is true when the consuming-policy set exceeded + the 50-entry cap on ReferencedBy. Consumers should fall back to a + label-selector list query rather than relying on ReferencedBy alone; + ReferencedByCount remains accurate regardless. + type: boolean + ruleCount: + description: + RuleCount is the number of SecRule directives in this + plugin + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/applicationlayer.projectcalico.org_wafpolicies.yaml b/config/crd/applicationlayer.projectcalico.org_wafpolicies.yaml new file mode 100644 index 00000000..8b476229 --- /dev/null +++ b/config/crd/applicationlayer.projectcalico.org_wafpolicies.yaml @@ -0,0 +1,375 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: wafpolicies.applicationlayer.projectcalico.org +spec: + group: applicationlayer.projectcalico.org + names: + kind: WAFPolicy + listKind: WAFPolicyList + plural: wafpolicies + shortNames: + - wafp + singular: wafpolicy + preserveUnknownFields: false + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.action + name: Action + type: string + - jsonPath: .status.pluginCount + name: Plugins + type: integer + - jsonPath: .status.validation.status + name: Validation + type: string + - jsonPath: .status.validation.securityPosture + name: Posture + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v3 + schema: + openAPIV3Schema: + description: WAFPolicy is the Schema for namespace-scoped WAF configuration + 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: WAFPolicySpec defines the desired state + properties: + action: + description: |- + Action overrides the global default action for this namespace. + Nil means inherit from GlobalWAFPolicy; an explicit value overrides + the global default. Subject to validation policy enforcement. + enum: + - Detect + - Block + type: string + coreRuleSet: + description: |- + CoreRuleSet configures the OWASP Core Rule Set for this namespace + If not specified, inherits from GlobalWAFPolicy + properties: + enabled: + description: |- + Enabled is the deprecated boolean form. Read for backward compatibility + with v0.2.x CRs; new CRs should set State. If both fields are set, + State wins. + + Deprecated: use State. + type: boolean + paranoiaLevel: + default: 1 + description: ParanoiaLevel sets the CRS paranoia level (1-4) + maximum: 4 + minimum: 1 + type: integer + state: + default: Enabled + description: State enables or disables the OWASP CRS baseline. + enum: + - Enabled + - Disabled + type: string + type: object + plugins: + description: Plugins references WAFPlugins in this namespace + items: + description: |- + PluginRef references a plugin by kind + name. Kind makes the + reference target explicit; without it, "is this naming a Global or a + namespace plugin?" had to be inferred from which policy's spec.plugins[] + the reference appeared in. The default is WAFPlugin (namespace-scoped) for + backward-compat with v0.2.x CRs that omit Kind. + + Note: in this release the resolved scope still follows the parent policy + (GlobalWAFPolicy.spec.plugins[] resolves as Global; WAFPolicy.spec.plugins[] + resolves as namespace-scoped). Cross-scope lookup (e.g. WAFPolicy + referencing a GlobalWAFPlugin) is a future addition; the Kind field + here is type-level disclosure of intent that the reconciler can validate + against in a later release. + properties: + kind: + default: WAFPlugin + description: |- + Kind selects between namespace-scoped (WAFPlugin) and cluster-scoped + (GlobalWAFPlugin) plugin types. + enum: + - WAFPlugin + - GlobalWAFPlugin + type: string + name: + description: Name is the name of the plugin resource. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 64 + type: array + targetRefs: + description: + TargetRefs specifies Gateway API references (Gateway, + HTTPRoute) + items: + description: PolicyTargetReference identifies a Gateway API resource + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the target resource + maxLength: 253 + type: string + kind: + description: Kind is the kind of the target resource + enum: + - Gateway + - HTTPRoute + maxLength: 253 + type: string + name: + description: Name is the name of the target resource + maxLength: 253 + type: string + sectionName: + description: |- + SectionName scopes the WAF to a single named section within the target + (GEP-713): an HTTPRoute rule name (spec.rules[].name) or a Gateway listener + name (spec.listeners[].name). When unset, the policy attaches to the entire + target. The named rule/listener must exist, or the policy reports + Programmed=False/TargetNotFound. A rule-scoped policy takes precedence over + a whole-route one for that rule (Envoy Gateway GEP-713 precedence). See + designs#25 §01. + maxLength: 253 + type: string + required: + - kind + - name + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - targetRefs + type: object + x-kubernetes-validations: + - message: only group gateway.networking.k8s.io is supported for targetRefs + rule: + "!has(self.targetRefs) || self.targetRefs.all(ref, ref.group == + 'gateway.networking.k8s.io')" + status: + description: |- + WAFPolicyStatus defines the observed state. + + Conditions emitted by the controller: + - Licensed (LicenseValid / LicenseInGracePeriod / LicenseExpired / + LicenseInvalid / LicenseBlocked) + - Accepted (Accepted / Invalid / Conflicted / PluginNotFound / + ReplicaUnmanaged / ValidationFailed) + - Programmed (ConfigurationApplied / WASMUnavailable / CheckerError / + NotAttempted) + - Ready (Ready / NotReady) + properties: + conditions: + description: Conditions represent the latest available observations + 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 + inheritedFromGlobal: + description: |- + InheritedFromGlobal names the GlobalWAFPolicy whose plugin merge + contributed an inherited error (e.g. an Invalid reason on the Accepted + condition) to this policy. Nil when the failure is self-authored or + no failure is present. UI consumers use this to render a "Inherited + from GlobalWAFPolicy/" attribution badge that deep-links to the + offending Global resource. + type: string + lastApplied: + description: LastApplied is the timestamp of the last successful application + format: date-time + type: string + pluginCount: + description: PluginCount is the number of plugins applied + type: integer + renderedConfigMapRef: + description: |- + RenderedConfigMapRef points to the ConfigMap the controller emitted + for this namespace. Unset until the first successful reconcile. + properties: + name: + maxLength: 253 + type: string + namespace: + maxLength: 253 + type: string + resourceVersion: + maxLength: 253 + type: string + required: + - name + - namespace + type: object + validation: + description: |- + Validation contains the results of validation policy evaluation. + Shows whether the policy passed, was audited (warnings logged), or rejected. + properties: + failures: + description: + Failures contains details about failed validation + rules + items: + description: + ValidationFailure describes a single validation + rule failure + properties: + message: + description: Message explains why validation failed + maxLength: 1024 + type: string + policyKind: + description: PolicyKind is Global or Namespace-scoped + enum: + - GlobalWAFValidationPolicy + - WAFValidationPolicy + maxLength: 253 + type: string + policyName: + description: + PolicyName is the name of the validation policy + that failed + maxLength: 253 + type: string + rule: + description: + Rule is the name of the specific rule that + failed + maxLength: 63 + type: string + severity: + description: Severity of the failure + enum: + - info + - warning + - critical + type: string + required: + - policyKind + - policyName + - rule + - severity + type: object + type: array + lastEvaluated: + description: LastEvaluated is when validation was last performed + format: date-time + type: string + securityPosture: + description: + SecurityPosture is the security posture based on + all validation results + enum: + - Compliant + - Warning + - Degraded + - Critical + type: string + status: + description: |- + Status is the overall validation outcome. Denormalized from the + Validated x Programmed conditions so the `kubectl get wafpolicy` + printcolumn can show a single readable scalar; CRD printcolumns can + only read one JSONPath, not compute from two conditions. The + conditions are authoritative — if this field and the conditions ever + diverge in a future change, the conditions win and this field is the + rendered projection. Valid = Validated/True + Programmed/True; + Audited = Validated/False + Programmed/True (Audit mode); + Rejected = Validated/False + Programmed/False (Enforce mode blocked). + enum: + - Valid + - Audited + - Rejected + type: string + required: + - status + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/applicationlayer.projectcalico.org_wafvalidationpolicies.yaml b/config/crd/applicationlayer.projectcalico.org_wafvalidationpolicies.yaml new file mode 100644 index 00000000..d1f2ec91 --- /dev/null +++ b/config/crd/applicationlayer.projectcalico.org_wafvalidationpolicies.yaml @@ -0,0 +1,227 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: wafvalidationpolicies.applicationlayer.projectcalico.org +spec: + group: applicationlayer.projectcalico.org + names: + kind: WAFValidationPolicy + listKind: WAFValidationPolicyList + plural: wafvalidationpolicies + shortNames: + - wafvp + singular: wafvalidationpolicy + preserveUnknownFields: false + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.securityPosture + name: Posture + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v3 + schema: + openAPIV3Schema: + description: |- + WAFValidationPolicy defines namespace-scoped validation rules for Application + Operators to self-validate their WAF configuration. Useful for catching + mistakes like accidentally removing required plugins. + 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: |- + WAFValidationPolicySpec defines namespace validation rules. + + Namespace WAFValidationPolicies are ADVISORY ONLY: they self-validate an App + Operator's namespace config and surface failures via status + SecurityPosture + but never block EnvoyExtensionPolicy generation. The enforcement role belongs + to the Cluster Operator's GlobalWAFValidationPolicy (which has an + EnforcementMode); this type intentionally has no EnforcementMode. See the + approved design (per-route/namespaced WAF, designs#25 §01/§02). A future + CO-delegated self-enforcement model would be added separately (RFE). EV-6386. + properties: + rules: + description: Rules defines the validation rules to apply + items: + description: + ValidationRule defines a single Rego-based validation + rule + properties: + message: + description: Message is displayed when validation fails + maxLength: 1024 + type: string + name: + description: Name is a unique identifier for this rule + maxLength: 63 + minLength: 1 + type: string + rego: + description: |- + Rego is a Rego module that decides violations against the merged WAF + configuration. The module must declare `package waf` and produce a + `violations` set; an empty set means the rule passed. Each violation + may be a plain string message, or an object carrying a `msg` string. + The `input` document available to the module: + - input.directives: []string - the final merged directive list + - input.config.action: string - effective action ("Detect" or "Block") + - input.config.crsState: string - CRS state ("Enabled" or "Disabled") + - input.config.paranoiaLevel: int - effective paranoia level (1-4) + - input.source.globalPolicy: string - name of GlobalWAFPolicy + - input.source.namespacePolicy: string - name of WAFPolicy (if any) + - input.source.globalPlugins: []string - names of global plugins applied + - input.source.namespacePlugins: []string - names of namespace plugins applied + maxLength: 16384 + minLength: 1 + type: string + severity: + default: warning + description: Severity determines the impact of this rule failing + enum: + - info + - warning + - critical + type: string + required: + - name + - rego + type: object + minItems: 1 + type: array + required: + - rules + type: object + status: + description: |- + WAFValidationPolicyStatus defines the observed state. + No conditions are emitted by the controller for this type today; the Conditions + field is reserved for future use. + properties: + conditions: + description: Conditions represent the latest available observations + 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 + lastEvaluated: + description: LastEvaluated is the timestamp of the last evaluation + format: date-time + type: string + securityPosture: + description: + SecurityPosture is the overall posture based on validation + results + enum: + - Compliant + - Warning + - Degraded + - Critical + type: string + validationResults: + description: ValidationResults contains results for each rule + items: + description: + ValidationResult represents the result of a single + validation rule + properties: + message: + description: Message is the failure message (if failed) + maxLength: 1024 + type: string + passed: + description: Passed indicates whether the rule passed + type: boolean + rule: + description: Rule is the name of the validation rule + maxLength: 63 + type: string + severity: + description: Severity is the severity level of this rule + enum: + - info + - warning + - critical + type: string + required: + - passed + - rule + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/projectcalico.org_alertexceptions.yaml b/config/crd/projectcalico.org_alertexceptions.yaml index 2750ea66..1dcd44c1 100644 --- a/config/crd/projectcalico.org_alertexceptions.yaml +++ b/config/crd/projectcalico.org_alertexceptions.yaml @@ -80,3 +80,5 @@ spec: type: object served: true storage: true + subresources: + status: {} diff --git a/config/crd/projectcalico.org_bgpconfigurations.yaml b/config/crd/projectcalico.org_bgpconfigurations.yaml index 3b18633e..6a11cd0b 100644 --- a/config/crd/projectcalico.org_bgpconfigurations.yaml +++ b/config/crd/projectcalico.org_bgpconfigurations.yaml @@ -82,7 +82,7 @@ spec: x-kubernetes-map-type: atomic maxItems: 500 type: array - x-kubernetes-list-type: set + x-kubernetes-list-type: atomic extensions: additionalProperties: type: string @@ -211,7 +211,7 @@ spec: x-kubernetes-map-type: atomic maxItems: 500 type: array - x-kubernetes-list-type: set + x-kubernetes-list-type: atomic programClusterRoutes: description: |- ProgramClusterRoutes controls how a cluster node gets a route to a workload on another node, @@ -237,7 +237,7 @@ spec: type: object x-kubernetes-map-type: atomic type: array - x-kubernetes-list-type: set + x-kubernetes-list-type: atomic serviceExternalIPs: description: |- ServiceExternalIPs are the CIDR blocks for Kubernetes Service External IPs. @@ -253,7 +253,7 @@ spec: type: object x-kubernetes-map-type: atomic type: array - x-kubernetes-list-type: set + x-kubernetes-list-type: atomic serviceLoadBalancerAggregation: default: Enabled description: |- @@ -280,7 +280,7 @@ spec: type: object x-kubernetes-map-type: atomic type: array - x-kubernetes-list-type: set + x-kubernetes-list-type: atomic type: object x-kubernetes-validations: - message: diff --git a/config/crd/projectcalico.org_bgppeers.yaml b/config/crd/projectcalico.org_bgppeers.yaml index 80d512f0..6d6436bb 100644 --- a/config/crd/projectcalico.org_bgppeers.yaml +++ b/config/crd/projectcalico.org_bgppeers.yaml @@ -91,7 +91,9 @@ spec: used in custom BGP templates type: object externalNetwork: - description: Name of the external network to which this peer belongs. + description: + Name of the external network to which this peer belongs. Cannot + be set if network is set. type: string failureDetectionMode: description: |- @@ -141,6 +143,11 @@ spec: RestartMode is "LongLivedGracefulRestart". When not specified, the BIRD defaults are used, which are 120s for "GracefulRestart" and 3600s for "LongLivedGracefulRestart". type: string + network: + description: + Name of the network to which this peer belongs. Cannot + be set if externalNetwork is set. + type: string nextHopMode: description: |- NextHopMode defines the method of calculating the next hop attribute for received routes. @@ -313,6 +320,11 @@ spec: rule: "!has(self.keepOriginalNextHop) || !self.keepOriginalNextHop || !has(self.nextHopMode)" + - message: network and externalNetwork cannot both be set + reason: FieldValueForbidden + rule: + (!has(self.network) || size(self.network) == 0) || (!has(self.externalNetwork) + || size(self.externalNetwork) == 0) required: - metadata - spec diff --git a/config/crd/projectcalico.org_felixconfigurations.yaml b/config/crd/projectcalico.org_felixconfigurations.yaml index 7a7282f5..988b3890 100644 --- a/config/crd/projectcalico.org_felixconfigurations.yaml +++ b/config/crd/projectcalico.org_felixconfigurations.yaml @@ -322,6 +322,14 @@ spec: [Default: unset - read from net.ipv4.ipfrag_time] pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ type: string + bpfIPFragmentReassemblyEnabled: + description: |- + BPFIPFragmentReassemblyEnabled controls whether Felix loads the BPF program that + reassembles out-of-order IP fragments from external networks. This program requires + a kernel newer than 5.10. When enabled (the default) and the program fails to load, + Felix reports not-ready until the user sets this to false. When false, fragmented + packets from external sources are dropped. [Default: true] + type: boolean bpfJITHardening: allOf: - enum: @@ -1470,6 +1478,16 @@ spec: ExcludeL7SourceInfo - Aggregate over all other fields ignoring the source aggregated name, namespace, and type. pattern: ^(?i)(IncludeL7SourceInfo|IncludeL7SourceInfoNoPort|ExcludeL7SourceInfo)?$ type: string + l7LogsFileAggregationTLSSNI: + description: |- + L7LogsFileAggregationTLSSNI controls whether the TLS Server Name Indication (SNI) + participates in the aggregation key for L7 logs. + [Default: IncludeL7TLSSNI - SNI is part of the aggregation key] + Accepted values: + IncludeL7TLSSNI - Include the SNI in the aggregation key. + ExcludeL7TLSSNI - Aggregate over all other fields ignoring the SNI entirely. + pattern: ^(?i)(IncludeL7TLSSNI|ExcludeL7TLSSNI)?$ + type: string l7LogsFileAggregationTrimURL: description: |- L7LogsFileAggregationTrimURL is used to choose the type of aggregation for the url on L7 log entries. @@ -1519,6 +1537,12 @@ spec: [Default: 300s] pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ type: string + l7ObservabilityEnabled: + description: |- + L7ObservabilityEnabled enables eBPF-based L7 HTTP and TLS observability. + It is dataplane-agnostic - works with eBPF, iptables, or nftables. + Requires kernel 5.17+. [Default: false] + type: boolean liveMigrationRouteConvergenceTime: description: |- LiveMigrationRouteConvergenceTime is the time to keep elevated route priority after a @@ -1709,6 +1733,22 @@ spec: "NftablesRefreshInterval controls the interval at which Felix periodically refreshes the nftables rules. [Default: 90s]" type: string + nodeSelector: + description: |- + NodeSelector is an optional label selector that restricts this FelixConfiguration + to apply only to nodes that match the given selector. This field is only valid + on FelixConfiguration resources whose name is not "default" and does not start + with "node.". For resources named "default", the configuration applies globally + to all nodes. For resources named "node.", the configuration applies to + the named node only. + + At most one selector-scoped FelixConfiguration should match any given node. + If multiple selector-scoped resources match, the oldest (by creation + timestamp) is used and a warning is logged. This prevents an accidentally + created conflicting resource from disrupting an existing, working + configuration. + maxLength: 1024 + type: string openstackRegion: description: |- OpenstackRegion is the name of the region that a particular Felix belongs to. In a multi-region @@ -2195,5 +2235,13 @@ spec: - metadata - spec type: object + x-kubernetes-validations: + - message: + nodeSelector must not be set on the 'default' or per-node ('node.*') + FelixConfiguration + reason: FieldValueForbidden + rule: + "self.metadata.name == 'default' || self.metadata.name.startsWith('node.') + ? !has(self.spec.nodeSelector) : true" served: true storage: true diff --git a/config/crd/projectcalico.org_globalalerts.yaml b/config/crd/projectcalico.org_globalalerts.yaml index 5e176fe3..5583399d 100644 --- a/config/crd/projectcalico.org_globalalerts.yaml +++ b/config/crd/projectcalico.org_globalalerts.yaml @@ -228,3 +228,5 @@ spec: type: object served: true storage: true + subresources: + status: {} diff --git a/config/crd/projectcalico.org_globalreports.yaml b/config/crd/projectcalico.org_globalreports.yaml index 7522f100..355df8eb 100644 --- a/config/crd/projectcalico.org_globalreports.yaml +++ b/config/crd/projectcalico.org_globalreports.yaml @@ -461,3 +461,5 @@ spec: type: object served: true storage: true + subresources: + status: {} diff --git a/config/crd/projectcalico.org_ippools.yaml b/config/crd/projectcalico.org_ippools.yaml index 285389ad..e9bfd125 100644 --- a/config/crd/projectcalico.org_ippools.yaml +++ b/config/crd/projectcalico.org_ippools.yaml @@ -70,14 +70,16 @@ spec: items: description: |- IPPoolAllowedUse defines the allowed uses for an IP pool. - It can be one of "Workload", "Tunnel", or "LoadBalancer". + It can be one of "Workload", "Tunnel", "LoadBalancer" or "HostSecondaryInterface". - "Workload" means the pool is used for workload IP addresses. - "Tunnel" means the pool is used for tunnel IP addresses. - "LoadBalancer" means the pool is used for load balancer IP addresses. + - "HostSecondaryInterface" means the pool is used for host secondary interface IP addresses. enum: - Workload - Tunnel - LoadBalancer + - HostSecondaryInterface type: string maxItems: 10 type: array diff --git a/config/crd/projectcalico.org_kubecontrollersconfigurations.yaml b/config/crd/projectcalico.org_kubecontrollersconfigurations.yaml index cf04e946..e523fb35 100644 --- a/config/crd/projectcalico.org_kubecontrollersconfigurations.yaml +++ b/config/crd/projectcalico.org_kubecontrollersconfigurations.yaml @@ -48,6 +48,19 @@ spec: Controllers enables and configures individual Kubernetes controllers properties: + applicationLayer: + description: |- + ApplicationLayer enables and configures the application-layer subsystem + (WAF, GlobalWAF, WAFPlugin, validation). Operator-managed; users should + not edit this field directly. Non-nil enables the subsystem; activation + is gated on a valid Calico Enterprise license. + properties: + reconcilerPeriod: + description: + "ReconcilerPeriod is the period to perform reconciliation. + [Default: 30s]" + type: string + type: object federatedServices: description: FederatedServices enables and configures the federatedservices @@ -195,6 +208,17 @@ spec: with the Calico datastore. [Default: 5m]" type: string type: object + rbacSync: + description: |- + RBACSync enables and configures the RBAC sync controller, which reconciles + Calico RBAC ClusterRoles and bindings. Disabled by default, set to non-nil to enable. + properties: + reconcilerPeriod: + description: + "ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 30s]" + type: string + type: object serviceAccount: description: ServiceAccount enables and configures the service @@ -287,6 +311,19 @@ spec: Controllers enables and configures individual Kubernetes controllers properties: + applicationLayer: + description: |- + ApplicationLayer enables and configures the application-layer subsystem + (WAF, GlobalWAF, WAFPlugin, validation). Operator-managed; users should + not edit this field directly. Non-nil enables the subsystem; activation + is gated on a valid Calico Enterprise license. + properties: + reconcilerPeriod: + description: + "ReconcilerPeriod is the period to perform + reconciliation. [Default: 30s]" + type: string + type: object federatedServices: description: FederatedServices enables and configures the @@ -437,6 +474,18 @@ spec: 5m]" type: string type: object + rbacSync: + description: |- + RBACSync enables and configures the RBAC sync controller, which reconciles + Calico RBAC ClusterRoles and bindings. Disabled by default, set to non-nil to enable. + properties: + reconcilerPeriod: + description: + "ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 30s]" + type: string + type: object serviceAccount: description: ServiceAccount enables and configures the service diff --git a/config/crd/projectcalico.org_licensekeys.yaml b/config/crd/projectcalico.org_licensekeys.yaml index d976e115..c93478b4 100644 --- a/config/crd/projectcalico.org_licensekeys.yaml +++ b/config/crd/projectcalico.org_licensekeys.yaml @@ -24,6 +24,9 @@ spec: - jsonPath: .status.maxnodes name: Max-Nodes type: integer + - jsonPath: .status.maxcores + name: Max-Cores + type: integer - jsonPath: .status.conditions[?(@.type=='Valid')].status name: Valid type: string @@ -149,8 +152,11 @@ spec: GracePeriod is how long after expiry the license remains functional (e.g. "90d") type: string + maxcores: + description: Maximum Number of Allowed CPU Cores. + type: integer maxnodes: - description: Maximum Number of Allowed Nodes + description: Maximum Number of Allowed Nodes. type: integer package: description: diff --git a/config/crd/projectcalico.org_managedclusters.yaml b/config/crd/projectcalico.org_managedclusters.yaml index b415f75d..c6f1590f 100644 --- a/config/crd/projectcalico.org_managedclusters.yaml +++ b/config/crd/projectcalico.org_managedclusters.yaml @@ -14,7 +14,17 @@ spec: preserveUnknownFields: false scope: Cluster versions: - - name: v3 + - additionalPrinterColumns: + - description: + Whether the managed cluster is currently connected to the management + cluster + jsonPath: .status.conditions[?(@.type=='ManagedClusterConnected')].status + name: Connected + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v3 schema: openAPIV3Schema: description: |- @@ -85,7 +95,8 @@ spec: required: - metadata - spec - - status type: object served: true storage: true + subresources: + status: {} diff --git a/config/crd/projectcalico.org_networks.yaml b/config/crd/projectcalico.org_networks.yaml new file mode 100644 index 00000000..7e2846d2 --- /dev/null +++ b/config/crd/projectcalico.org_networks.yaml @@ -0,0 +1,247 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: networks.projectcalico.org +spec: + group: projectcalico.org + names: + kind: Network + listKind: NetworkList + plural: networks + singular: network + preserveUnknownFields: false + scope: Cluster + versions: + - name: v3 + schema: + openAPIV3Schema: + description: |- + Network defines a logical network within a Calico cluster. Each Network has a type + (VRF, ...) that determines how pods on that network are isolated and how + their traffic is routed. + 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: |- + NetworkSpec contains the specification for a Network resource. Exactly one of the + network-type fields (vrf, ...) must be set. + maxProperties: 1 + minProperties: 1 + properties: + vrf: + description: |- + VRF network configuration. + Pods interfaces on a VRF network are isolated in a Linux VRF and can only access their own VRF. + properties: + hostConfig: + description: |- + HostConfig defines per-node configuration for this VRF network. At least one entry + must be specified. When multiple entries are present (e.g. one per rack), they must + have disjoint nodeSelectors although this is not enforced. For a given node, the + first matching entry is applied and all others are ignored. + + The list is stored and served as a JSON array; Kubernetes preserves the + order in which entries were submitted (including across Server-Side + Apply merges keyed on nodeSelector), so the result of `kubectl get -oyaml` + is authoritative for "first match wins". Single-actor edits keep the + order users see in the YAML they edit. + items: + description: |- + VRFHostConfig provides node-specific VRF settings which may vary across different hosts + in the cluster. + properties: + hostInterfaces: + description: |- + Interfaces on the node to attach to the VRF. The IP address, and local routes + for that IP address will move into the VRF routing table. At least one interface + should be specified to allow pods in the VRF to communicate outside the node. + items: + description: |- + InterfaceMatch identifies a network interface. Exactly one match + criterion must be set. + maxProperties: 1 + minProperties: 1 + properties: + name: + description: |- + Name matches a network interface by its exact device name + (e.g. "bond0", "eth1", "ens192"). + maxLength: 15 + minLength: 1 + type: string + type: object + type: array + x-kubernetes-list-type: atomic + nodeSelector: + default: "" + description: |- + NodeSelector is a Calico selector expression that determines which nodes this + configuration applies to. If omitted, the entry applies to all nodes. + When multiple HostConfig entries are present, the first entry whose selector + matches a given node wins. + type: string + routeTableIndex: + description: |- + RouteTableIndex is the Linux kernel routing table number to use for this VRF. + Must be unique on these nodes, must not overlap with the RouteTableRanges in + FelixConfiguration, and must not collide with tables used by other software on + the node. Tables 253 (default), 254 (main), and 255 (local) are reserved by + the kernel. + format: int32 + maximum: 2147483647 + minimum: 1 + type: integer + staticRoutes: + description: |- + StaticRoutes are additional routes programmed into the VRF routing table, beyond + the pod routes that Felix manages automatically and routes derived from VRF + interface addresses. + items: + description: + VRFStaticRoute defines a static route to + program in a VRF routing table. + properties: + action: + description: |- + Action determines how traffic matching this route is handled. Exactly one action + field must be set. + maxProperties: 1 + minProperties: 1 + properties: + nextHop: + description: |- + NextHop forwards matching traffic to the specified gateway IP. The address must be + reachable on the subnet of one of the VRF interfaces on the node. + type: string + type: object + destination: + description: |- + Destination is the CIDR prefix for this route. Use "0.0.0.0/0" or "::/0" for a + default route. + type: string + required: + - action + - destination + type: object + type: array + x-kubernetes-list-type: atomic + required: + - routeTableIndex + type: object + maxItems: 100 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - nodeSelector + x-kubernetes-list-type: map + routing: + description: + Routing controls cluster-wide routing behaviour for + this VRF network. + properties: + inClusterMode: + default: Local + description: |- + InClusterMode controls how Felix programs routes to pods on remote nodes inside + the VRF routing table. + + - Local: Felix programs routes to VRF pods local to this node; + routing to pods on other nodes must be handled by BGP. + enum: + - Local + type: string + type: object + required: + - hostConfig + type: object + type: object + status: + description: NetworkStatus reports the observed state of the Network resource. + properties: + conditions: + description: + Conditions is a list of conditions that apply to this + network. + 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 + x-kubernetes-list-type: atomic + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/projectcalico.org_packetcaptures.yaml b/config/crd/projectcalico.org_packetcaptures.yaml index 60f72703..d36ec49f 100644 --- a/config/crd/projectcalico.org_packetcaptures.yaml +++ b/config/crd/projectcalico.org_packetcaptures.yaml @@ -166,3 +166,5 @@ spec: type: object served: true storage: true + subresources: + status: {} diff --git a/config/crd/projectcalico.org_securityeventwebhooks.yaml b/config/crd/projectcalico.org_securityeventwebhooks.yaml index 7226756f..b701e292 100644 --- a/config/crd/projectcalico.org_securityeventwebhooks.yaml +++ b/config/crd/projectcalico.org_securityeventwebhooks.yaml @@ -190,3 +190,5 @@ spec: type: object served: true storage: true + subresources: + status: {} diff --git a/deps.txt b/deps.txt index ca5f796d..b9e81ba0 100644 --- a/deps.txt +++ b/deps.txt @@ -1,14 +1,14 @@ !!! GENERATED FILE, DO NOT EDIT !!! Run 'make gen-deps-files' to regenerate. -go 1.26.1 +go 1.26.3 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/emicklei/go-restful v2.15.0+incompatible github.com/emicklei/go-restful/v3 v3.13.0 github.com/fxamacker/cbor/v2 v2.9.0 github.com/go-logr/logr v1.4.3 -github.com/go-openapi/jsonpointer v0.22.4 -github.com/go-openapi/jsonreference v0.21.4 +github.com/go-openapi/jsonpointer v0.22.5 +github.com/go-openapi/jsonreference v0.21.5 github.com/go-openapi/swag v0.23.1 github.com/google/gnostic-models v0.7.0 github.com/google/uuid v1.6.0 @@ -25,29 +25,37 @@ github.com/spf13/pflag v1.0.10 github.com/x448/float16 v0.8.4 go.yaml.in/yaml/v2 v2.4.4 go.yaml.in/yaml/v3 v3.0.4 -golang.org/x/net v0.52.0 +golang.org/x/net v0.54.0 golang.org/x/oauth2 v0.36.0 -golang.org/x/sys v0.42.0 -golang.org/x/term v0.41.0 -golang.org/x/text v0.35.0 +golang.org/x/sys v0.44.0 +golang.org/x/term v0.43.0 +golang.org/x/text v0.37.0 golang.org/x/time v0.15.0 google.golang.org/protobuf v1.36.11 gopkg.in/evanphx/json-patch.v4 v4.13.0 gopkg.in/inf.v0 v0.9.1 gopkg.in/yaml.v3 v3.0.1 -k8s.io/api v0.35.3 -k8s.io/apiextensions-apiserver v0.35.3 -k8s.io/apimachinery v0.35.3 -k8s.io/apiserver v0.35.3 -k8s.io/client-go v0.35.3 +k8s.io/api v0.35.5 +k8s.io/apiextensions-apiserver v0.35.5 +k8s.io/apimachinery v0.35.5 +k8s.io/apiserver v0.35.5 +k8s.io/client-go v0.35.5 k8s.io/klog v0.2.0 k8s.io/klog/v2 v2.140.0 k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 sigs.k8s.io/randfill v1.0.0 -sigs.k8s.io/structured-merge-diff/v6 v6.3.2 +sigs.k8s.io/structured-merge-diff/v6 v6.4.0 sigs.k8s.io/yaml v1.6.0 +local:api/examples/list-gnp +local:api/hack/openapi-schema +local:api/pkg/apis/projectcalico/v3 +local:api/pkg/client/applyconfiguration_generated/internal +local:api/pkg/client/applyconfiguration_generated/projectcalico/v3 +local:api/pkg/client/clientset_generated/clientset +local:api/pkg/client/clientset_generated/clientset/scheme +local:api/pkg/client/clientset_generated/clientset/typed/projectcalico/v3 local:api/pkg/lib/numorstring local:api/pkg/openapi diff --git a/go.mod b/go.mod index ef61cb6c..3c687a93 100644 --- a/go.mod +++ b/go.mod @@ -1,19 +1,19 @@ module github.com/tigera/api -go 1.26.1 +go 1.26.3 require ( github.com/jinzhu/copier v0.4.0 - github.com/onsi/ginkgo/v2 v2.28.1 - github.com/onsi/gomega v1.39.1 - github.com/projectcalico/api v0.0.0-20260303210141-543421943355 - k8s.io/api v0.35.3 - k8s.io/apiextensions-apiserver v0.35.3 - k8s.io/apimachinery v0.35.3 - k8s.io/apiserver v0.35.3 - k8s.io/client-go v0.35.3 + github.com/onsi/ginkgo/v2 v2.28.3 + github.com/onsi/gomega v1.40.0 + github.com/projectcalico/api v0.0.0-20260415222737-ebf7b29bd308 + k8s.io/api v0.35.5 + k8s.io/apiextensions-apiserver v0.35.5 + k8s.io/apimachinery v0.35.5 + k8s.io/apiserver v0.35.5 + k8s.io/client-go v0.35.5 k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 - sigs.k8s.io/structured-merge-diff/v6 v6.3.0 + sigs.k8s.io/structured-merge-diff/v6 v6.4.0 sigs.k8s.io/yaml v1.6.0 ) @@ -29,7 +29,7 @@ require ( github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect + github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 // indirect github.com/google/uuid v1.6.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -42,15 +42,15 @@ require ( github.com/x448/float16 v0.8.4 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/mod v0.32.0 // indirect - golang.org/x/net v0.49.0 // indirect + golang.org/x/mod v0.35.0 // indirect + golang.org/x/net v0.53.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/term v0.39.0 // indirect - golang.org/x/text v0.33.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.43.0 // indirect + golang.org/x/term v0.42.0 // indirect + golang.org/x/text v0.36.0 // indirect golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.41.0 // indirect + golang.org/x/tools v0.44.0 // indirect google.golang.org/protobuf v1.36.8 // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect @@ -62,29 +62,29 @@ require ( ) replace ( - k8s.io/api => k8s.io/api v0.35.3 - k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.35.3 - k8s.io/apimachinery => k8s.io/apimachinery v0.35.3 - k8s.io/apiserver => k8s.io/apiserver v0.35.3 - k8s.io/cli-runtime => k8s.io/cli-runtime v0.35.3 - k8s.io/client-go => k8s.io/client-go v0.35.3 - k8s.io/cloud-provider => k8s.io/cloud-provider v0.35.3 - k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.35.3 - k8s.io/code-generator => k8s.io/code-generator v0.35.3 - k8s.io/component-base => k8s.io/component-base v0.35.3 - k8s.io/component-helpers => k8s.io/component-helpers v0.35.3 - k8s.io/controller-manager => k8s.io/controller-manager v0.35.3 - k8s.io/cri-api => k8s.io/cri-api v0.35.3 - k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.35.3 - k8s.io/externaljwt => k8s.io/externaljwt v0.35.3 - k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.35.3 - k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.35.3 - k8s.io/kube-proxy => k8s.io/kube-proxy v0.35.3 - k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.35.3 - k8s.io/kubectl => k8s.io/kubectl v0.35.3 - k8s.io/kubelet => k8s.io/kubelet v0.35.3 - k8s.io/metrics => k8s.io/metrics v0.35.3 - k8s.io/mount-utils => k8s.io/mount-utils v0.35.3 - k8s.io/node-api => k8s.io/node-api v0.35.3 - k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.35.3 + k8s.io/api => k8s.io/api v0.35.5 + k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.35.5 + k8s.io/apimachinery => k8s.io/apimachinery v0.35.5 + k8s.io/apiserver => k8s.io/apiserver v0.35.5 + k8s.io/cli-runtime => k8s.io/cli-runtime v0.35.5 + k8s.io/client-go => k8s.io/client-go v0.35.5 + k8s.io/cloud-provider => k8s.io/cloud-provider v0.35.5 + k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.35.5 + k8s.io/code-generator => k8s.io/code-generator v0.35.5 + k8s.io/component-base => k8s.io/component-base v0.35.5 + k8s.io/component-helpers => k8s.io/component-helpers v0.35.5 + k8s.io/controller-manager => k8s.io/controller-manager v0.35.5 + k8s.io/cri-api => k8s.io/cri-api v0.35.5 + k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.35.5 + k8s.io/externaljwt => k8s.io/externaljwt v0.35.5 + k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.35.5 + k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.35.5 + k8s.io/kube-proxy => k8s.io/kube-proxy v0.35.5 + k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.35.5 + k8s.io/kubectl => k8s.io/kubectl v0.35.5 + k8s.io/kubelet => k8s.io/kubelet v0.35.5 + k8s.io/metrics => k8s.io/metrics v0.35.5 + k8s.io/mount-utils => k8s.io/mount-utils v0.35.5 + k8s.io/node-api => k8s.io/node-api v0.35.5 + k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.35.5 ) diff --git a/go.sum b/go.sum index 78128b35..7a39503b 100644 --- a/go.sum +++ b/go.sum @@ -34,8 +34,8 @@ github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7O 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/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= -github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= +github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 h1:EwtI+Al+DeppwYX2oXJCETMO23COyaKGP6fHVpkpWpg= +github.com/google/pprof v0.0.0-20260402051712-545e8a4df936/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= @@ -67,14 +67,14 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= -github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= -github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= -github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= +github.com/onsi/ginkgo/v2 v2.28.3 h1:4JvMdwtFU0imd8fHx25OJXoDMRexnf8v5NHKYSTTji4= +github.com/onsi/ginkgo/v2 v2.28.3/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU9kNcA44= +github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc= +github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A= 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/projectcalico/api v0.0.0-20260303210141-543421943355 h1:nz3rpu5iJMZyrtlJzGozf4/lKEl3MRH5LHvLcg6SgAg= -github.com/projectcalico/api v0.0.0-20260303210141-543421943355/go.mod h1:SRPurzoi23s+lg9pp3Ox2xZsM7z+BAPDm/H3YOuHNWs= +github.com/projectcalico/api v0.0.0-20260415222737-ebf7b29bd308 h1:TdeUR3c5JJkfY6T2NBaNouXqdr8U9dYS9aOFYADq0mU= +github.com/projectcalico/api v0.0.0-20260415222737-ebf7b29bd308/go.mod h1:pfbDD0JEeZugRa5YxjVoCna9RVyYWjsI8qZjY5TKSqs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= @@ -106,24 +106,24 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= -golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= +golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= +golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= +golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= +golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= -golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= +golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -136,16 +136,16 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.35.3 h1:pA2fiBc6+N9PDf7SAiluKGEBuScsTzd2uYBkA5RzNWQ= -k8s.io/api v0.35.3/go.mod h1:9Y9tkBcFwKNq2sxwZTQh1Njh9qHl81D0As56tu42GA4= -k8s.io/apiextensions-apiserver v0.35.3 h1:2fQUhEO7P17sijylbdwt0nBdXP0TvHrHj0KeqHD8FiU= -k8s.io/apiextensions-apiserver v0.35.3/go.mod h1:tK4Kz58ykRpwAEkXUb634HD1ZAegEElktz/B3jgETd8= -k8s.io/apimachinery v0.35.3 h1:MeaUwQCV3tjKP4bcwWGgZ/cp/vpsRnQzqO6J6tJyoF8= -k8s.io/apimachinery v0.35.3/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= -k8s.io/apiserver v0.35.3 h1:D2eIcfJ05hEAEewoSDg+05e0aSRwx8Y4Agvd/wiomUI= -k8s.io/apiserver v0.35.3/go.mod h1:JI0n9bHYzSgIxgIrfe21dbduJ9NHzKJ6RchcsmIKWKY= -k8s.io/client-go v0.35.3 h1:s1lZbpN4uI6IxeTM2cpdtrwHcSOBML1ODNTCCfsP1pg= -k8s.io/client-go v0.35.3/go.mod h1:RzoXkc0mzpWIDvBrRnD+VlfXP+lRzqQjCmKtiwZ8Q9c= +k8s.io/api v0.35.5 h1:BrFeUDGY/LBtlA1R5RoxhlYRHs76RnQBc6xbm/y7hsQ= +k8s.io/api v0.35.5/go.mod h1:xWkFhMnoPZdTAQh95Rlw3zZpUUNVlFHcuESUYd06BWM= +k8s.io/apiextensions-apiserver v0.35.5 h1:HttlJjgsx3ddLsASCqklkKvfBlwUoXma8VLpeMG5YL8= +k8s.io/apiextensions-apiserver v0.35.5/go.mod h1:4xbAgP/jbt8sVHE3H4DfE1gSPLUoSzXrNqhZz1lTHKc= +k8s.io/apimachinery v0.35.5 h1:lbjjjUfVeVqFbiOpyhqZHc8DhiYkWOxSNij7lHx2U8Y= +k8s.io/apimachinery v0.35.5/go.mod h1:NNi1taPOpep0jOj+oRha3mBJPqvi0hGdaV8TCqGQ+cc= +k8s.io/apiserver v0.35.5 h1:ZtFpSEmxf/VmOdbL3bo7hLxyNRorRegqOLmYSW0mxEo= +k8s.io/apiserver v0.35.5/go.mod h1:6NNWFTq/UosCwUmqhQDC+3ApzSx5ekeYMIwzSG+49VU= +k8s.io/client-go v0.35.5 h1:wUrgqVSmFRw75bgSHY7X0G/hZM/QYpV0Hg7SYYOYpFk= +k8s.io/client-go v0.35.5/go.mod h1:Z0mDcAJsX1Y7RQfuQlJipiRtqf8Mhk2VDu1/JvRqdGo= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= @@ -156,7 +156,7 @@ sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5E sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= 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/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v6 v6.4.0 h1:qmp2e3ZfFi1/jJbDGpD4mt3wyp6PE1NfKHCYLqgNQJo= +sigs.k8s.io/structured-merge-diff/v6 v6.4.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/hack/openapi-violations-known.list b/hack/openapi-violations-known.list index edfe8855..ba1f69b3 100644 --- a/hack/openapi-violations-known.list +++ b/hack/openapi-violations-known.list @@ -29,5 +29,6 @@ API rule violation: names_match,github.com/tigera/api/pkg/apis/projectcalico/v3, API rule violation: names_match,github.com/tigera/api/pkg/apis/projectcalico/v3,FelixConfigurationSpec,WindowsDNSExtraTTL API rule violation: names_match,github.com/tigera/api/pkg/apis/projectcalico/v3,FelixConfigurationSpec,WireguardPersistentKeepAlive API rule violation: names_match,github.com/tigera/api/pkg/apis/projectcalico/v3,IPAMBlockSpec,DeprecatedStrictAffinity +API rule violation: names_match,github.com/tigera/api/pkg/apis/projectcalico/v3,LicenseKeyStatus,MaxCores API rule violation: names_match,github.com/tigera/api/pkg/apis/projectcalico/v3,LicenseKeyStatus,MaxNodes API rule violation: names_match,github.com/tigera/api/pkg/apis/projectcalico/v3,MigrationControllerConfig,PolicyNameMigrator diff --git a/lib.Makefile b/lib.Makefile index 28426a83..65f1522c 100644 --- a/lib.Makefile +++ b/lib.Makefile @@ -1,8 +1,13 @@ # Find path to the repo root dir (i.e. this files's dir). Must be first in the file, before including anything. -REPO_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) +# Use Make builtins instead of `dirname` so this works under PowerShell on Windows agents too. +REPO_DIR := $(patsubst %/,%,$(dir $(realpath $(lastword $(MAKEFILE_LIST))))) # Always install the git hooks to prevent publishing closed source code to a non-private repo. -install_hooks:=$(shell $(REPO_DIR)/hack/install-git-hooks) +# The install script is bash-only; skip on Windows agents where every $(shell ...) call would +# spawn a PowerShell that adds startup latency to every sub-make. +ifneq ($(OS),Windows_NT) +install_hooks := $(shell $(REPO_DIR)/hack/install-git-hooks) +endif # Disable built-in rules .SUFFIXES: @@ -61,14 +66,18 @@ endif # The list of sub-projects which build non-cluster host RPMs NON_CLUSTER_HOST_SUBDIRS := selinux fluent-bit node -# detect the local outbound ip address +# detect the local outbound ip address (only used by FV/etcd targets that don't run on Windows) +ifneq ($(OS),Windows_NT) LOCAL_IP_ENV?=$(shell ip route get 8.8.8.8 | head -1 | awk '{print $$7}') +endif LATEST_IMAGE_TAG?=latest # these macros create a list of valid architectures for pushing manifests comma := , +ifneq ($(OS),Windows_NT) double_quote := $(shell echo '"') +endif ## Targets used when cross building. .PHONY: native register @@ -108,7 +117,10 @@ THIRD_PARTY_REGISTRY_CI=gcr.io/unique-caldron-775/third-party-ci THIRD_PARTY_REGISTRY_CD=gcr.io/unique-caldron-775/cnx/tigera/third-party # THIRD_PARTY_REGISTRY configures the third-party registry that serves intermediate base image # for some Calico Enterprise components. They are never released directly to public. -THIRD_PARTY_RELEASE_BRANCH ?= $(if $(SEMAPHORE_GIT_BRANCH),$(SEMAPHORE_GIT_BRANCH),master) +# Only master and release-calient-* branches have third-party base images published under +# their branch name. For any other branch (feature branches, or PRs whose base is a feature +# branch such as stacked PRs), fall back to the master-tagged images. +THIRD_PARTY_RELEASE_BRANCH ?= $(if $(filter master release-calient-%,$(SEMAPHORE_GIT_BRANCH)),$(SEMAPHORE_GIT_BRANCH),master) ifeq ($(SEMAPHORE_GIT_REF_TYPE), branch) # on master and release-calient branches THIRD_PARTY_REGISTRY?=$(THIRD_PARTY_REGISTRY_CD) @@ -155,6 +167,14 @@ endif endif endif +# Optional cap on go build/test package parallelism. Appended to GOFLAGS so +# it flows through every docker invocation that already passes GOFLAGS in. +# Useful for limiting memory pressure when running multiple parallel builds +# on a workstation (each in-flight package can fork its own compiler). +ifneq ($(GO_BUILD_PARALLELISM),) +GOFLAGS := $(GOFLAGS) -p=$(GO_BUILD_PARALLELISM) +endif + # For building, we use the go-build image for the *host* architecture, even if the target is different # the one for the host should contain all the necessary cross-compilation tools # we do not need to use the arch since go-build:v0.15 now is multi-arch manifest @@ -164,6 +184,34 @@ CALICO_BUILD = $(GO_BUILD_IMAGE):$(GO_BUILD_VER) RUST_BUILD_IMAGE ?= calico/rust-build CALICO_RUST_BUILD = $(RUST_BUILD_IMAGE):$(RUST_BUILD_VER) +# Cross-compilation support using clang. When building on amd64 for a different +# target architecture, we use clang as a cross-compiler (it natively supports all +# targets) with a per-arch sysroot containing the target libraries. This avoids +# slow QEMU emulation for CGO builds. +# +# Map Go ARCH names to clang target triples. +# Only arm64 and ppc64le need cross-compilation support (CGO is not enabled for s390x). +CLANG_CROSS_TRIPLE_arm64 := aarch64-linux-gnu +CLANG_CROSS_TRIPLE_ppc64le := powerpc64le-linux-gnu + +# Rust target triple (long form). Injected as CARGO_BUILD_TARGET so cargo +# cross-compiles transparently. Linker/sysroot side uses CROSS_TRIPLE below. +RUST_TARGET_amd64 := x86_64-unknown-linux-gnu +RUST_TARGET_arm64 := aarch64-unknown-linux-gnu +RUST_TARGET := $(RUST_TARGET_$(ARCH)) + +# Set CROSS_CC and CROSS_SYSROOT when cross-compiling from amd64. +ifeq ($(BUILDARCH),amd64) +ifneq ($(ARCH),amd64) +ifneq ($(CLANG_CROSS_TRIPLE_$(ARCH)),) +CROSS_TRIPLE := $(CLANG_CROSS_TRIPLE_$(ARCH)) +CROSS_SYSROOT := /usr/$(CROSS_TRIPLE)/sys-root +CROSS_CC := clang --target=$(CROSS_TRIPLE) --sysroot=$(CROSS_SYSROOT) +CROSS_LDFLAGS := -fuse-ld=lld +endif +endif +endif + # Build a binary with boring crypto support. # This function expects you to pass in two arguments: # 1st arg: path/to/input/package(s) @@ -174,6 +222,7 @@ CALICO_RUST_BUILD = $(RUST_BUILD_IMAGE):$(RUST_BUILD_VER) define build_cgo_boring_binary $(DOCKER_RUN) \ -e CGO_ENABLED=1 \ + $(if $(CROSS_CC),-e CC="$(CROSS_CC)") \ -e CGO_CFLAGS=$(CGO_CFLAGS) \ -e CGO_LDFLAGS=$(CGO_LDFLAGS) \ $(CALICO_BUILD) \ @@ -185,6 +234,7 @@ endef define build_cgo_binary $(DOCKER_RUN) \ -e CGO_ENABLED=1 \ + $(if $(CROSS_CC),-e CC="$(CROSS_CC)") \ -e CGO_CFLAGS=$(CGO_CFLAGS) \ -e CGO_LDFLAGS=$(CGO_LDFLAGS) \ $(CALICO_BUILD) \ @@ -220,7 +270,7 @@ define build_cgo_windows_binary -e GOOS=windows \ -e GOEXPERIMENT=nodwarf5 \ $(CALICO_BUILD) \ - sh -c '$(GIT_CONFIG_SSH) go build -o $(2) $(if $(BUILD_TAGS),-tags $(BUILD_TAGS)) -v -buildvcs=false -ldflags "$(LDFLAGS)" $(1)' + sh -c '$(GIT_CONFIG_SSH) go build -o $(2) $(if $(BUILD_TAGS),-tags $(BUILD_TAGS)) -v -buildvcs=false -ldflags "$(LDFLAGS) -s -w" $(1)' endef # For windows builds that do not require cgo. @@ -231,7 +281,7 @@ define build_windows_binary -e GOOS=windows \ -e GOEXPERIMENT=nodwarf5 \ $(CALICO_BUILD) \ - sh -c '$(GIT_CONFIG_SSH) go build -o $(2) $(if $(BUILD_TAGS),-tags $(BUILD_TAGS)) -v -buildvcs=false -ldflags "$(LDFLAGS)" $(1)' + sh -c '$(GIT_CONFIG_SSH) go build -o $(2) $(if $(BUILD_TAGS),-tags $(BUILD_TAGS)) -v -buildvcs=false -ldflags "$(LDFLAGS) -s -w" $(1)' endef # Images used in build / test across multiple directories. @@ -250,6 +300,12 @@ endif # Get version from git. We allow setting this manually for the hashrelease process. # By default, includes commit count and hash (--long). During releases (RELEASE=true), # only the tag is used without the commit count suffix. +# +# Skip on Windows: these LDFLAGS-related vars use bash `||` fallbacks that PowerShell +# can't parse, and Windows builds (e.g. fluentd-base) don't link Go binaries that +# embed buildinfo. Each $(shell git ...) call would otherwise spawn PowerShell on +# every sub-make recursion, multiplying parse time noticeably. +ifneq ($(OS),Windows_NT) GIT_VERSION ?= $(shell git describe --tags --dirty --always --abbrev=12 --long) ifeq ($(RELEASE),true) GIT_VERSION := $(shell git describe --tags --dirty --always --abbrev=12) @@ -265,6 +321,7 @@ BUILD_ID:=$(shell git rev-parse HEAD || uuidgen | sed 's/-//g') # Variables elsewhere that depend on this (such as LDFLAGS) must also be lazy. GIT_DESCRIPTION=$(shell git describe --tags --dirty --always --abbrev=12 || echo '') ENTERPRISE_VERSION?=$(call git-release-tag-from-dev-tag) +endif # Calculate a timestamp for any build artifacts. ifneq ($(OS),Windows_NT) @@ -320,6 +377,23 @@ endif EXTRA_DOCKER_ARGS += -v $(GOMOD_CACHE):/go/pkg/mod:rw +# Optional per-build resource caps. When unset, no flags are added and the +# container has full host access (current behaviour). Useful when running +# multiple parallel builds on a workstation to avoid memory thrash. +# DOCKER_CPUS=N Hard cap on total CPU bandwidth (any core). +# DOCKER_CPUSET_CPUS=0-3 Pin container to specific cores (true affinity). +# GOMAXPROCS=N Cap goroutine parallelism inside each go invocation +# (linker, vet, etc.); complements -p=N from GOFLAGS. +ifneq ($(DOCKER_CPUS),) +EXTRA_DOCKER_ARGS += --cpus=$(DOCKER_CPUS) +endif +ifneq ($(DOCKER_CPUSET_CPUS),) +EXTRA_DOCKER_ARGS += --cpuset-cpus=$(DOCKER_CPUSET_CPUS) +endif +ifneq ($(GOMAXPROCS),) +EXTRA_DOCKER_ARGS += -e GOMAXPROCS=$(GOMAXPROCS) +endif + # Define go architecture flags GOARCH_FLAGS :=-e GOARCH=$(ARCH) @@ -335,6 +409,11 @@ CERTS_PATH := $(REPO_ROOT)/hack/test/certs # /.git/worktrees/. When Docker containers need git access, # the main .git directory must also be mounted, and GIT_DIR / GIT_WORK_TREE # must be set so that git can find objects and the correct working tree. +# +# Skip on Windows: this only configures Linux Docker mounts, and the bash `2>/dev/null` +# redirection PowerShell tries to interpret as `2 > /dev/null` (writing to a file at +# C:\dev\null), which fails noisily on every parse. +ifneq ($(OS),Windows_NT) _GIT_DIR := $(shell git rev-parse --absolute-git-dir 2>/dev/null) _GIT_COMMON_DIR := $(realpath $(shell git rev-parse --git-common-dir 2>/dev/null)) ifneq ($(_GIT_DIR),$(_GIT_COMMON_DIR)) @@ -350,6 +429,7 @@ DOCKER_GIT_WORKTREE_ARGS := \ else DOCKER_GIT_WORKTREE_ARGS := endif +endif # Configure the Calico API group to use. Projects importing this Makefile can override this variable # if they need to. @@ -408,11 +488,29 @@ DOCKER_RUN := $(DOCKER_RUN_PRIV_NET) --net=host DOCKER_GO_BUILD := $(DOCKER_RUN) $(CALICO_BUILD) +# Cross-compile env for Rust + cc-rs / bindgen. Same gate as the Go side. +# Key suffixes use the long Rust triple (cc-rs convention); extend for ppc64le. +ifeq ($(BUILDARCH),amd64) +ifneq ($(ARCH),amd64) +RUST_CROSS_ENV := \ + -e CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=clang \ + -e CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-C link-arg=--target=$(CROSS_TRIPLE) -C link-arg=--sysroot=$(CROSS_SYSROOT) -C link-arg=-fuse-ld=lld" \ + -e CC_aarch64_unknown_linux_gnu=clang \ + -e CXX_aarch64_unknown_linux_gnu=clang++ \ + -e AR_aarch64_unknown_linux_gnu=$(CROSS_TRIPLE)-ar \ + -e CFLAGS_aarch64_unknown_linux_gnu="--sysroot=$(CROSS_SYSROOT) -fuse-ld=lld" \ + -e CXXFLAGS_aarch64_unknown_linux_gnu="--sysroot=$(CROSS_SYSROOT) -fuse-ld=lld" \ + -e BINDGEN_EXTRA_CLANG_ARGS_aarch64_unknown_linux_gnu="--target=$(CROSS_TRIPLE) --sysroot=$(CROSS_SYSROOT) -I$(CROSS_SYSROOT)/usr/include" +endif +endif + DOCKER_RUST_BUILD := mkdir -p bin && \ docker run --rm \ --init \ --user $(LOCAL_USER_ID):$(LOCAL_GROUP_ID) \ $(EXTRA_DOCKER_ARGS) \ + -e CARGO_BUILD_TARGET=$(RUST_TARGET) \ + $(RUST_CROSS_ENV) \ -v $(REPO_ROOT):/rust/src/github.com/projectcalico/calico:rw \ -w /rust/src/$(PACKAGE_NAME) \ $(CALICO_RUST_BUILD) @@ -420,11 +518,32 @@ DOCKER_RUST_BUILD := mkdir -p bin && \ # Host native build images HOST_NATIVE_BUILD_IMAGE ?= calico/host-native-build -.PHONY: host-native-build -host-native-build: $(wildcard $(REPO_DIR)/third_party/host-native/Dockerfile.*) - cd $(REPO_DIR)/third_party/host-native && \ +# Go release for the rhel8 host-native image, derived from GO_BUILD_VER. +# Sole source of truth — bake file and Dockerfile carry no default. +RHEL8_GO_VERSION = $(firstword $(subst -, ,$(GO_BUILD_VER))) + +# Distros for which we maintain a host-native build image — discovered from +# Dockerfiles in third_party/host-native/. New distros are picked up +# automatically by adding a Dockerfile.. +HOST_NATIVE_DISTROS := $(patsubst Dockerfile.%,%,$(notdir $(wildcard $(REPO_DIR)/third_party/host-native/Dockerfile.*))) + +.PHONY: host-native-build $(addprefix host-native-build-,$(HOST_NATIVE_DISTROS)) + +# Umbrella — build host-native images for every supported distro. +host-native-build: $(addprefix host-native-build-,$(HOST_NATIVE_DISTROS)) + +# Per-distro — build only the named host-native image. Package targets should +# depend on `host-native-build-` to avoid triggering bakes of images +# they don't use. Generated as explicit rules per distro because GNU make +# does not apply pattern rules to .PHONY targets. +define host_native_build_rule +host-native-build-$(1): $$(REPO_DIR)/third_party/host-native/Dockerfile.$(1) + cd $$(REPO_DIR)/third_party/host-native && \ + RHEL8_GO_VERSION=$$(RHEL8_GO_VERSION) \ docker buildx bake --load --pull \ - -f $(REPO_DIR)/third_party/host-native/host-native-build-bake.hcl + -f $$(REPO_DIR)/third_party/host-native/host-native-build-bake.hcl $(1) +endef +$(foreach d,$(HOST_NATIVE_DISTROS),$(eval $(call host_native_build_rule,$(d)))) DOCKER_HOST_NATIVE_RUN := docker run --rm \ --net=host \ @@ -435,6 +554,9 @@ DOCKER_HOST_NATIVE_RUN := docker run --rm \ -w /go/src/$(PACKAGE_NAME) # This function replaces the version string in the spec template and builds the rpm package. +# Args: $(1) distro, $(2) package name, $(3) component version (passed to +# generate-package-version.sh), $(4) optional sourcedir override (relative to +# component directory; defaults to component dir itself). define host_native_rpm_build $(eval version := $(shell $(REPO_ROOT)/hack/generate-package-version.sh $(REPO_ROOT) rpm "" $(3))) @@ -444,7 +566,7 @@ define host_native_rpm_build $(HOST_NATIVE_BUILD_IMAGE):$(1) \ sh -c 'rpmbuild \ --define "_topdir $$PWD/package/$(1)" \ - --define "_sourcedir $$PWD" \ + --define "_sourcedir $$PWD$(if $(4),/$(4),)" \ -ba rhel/$(2).spec' endef @@ -498,16 +620,25 @@ endef # IMAGE_DEPS lists non-Go files that the Docker image depends on (Dockerfiles, # config templates, scripts, etc.). Components should override or append to # this variable and include $(IMAGE_DEPS) in their .image.created prereqs. +# +# Skip on Windows: this is dependency tracking for Linux Go-based image stamps; +# Windows components (e.g. third_party/fluentd-base) build pure Docker images. +# Each $(shell find ... grep ... cut ...) call would otherwise spawn PowerShell +# (no find/grep/cut available) on every sub-make recursion. With ~20 components +# referenced from .image.created-* prerequisites below, this was the dominant +# contributor to the Windows publish job hitting Semaphore's 3h timeout. ############################################################################### +IMAGE_DEPS ?= Dockerfile + +ifneq ($(OS),Windows_NT) ifneq ($(wildcard deps.txt),) SRC_FILES := $(shell find $(addprefix $(REPO_ROOT)/,$(shell grep '^local:' deps.txt | cut -d: -f2-)) -name '*.go' 2>/dev/null) endif -IMAGE_DEPS ?= Dockerfile - # Expand a component's deps.txt local entries to the list of .go files. # Usage: $(call local-deps-go-files,) local-deps-go-files = $(shell find $(addprefix $(REPO_ROOT)/,$(shell grep '^local:' $(REPO_ROOT)/$(1)/deps.txt | cut -d: -f2-)) -name '*.go' 2>/dev/null) +endif # A target that does nothing but it always stale, used to force a rebuild on certain targets based on some non-file criteria. .PHONY: force-rebuild @@ -601,7 +732,6 @@ define update_calico_base_pin fi' endef -GIT_REMOTE?=origin API_BRANCH?=$(PIN_BRANCH) API_REPO?=github.com/projectcalico/calico/api BASE_API_REPO?=github.com/projectcalico/calico/api @@ -859,9 +989,10 @@ REPO_REL_DIR=$(shell if [ -e hack/format-changed-files.sh ]; then echo '.'; else # Format changed files only. fix-changed go-fmt-changed goimports-changed: if [ "$(SKIP_FIX_CHANGED)" != "true" ]; then \ + parent_branch=`release_prefix=$(RELEASE_BRANCH_PREFIX)-v git_repo_slug=$(GIT_REPO_SLUG) $(REPO_REL_DIR)/hack/find-parent-release-branch.sh`; \ $(DOCKER_RUN) -e release_prefix=$(RELEASE_BRANCH_PREFIX)-v \ -e git_repo_slug=$(GIT_REPO_SLUG) \ - -e parent_branch=$(shell git_repo_slug=$(GIT_REPO_SLUG) $(REPO_REL_DIR)/hack/find-parent-release-branch.sh) \ + -e parent_branch=$$parent_branch \ $(CALICO_BUILD) $(REPO_REL_DIR)/hack/format-changed-files.sh; \ fi @@ -869,7 +1000,7 @@ fix-changed go-fmt-changed goimports-changed: fix-all go-fmt-all goimports-all: $(DOCKER_RUN) $(CALICO_BUILD) $(REPO_REL_DIR)/hack/format-all-files.sh -GOMODDER=./hack/cmd/gomodder/main.go +GOMODDER=$(REPO_REL_DIR)/hack/cmd/gomodder/main.go .PHONY: verify-go-mods verify-go-mods: @@ -1119,17 +1250,39 @@ retag-build-image-with-registry-%: var-require-all-REGISTRY-BUILD_IMAGES $(MAKE) $(addprefix retag-build-image-arch-with-registry-,$(VALIDARCHES)) BUILD_IMAGE=$(call unescapefs,$*) # retag-build-image-arch-with-registry-% retags the build / arch image specified by $* and BUILD_IMAGE with the -# registry specified by REGISTRY. +# registry specified by REGISTRY. SOURCE_IMAGE lets a component decouple its +# local tag from BUILD_IMAGE - e.g. cmd/calico tags locally as `tigera/calico` +# but publishes as `/calico`. +SOURCE_IMAGE ?= $(BUILD_IMAGE) retag-build-image-arch-with-registry-%: var-require-all-REGISTRY-BUILD_IMAGE-IMAGETAG - docker tag $(BUILD_IMAGE):$(LATEST_IMAGE_TAG)-$* $(call filter-registry,$(REGISTRY))$(BUILD_IMAGE):$(IMAGETAG)-$* + docker tag $(SOURCE_IMAGE):$(LATEST_IMAGE_TAG)-$* $(call filter-registry,$(REGISTRY))$(BUILD_IMAGE):$(IMAGETAG)-$* $(if $(filter $*,amd64),\ - docker tag $(BUILD_IMAGE):$(LATEST_IMAGE_TAG)-$(ARCH) $(REGISTRY)/$(BUILD_IMAGE):$(IMAGETAG),\ + docker tag $(SOURCE_IMAGE):$(LATEST_IMAGE_TAG)-$(ARCH) $(REGISTRY)/$(BUILD_IMAGE):$(IMAGETAG),\ $(NOECHO) $(NOOP)\ ) +# validate-dev-registries fails if any entry in DEV_REGISTRIES is not prefixed +# by an entry in ALLOWED_DEV_REGISTRIES. Intended to prevent accidental pushes +# to registries outside Tigera control - notably the OSS quay.io/calico and +# docker.io/calico paths owned by projectcalico/calico, which previously got +# clobbered by an Enterprise CI job. +validate-dev-registries: + @if [ -z "$(strip $(ALLOWED_DEV_REGISTRIES))" ]; then exit 0; fi; \ + for r in $(DEV_REGISTRIES); do \ + ok=0; \ + for a in $(ALLOWED_DEV_REGISTRIES); do \ + case "$$r" in $$a*) ok=1; break;; esac; \ + done; \ + if [ "$$ok" = "0" ]; then \ + echo "ERROR: DEV_REGISTRIES contains '$$r', which is not prefixed by any value in ALLOWED_DEV_REGISTRIES (\"$(ALLOWED_DEV_REGISTRIES)\")."; \ + echo " Update ALLOWED_DEV_REGISTRIES in metadata.mk if this push target is now legitimate."; \ + exit 1; \ + fi; \ + done + # push-images-to-registries pushes the build / arch images specified by BUILD_IMAGES and VALIDARCHES to the registries # specified by DEV_REGISTRY. -push-images-to-registries: $(addprefix push-images-to-registry-,$(call escapefs,$(DEV_REGISTRIES))) +push-images-to-registries: validate-dev-registries $(addprefix push-images-to-registry-,$(call escapefs,$(DEV_REGISTRIES))) # push-images-to-registry-% pushes the build / arch images specified by BUILD_IMAGES and VALIDARCHES to the registry # specified by %*. @@ -1157,6 +1310,14 @@ endif # retry_docker_cmd retries a docker command up to a specified number of times. # Usage: $(call retry_docker_cmd,,,,) +# +# Windows agents (Semaphore) execute recipe lines under PowerShell, which can't parse +# the bash retry loop used elsewhere; emit a single-line PowerShell loop instead. +ifeq ($(OS),Windows_NT) +define retry_docker_cmd + for ($$i=1; $$i -le $(3); $$i++) { $(2); if ($$LASTEXITCODE -eq 0) { break }; Write-Host ('WARNING: $(1) failed (attempt {0}/$(3)), retrying in $(4)s...' -f $$i); if ($$i -eq $(3)) { exit 1 }; Start-Sleep -Seconds $(4) } +endef +else define retry_docker_cmd i=1; \ while [ $$i -le $(3) ]; do \ @@ -1167,40 +1328,56 @@ define retry_docker_cmd i=$$((i + 1)); \ done endef +endif # Configuration options for retrying docker commands MANIFEST_RETRIES ?= 5 MANIFEST_RETRY_DELAY ?= 5 +# log_step prints a grep-able timing record. Bracket a long-running shell +# step with start/end calls so per-step durations can be computed from the +# CI log without per-line instrumentation. +# Usage: $(call log_step,start,