{"record":{"id":"57dc14107d65d89e","repo":"kubernetes/kops","slug":"spotinst-found-multiple-role-tags-q-vs-q-57dc14","errorCode":null,"errorMessage":"spotinst: found multiple role tags %q vs %q","messagePattern":"spotinst: found multiple role tags %q vs %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/spotinsttasks/launch_spec.go","lineNumber":989,"sourceCode":"\t{\n\t\tif e.ImageID != nil {\n\t\t\timage, err := resolveImage(cloud, fi.ValueOf(e.ImageID))\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\ttf.ImageID = image.ImageId\n\t\t}\n\t}\n\n\tvar role string\n\tfor key := range e.Ocean.Tags {\n\t\tif strings.HasPrefix(key, awstasks.CloudTagInstanceGroupRolePrefix) {\n\t\t\tsuffix := strings.TrimPrefix(key, awstasks.CloudTagInstanceGroupRolePrefix)\n\t\t\tif role == \"master\" {\n\t\t\t\trole = \"control-plane\"\n\t\t\t}\n\t\t\tif role != \"\" && role != suffix {\n\t\t\t\treturn fmt.Errorf(\"spotinst: found multiple role tags %q vs %q\", role, suffix)\n\t\t\t}\n\t\t\trole = suffix\n\t\t}\n\t}\n\n\t// Security groups.\n\t{\n\t\tif e.SecurityGroups != nil {\n\t\t\tfor _, sg := range e.SecurityGroups {\n\t\t\t\ttf.SecurityGroups = append(tf.SecurityGroups, sg.TerraformLink())\n\t\t\t\tif role != \"\" {\n\t\t\t\t\tif err := t.AddOutputVariableArray(role+\"_security_groups\", sg.TerraformLink()); err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}","sourceCodeStart":971,"sourceCodeEnd":1007,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/spotinsttasks/launch_spec.go#L971-L1007","documentation":"While rendering Terraform for a LaunchSpec, kops scans instance-group role tags (CloudTagInstanceGroupRolePrefix). If the tags imply two different roles for the same resource, rendering aborts. This catches contradictory tagging such as one tag naming control-plane and another naming a node role.","triggerScenarios":"RenderTerraform encounters multiple tags with the awstasks.CloudTagInstanceGroupRolePrefix whose suffixes disagree, e.g. kops-role=master plus kops-role=node on the same security-group/IAM scope.","commonSituations":"Hand-added role tags on the instance group; leftover tags from a renamed group (old role tag not removed); migrating master->control-plane naming while keeping the old tag.","solutions":["Inspect the instance group's extraTags and remove the stale/conflicting kops-role tag","Keep exactly one kops-role tag per instance group","If renaming roles, delete the old tag in the cluster spec and re-run kops update cluster"],"exampleFix":"// before (cluster spec instanceGroup extraTags)\n\"kops.k8s.io/instancegroup-role\": \"node\", \"kops-role\": \"control-plane\"\n// after\n\"kops.k8s.io/instancegroup-role\": \"node\"","handlingStrategy":"validation","validationCode":"roles := map[string]bool{}\nfor k := range ig.Spec.ExtraTags {\n    if strings.HasPrefix(k, \"kops.k8s.io/instancegroup-role\") {\n        suffix := strings.TrimPrefix(k, \"kops.k8s.io/instancegroup-role\")\n        roles[suffix] = true\n    }\n}\nif len(roles) > 1 {\n    return fmt.Errorf(\"conflicting role tags: %v\", roles)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep at most one kops-role tag per instance group","Remove old role tags when migrating master to control-plane naming","Lint cluster specs for duplicate prefixed tags before kops update","Never hand-copy tags between instance groups without cleanup"],"tags":["spotinst","terraform","tags","iam-roles"],"backgroundTag":"conflicting-role-tags","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}