{"record":{"id":"b824d44f4b367bc8","repo":"kubernetes/kops","slug":"expected-exactly-one-deployment-in-dns-controller","errorCode":null,"errorMessage":"expected exactly one Deployment in dns-controller manifest, found %d","messagePattern":"expected exactly one Deployment in dns-controller manifest, found (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/model/components/addonmanifests/dnscontroller/remap.go","lineNumber":47,"sourceCode":"// Remap remaps the dns-controller addon\nfunc Remap(context *model.KopsModelContext, addon *addonsapi.AddonSpec, objects []*kubemanifest.Object) error {\n\tif !context.UseServiceAccountExternalPermissions() {\n\t\treturn nil\n\t}\n\n\tvar deployments []*kubemanifest.Object\n\tfor _, object := range objects {\n\t\tif object.Kind() != \"Deployment\" {\n\t\t\tcontinue\n\t\t}\n\t\tif object.APIVersion() != \"apps/v1\" {\n\t\t\tcontinue\n\t\t}\n\t\tdeployments = append(deployments, object)\n\t}\n\n\tif len(deployments) != 1 {\n\t\treturn fmt.Errorf(\"expected exactly one Deployment in dns-controller manifest, found %d\", len(deployments))\n\t}\n\n\tpodSpec := &corev1.PodSpec{}\n\tif err := deployments[0].Reparse(podSpec, \"spec\", \"template\", \"spec\"); err != nil {\n\t\treturn fmt.Errorf(\"failed to parse spec.template.spec from Deployment: %v\", err)\n\t}\n\n\tcontainers := podSpec.Containers\n\tif len(containers) != 1 {\n\t\treturn fmt.Errorf(\"expected exactly one container in dns-controller Deployment, found %d\", len(containers))\n\t}\n\n\tif err := iam.AddServiceAccountRole(&context.IAMModelContext, podSpec, &ServiceAccount{}); err != nil {\n\t\treturn err\n\t}\n\n\tif err := deployments[0].Set(podSpec, \"spec\", \"template\", \"spec\"); err != nil {\n\t\treturn err","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/model/components/addonmanifests/dnscontroller/remap.go#L29-L65","documentation":"RemapAddonManifest parses the dns-controller addon manifest and collects its Deployment objects to rewrite image/versions. The addon is expected to ship exactly one Deployment; anything else means the manifest changed unexpectedly, so remapping aborts.","triggerScenarios":"Applying `RemapAddonManifest` to a dns-controller addons.yaml that contains zero or multiple Deployment objects — e.g. after editing the manifest, using a custom/older addon bundle, or a parser that mis-scopes objects.","commonSituations":"Users hand-editing the dns-controller manifest adding extra Deployments; kops upgrade where the bundled addon format changed; a corrupted or truncated addons.yaml yielding no deployments.","solutions":["Restore the stock dns-controller addons manifest shipped with your kops version (do not hand-edit deployments count).","Ensure the addon manifest file is complete and uncorrupted in your addons channel/location.","Upgrade kops so the built-in manifest matches what Remap expects, then re-run `kops update cluster`."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"deployments := countDeployments(dnsControllerManifestYAML)\nif deployments != 1 {\n  return fmt.Errorf(\"dns-controller manifest must contain exactly 1 Deployment, found %d\", deployments)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not hand-edit the bundled dns-controller addon manifest.","Validate addon manifests with kubectl apply --dry-run=client before use.","Use the addons bundle matching your kops version."],"tags":["addons","dns-controller","manifest","deployment"],"backgroundTag":"unexpected-manifest-object-count","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}