rebrand: API group apps.hanzo.ai -> cd.hanzo.ai

apps.hanzo.ai collided head-on with the operator: its App CR already occupies
the resource name `apps.hanzo.ai` (plural `apps`, group `hanzo.ai`), so
`kubectl get apps.hanzo.ai` resolved to the operator's CR, not ours, and
`applications.apps.hanzo.ai` read as a stutter. cd.hanzo.ai gives the delivery
plane its own orthogonal group: applications/applicationsets/appprojects.cd.hanzo.ai
alongside the operator's apps.hanzo.ai. One name per concern.

Mechanically identical to e1b924475 (deploy.hanzo.ai -> apps.hanzo.ai): group
constant, every annotation/label/finalizer domain, the node.Group check, the
leader-election ID, the informer GVRs, RBAC apiGroups, and the 3 CRD manifests.
Also corrects the stale `+groupName=argoproj.io` marker in doc.go, which drove
nothing but misled every reader of this package, and the ArgoCD/argoproj naming
in the hanzo.yml cutover note.

Live cutover (CRD apply, CR re-home, image swap) stays separately greenlit —
hanzo.yml is deliberately build-only.
This commit is contained in:
2026-07-25 15:11:48 -07:00
parent e1b924475c
commit 2ee31f825c
22 changed files with 58 additions and 58 deletions
@@ -169,7 +169,7 @@ func NewCommand() *cobra.Command {
Cache: cacheOpt,
HealthProbeBindAddress: probeBindAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: "58ac56fa.applicationsets.apps.hanzo.ai",
LeaderElectionID: "58ac56fa.applicationsets.cd.hanzo.ai",
Client: ctrlclient.Options{
DryRun: &dryRun,
},
+14 -14
View File
@@ -191,13 +191,13 @@ const (
// LabelKeyAppName is the label key to use to uniquely identify the name of the Kubernetes application
LabelKeyAppName = "app.kubernetes.io/name"
// LabelKeyAutoLabelClusterInfo if set to true will automatically add extra labels from the cluster info (currently it only adds a k8s version label)
LabelKeyAutoLabelClusterInfo = "apps.hanzo.ai/auto-label-cluster-info"
LabelKeyAutoLabelClusterInfo = "cd.hanzo.ai/auto-label-cluster-info"
// LabelKeyLegacyApplicationName is the legacy label (v0.10 and below) and is superseded by 'app.kubernetes.io/instance'
LabelKeyLegacyApplicationName = "applications.argoproj.io/app-name"
// LabelKeySecretType contains the type of argocd secret (currently: 'cluster', 'repository', 'repo-config' or 'repo-creds')
LabelKeySecretType = "apps.hanzo.ai/secret-type"
LabelKeySecretType = "cd.hanzo.ai/secret-type"
// LabelKeyClusterKubernetesVersion contains the kubernetes version of the cluster secret if it has been enabled
LabelKeyClusterKubernetesVersion = "apps.hanzo.ai/kubernetes-version"
LabelKeyClusterKubernetesVersion = "cd.hanzo.ai/kubernetes-version"
// LabelValueSecretTypeCluster indicates a secret type of cluster
LabelValueSecretTypeCluster = "cluster"
// LabelValueSecretTypeRepository indicates a secret type of repository
@@ -212,41 +212,41 @@ const (
LabelValueSecretTypeSCMCreds = "scm-creds"
// AnnotationKeyAppInstance is the Argo CD application name is used as the instance name
AnnotationKeyAppInstance = "apps.hanzo.ai/tracking-id"
AnnotationInstallationID = "apps.hanzo.ai/installation-id"
AnnotationKeyAppInstance = "cd.hanzo.ai/tracking-id"
AnnotationInstallationID = "cd.hanzo.ai/installation-id"
// AnnotationCompareOptions is a comma-separated list of options for comparison
AnnotationCompareOptions = "apps.hanzo.ai/compare-options"
AnnotationCompareOptions = "cd.hanzo.ai/compare-options"
// AnnotationClientSideApplyMigrationManager specifies a custom field manager for client-side apply migration
AnnotationClientSideApplyMigrationManager = "apps.hanzo.ai/client-side-apply-migration-manager"
AnnotationClientSideApplyMigrationManager = "cd.hanzo.ai/client-side-apply-migration-manager"
// AnnotationIgnoreHealthCheck when set on an Application's immediate child indicates that its health check
// can be disregarded.
AnnotationIgnoreHealthCheck = "apps.hanzo.ai/ignore-healthcheck"
AnnotationIgnoreHealthCheck = "cd.hanzo.ai/ignore-healthcheck"
// AnnotationKeyManagedBy is annotation name which indicates that k8s resource is managed by an application.
AnnotationKeyManagedBy = "managed-by"
// AnnotationValueManagedByArgoCD is a 'managed-by' annotation value for resources managed by Argo CD
AnnotationValueManagedByArgoCD = "apps.hanzo.ai"
AnnotationValueManagedByArgoCD = "cd.hanzo.ai"
// AnnotationKeyLinkPrefix tells the UI to add an external link icon to the application node
// that links to the value given in the annotation.
// The annotation key must be followed by a unique identifier. Ex: link.apps.hanzo.ai/dashboard
// The annotation key must be followed by a unique identifier. Ex: link.cd.hanzo.ai/dashboard
// It's valid to have multiple annotations that match the prefix.
// Values can simply be a url or they can have
// an optional link title separated by a "|"
// Ex: "http://grafana.example.com/d/yu5UH4MMz/deployments"
// Ex: "Go to Dashboard|http://grafana.example.com/d/yu5UH4MMz/deployments"
AnnotationKeyLinkPrefix = "link.apps.hanzo.ai/"
AnnotationKeyLinkPrefix = "link.cd.hanzo.ai/"
// AnnotationKeyIgnoreDefaultLinks tells the Application to not add autogenerated links from this object into its externalURLs
// This applies to ingress objects and takes effect if set to "true"
// This only disables the default behavior of generating links based on the ingress spec, and does not disable AnnotationKeyLinkPrefix
AnnotationKeyIgnoreDefaultLinks = "apps.hanzo.ai/ignore-default-links"
AnnotationKeyIgnoreDefaultLinks = "cd.hanzo.ai/ignore-default-links"
// AnnotationKeyAppSkipReconcile tells the Application to skip the Application controller reconcile.
// Skip reconcile when the value is "true" or any other string values that can be strconv.ParseBool() to be true.
AnnotationKeyAppSkipReconcile = "apps.hanzo.ai/skip-reconcile"
AnnotationKeyAppSkipReconcile = "cd.hanzo.ai/skip-reconcile"
// LabelKeyComponentRepoServer is the label key to identify the component as repo-server
LabelKeyComponentRepoServer = "app.kubernetes.io/component"
@@ -442,7 +442,7 @@ func GetCMPWorkDir() string {
const (
// AnnotationApplicationSetRefresh is an annotation that is added when an ApplicationSet is requested to be refreshed by a webhook. The ApplicationSet controller will remove this annotation at the end of reconciliation.
AnnotationApplicationSetRefresh = "apps.hanzo.ai/application-set-refresh"
AnnotationApplicationSetRefresh = "cd.hanzo.ai/application-set-refresh"
)
// gRPC settings
+1 -1
View File
@@ -89,7 +89,7 @@ func populateNodeInfo(un *unstructured.Unstructured, res *ResourceInfo, customLa
case "Gateway":
populateGatewayInfo(un, res)
}
case "apps.hanzo.ai":
case "cd.hanzo.ai":
if gvk.Kind == "Application" {
populateApplicationInfo(un, res)
}
+3 -3
View File
@@ -18,9 +18,9 @@ test:
run: CGO_ENABLED=0 go build ./...
# BUILD-ONLY for the hard-fork cutover: no `deploy:` block. The live `hanzo-cd`
# namespace reconciles the whole Hanzo fleet (ArgoCD IS the deploy mechanism
# for everything else), so the prod cutover — apps.hanzo.ai CRDs + image swap
# + re-homing every live Application from argoproj.io → apps.hanzo.ai — is a
# namespace reconciles the whole Hanzo fleet (Hanzo CD IS the delivery mechanism
# for everything else), so the prod cutover — cd.hanzo.ai CRDs + image swap
# + re-homing every live Application onto cd.hanzo.ai — is a
# deliberate, separately-greenlit action, never an auto-deploy on merge. See
# universe: infra/k8s/hanzo-cd/ for the prepared-but-HELD swap. (Same
# controlled build-only-first pattern as hanzoai/cms.)
@@ -17,7 +17,7 @@ rules:
- list
- watch
- apiGroups:
- apps.hanzo.ai
- cd.hanzo.ai
resources:
- applications
- applicationsets
@@ -8,7 +8,7 @@ metadata:
name: argocd-applicationset-controller
rules:
- apiGroups:
- apps.hanzo.ai
- cd.hanzo.ai
resources:
- applications
- applicationsets
@@ -22,7 +22,7 @@ rules:
- update
- watch
- apiGroups:
- apps.hanzo.ai
- cd.hanzo.ai
resources:
- appprojects
verbs:
@@ -30,7 +30,7 @@ rules:
- list
- watch
- apiGroups:
- apps.hanzo.ai
- cd.hanzo.ai
resources:
- applicationsets/status
verbs:
@@ -70,7 +70,7 @@ rules:
- leases
resourceNames:
# Defined in `cmd/argocd-applicationset-controller/commands/applicationset_controller.go`
- 58ac56fa.applicationsets.apps.hanzo.ai
- 58ac56fa.applicationsets.cd.hanzo.ai
verbs:
- get
- update
@@ -8,7 +8,7 @@ metadata:
name: argocd-notifications-controller
rules:
- apiGroups:
- apps.hanzo.ai
- cd.hanzo.ai
resources:
- applications
- appprojects
@@ -21,7 +21,7 @@ rules:
- patch
- delete
- apiGroups:
- apps.hanzo.ai
- cd.hanzo.ai
resources:
- applications
- appprojects
@@ -8,7 +8,7 @@ metadata:
app.kubernetes.io/component: applicationset-controller
rules:
- apiGroups:
- apps.hanzo.ai
- cd.hanzo.ai
resources:
- applications
- applicationsets
@@ -22,7 +22,7 @@ rules:
- update
- watch
- apiGroups:
- apps.hanzo.ai
- cd.hanzo.ai
resources:
- appprojects
verbs:
@@ -30,7 +30,7 @@ rules:
- list
- watch
- apiGroups:
- apps.hanzo.ai
- cd.hanzo.ai
resources:
- applicationsets/status
verbs:
@@ -70,7 +70,7 @@ rules:
- leases
resourceNames:
# Defined in `cmd/argocd-applicationset-controller/commands/applicationset_controller.go`
- 58ac56fa.applicationsets.apps.hanzo.ai
- 58ac56fa.applicationsets.cd.hanzo.ai
verbs:
- get
- update
@@ -35,7 +35,7 @@ rules:
verbs:
- get # supports viewing pod logs from UI
- apiGroups:
- "apps.hanzo.ai"
- "cd.hanzo.ai"
resources:
- "applications"
- "applicationsets"
+3 -3
View File
@@ -2,11 +2,11 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
labels:
app.kubernetes.io/name: applications.apps.hanzo.ai
app.kubernetes.io/name: applications.cd.hanzo.ai
app.kubernetes.io/part-of: argocd
name: applications.apps.hanzo.ai
name: applications.cd.hanzo.ai
spec:
group: apps.hanzo.ai
group: cd.hanzo.ai
names:
kind: Application
listKind: ApplicationList
+3 -3
View File
@@ -2,11 +2,11 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
labels:
app.kubernetes.io/name: applicationsets.apps.hanzo.ai
app.kubernetes.io/name: applicationsets.cd.hanzo.ai
app.kubernetes.io/part-of: argocd
name: applicationsets.apps.hanzo.ai
name: applicationsets.cd.hanzo.ai
spec:
group: apps.hanzo.ai
group: cd.hanzo.ai
names:
kind: ApplicationSet
listKind: ApplicationSetList
+3 -3
View File
@@ -2,11 +2,11 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
labels:
app.kubernetes.io/name: appprojects.apps.hanzo.ai
app.kubernetes.io/name: appprojects.cd.hanzo.ai
app.kubernetes.io/part-of: argocd
name: appprojects.apps.hanzo.ai
name: appprojects.cd.hanzo.ai
spec:
group: apps.hanzo.ai
group: cd.hanzo.ai
names:
kind: AppProject
listKind: AppProjectList
+1 -1
View File
@@ -2,7 +2,7 @@ package application
const (
// API Group
Group string = "apps.hanzo.ai"
Group string = "cd.hanzo.ai"
// Application constants
ApplicationKind string = "Application"
@@ -3,14 +3,14 @@ package v1alpha1
const (
// AnnotationKeyRefresh is the annotation key which indicates that app needs to be refreshed. Removed by application controller after app is refreshed.
// Might take values 'normal'/'hard'. Value 'hard' means manifest cache and target cluster state cache should be invalidated before refresh.
AnnotationKeyRefresh string = "apps.hanzo.ai/refresh"
AnnotationKeyRefresh string = "cd.hanzo.ai/refresh"
// AnnotationKeyHydrate is the annotation key which indicates that app needs to be hydrated. Removed by application controller after app is hydrated.
AnnotationKeyHydrate string = "apps.hanzo.ai/hydrate"
AnnotationKeyHydrate string = "cd.hanzo.ai/hydrate"
// AnnotationKeyManifestGeneratePaths is an annotation that contains a list of semicolon-separated paths in the
// manifests repository that affects the manifest generation. Paths might be either relative or absolute. The
// absolute path means an absolute path within the repository and the relative path is relative to the application
// source path within the repository.
AnnotationKeyManifestGeneratePaths = "apps.hanzo.ai/manifest-generate-paths"
AnnotationKeyManifestGeneratePaths = "cd.hanzo.ai/manifest-generate-paths"
// AnnotationKeyManagedByURL contains the URL of the Hanzo CD instance managing the application
AnnotationKeyManagedByURL = "apps.hanzo.ai/managed-by-url"
AnnotationKeyManagedByURL = "cd.hanzo.ai/managed-by-url"
)
@@ -7,19 +7,19 @@ const (
DefaultSyncRetryDuration time.Duration = 5000000000 // 5s
DefaultSyncRetryFactor = int64(2)
// ResourcesFinalizerName is the finalizer value which we inject to finalize deletion of an application
ResourcesFinalizerName string = "resources-finalizer.apps.hanzo.ai"
ResourcesFinalizerName string = "resources-finalizer.cd.hanzo.ai"
// PreDeleteFinalizerName is the finalizer that controls pre-delete hooks execution
PreDeleteFinalizerName string = "pre-delete-finalizer.apps.hanzo.ai"
PreDeleteFinalizerName string = "pre-delete-finalizer.cd.hanzo.ai"
// PostDeleteFinalizerName is the finalizer that controls post-delete hooks execution
PostDeleteFinalizerName string = "post-delete-finalizer.apps.hanzo.ai"
PostDeleteFinalizerName string = "post-delete-finalizer.cd.hanzo.ai"
// ForegroundPropagationPolicyFinalizer is the finalizer we inject to delete application with foreground propagation policy
ForegroundPropagationPolicyFinalizer string = "resources-finalizer.apps.hanzo.ai/foreground"
ForegroundPropagationPolicyFinalizer string = "resources-finalizer.cd.hanzo.ai/foreground"
// BackgroundPropagationPolicyFinalizer is the finalizer we inject to delete application with background propagation policy
BackgroundPropagationPolicyFinalizer = "resources-finalizer.apps.hanzo.ai/background"
BackgroundPropagationPolicyFinalizer = "resources-finalizer.cd.hanzo.ai/background"
// DefaultAppProjectName contains name of 'default' app project, which is available in every Hanzo CD installation
DefaultAppProjectName = "default"
+1 -1
View File
@@ -1,5 +1,5 @@
// Package v1alpha1 is the v1alpha1 version of the API.
// +groupName=argoproj.io
// +groupName=cd.hanzo.ai
// +k8s:deepcopy-gen=package,register
// +k8s:openapi-gen=true
package v1alpha1
+1 -1
View File
@@ -2150,7 +2150,7 @@ func (t *ApplicationTree) GetSummary(app *Application) ApplicationSummary {
for _, image := range node.Images {
imagesSet[image] = true
}
if node.Group == "apps.hanzo.ai" && node.Kind == "Application" {
if node.Group == "cd.hanzo.ai" && node.Kind == "Application" {
appOfApps = true
}
}
@@ -48,7 +48,7 @@ func NewFilteredApplicationInformer(client versioned.Interface, namespace string
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewApplicationInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer {
gvr := schema.GroupVersionResource{Group: "apps.hanzo.ai", Version: "v1alpha1", Resource: "applications"}
gvr := schema.GroupVersionResource{Group: "cd.hanzo.ai", Version: "v1alpha1", Resource: "applications"}
identifier := options.InformerName.WithResource(gvr)
tweakListOptions := options.TweakListOptions
return cache.NewSharedIndexInformerWithOptions(
@@ -48,7 +48,7 @@ func NewFilteredApplicationSetInformer(client versioned.Interface, namespace str
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewApplicationSetInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer {
gvr := schema.GroupVersionResource{Group: "apps.hanzo.ai", Version: "v1alpha1", Resource: "applicationsets"}
gvr := schema.GroupVersionResource{Group: "cd.hanzo.ai", Version: "v1alpha1", Resource: "applicationsets"}
identifier := options.InformerName.WithResource(gvr)
tweakListOptions := options.TweakListOptions
return cache.NewSharedIndexInformerWithOptions(
@@ -48,7 +48,7 @@ func NewFilteredAppProjectInformer(client versioned.Interface, namespace string,
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewAppProjectInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer {
gvr := schema.GroupVersionResource{Group: "apps.hanzo.ai", Version: "v1alpha1", Resource: "appprojects"}
gvr := schema.GroupVersionResource{Group: "cd.hanzo.ai", Version: "v1alpha1", Resource: "appprojects"}
identifier := options.InformerName.WithResource(gvr)
tweakListOptions := options.TweakListOptions
return cache.NewSharedIndexInformerWithOptions(
+3 -3
View File
@@ -204,7 +204,7 @@ func (s *Server) getAppEnforceRBAC(ctx context.Context, action, project, namespa
if apierrors.IsNotFound(err) {
if project != "" {
// We know that the user was allowed to get the Application, but the Application does not exist. Return 404.
return nil, nil, status.Error(codes.NotFound, apierrors.NewNotFound(schema.GroupResource{Group: "apps.hanzo.ai", Resource: "applications"}, name).Error())
return nil, nil, status.Error(codes.NotFound, apierrors.NewNotFound(schema.GroupResource{Group: "cd.hanzo.ai", Resource: "applications"}, name).Error())
}
// We don't know if the user was allowed to get the Application, and we don't want to leak information about
// the Application's existence. Return 403.
@@ -226,7 +226,7 @@ func (s *Server) getAppEnforceRBAC(ctx context.Context, action, project, namespa
// The user specified a project. We would have returned a 404 if the user had access to the app, but the app
// did not exist. So we have to return a 404 when the app does exist, but the user does not have access.
// Otherwise, they could infer that the app exists based on the error code.
return nil, nil, status.Error(codes.NotFound, apierrors.NewNotFound(schema.GroupResource{Group: "apps.hanzo.ai", Resource: "applications"}, name).Error())
return nil, nil, status.Error(codes.NotFound, apierrors.NewNotFound(schema.GroupResource{Group: "cd.hanzo.ai", Resource: "applications"}, name).Error())
}
// The user didn't specify a project. We always return permission denied for both lack of access and lack of
// existence.
@@ -243,7 +243,7 @@ func (s *Server) getAppEnforceRBAC(ctx context.Context, action, project, namespa
}).Warnf("user tried to %s application in project %s, but the application is in project %s", action, project, effectiveProject)
// The user has access to the app, but the app is in a different project. Return 404, meaning "app doesn't
// exist in that project".
return nil, nil, status.Error(codes.NotFound, apierrors.NewNotFound(schema.GroupResource{Group: "apps.hanzo.ai", Resource: "applications"}, name).Error())
return nil, nil, status.Error(codes.NotFound, apierrors.NewNotFound(schema.GroupResource{Group: "cd.hanzo.ai", Resource: "applications"}, name).Error())
}
// Get the app's associated project, and make sure all project restrictions are enforced.
proj, err := s.getAppProject(ctx, a, logCtx)