Skip to content

Commit ace243e

Browse files
committed
HIVE-2302, HIVE-2644: Destroyers use metadata.json
An earlier commit ensures that ClusterDeployments have an associated Secret containing the metadata.json emitted by the installer. This change adds a new generic destroyer via the (existing) `hiveutil deprovision` command that consumes this metadata.json to deprovision the cluster. This new behavior is the default, but we also include an escape hatch to run the platform-specific legacy destroyer by setting the following annotation on the ClusterDeployment: `hive.openshift.io/legacy-deprovision: "true"`
1 parent c0378f4 commit ace243e

File tree

21 files changed

+374
-133
lines changed

21 files changed

+374
-133
lines changed

apis/hive/v1/clusterdeprovision_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ type ClusterDeprovisionSpec struct {
2424
// BaseDomain is the DNS base domain.
2525
BaseDomain string `json:"baseDomain,omitempty"`
2626

27+
// MetaddataJSONSecretRef references the secret containing the metadata.json emitted by the
28+
// installer, potentially scrubbed for sensitive data.
29+
MetadataJSONSecretRef *corev1.LocalObjectReference `json:"metadataJSONSecretRef,omitempty"`
30+
2731
// Platform contains platform-specific configuration for a ClusterDeprovision
2832
Platform ClusterDeprovisionPlatform `json:"platform,omitempty"`
2933
}

apis/hive/v1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crds/hive.openshift.io_clusterdeprovisions.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,22 @@ spec:
6868
infraID:
6969
description: InfraID is the identifier generated during installation for a cluster. It is used for tagging/naming resources in cloud providers.
7070
type: string
71+
metadataJSONSecretRef:
72+
description: |-
73+
MetaddataJSONSecretRef references the secret containing the metadata.json emitted by the
74+
installer, potentially scrubbed for sensitive data.
75+
properties:
76+
name:
77+
default: ""
78+
description: |-
79+
Name of the referent.
80+
This field is effectively required, but due to backwards compatibility is
81+
allowed to be empty. Instances of this type with an empty value here are
82+
almost certainly wrong.
83+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
84+
type: string
85+
type: object
86+
x-kubernetes-map-type: atomic
7187
platform:
7288
description: Platform contains platform-specific configuration for a ClusterDeprovision
7389
properties:

contrib/pkg/deprovision/azure.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ type AzureOptions struct {
2323
}
2424

2525
// NewDeprovisionAzureCommand is the entrypoint to create the azure deprovision subcommand
26-
func NewDeprovisionAzureCommand() *cobra.Command {
27-
opt := &AzureOptions{}
26+
func NewDeprovisionAzureCommand(logLevel string) *cobra.Command {
27+
opt := &AzureOptions{
28+
logLevel: logLevel,
29+
}
2830
cmd := &cobra.Command{
2931
Use: "azure INFRAID [--azure-cloud-name CLOUDNAME] [--azure-resource-group-name RG] [--azure-base-domain-resource-group-name BDRG]",
3032
Short: "Deprovision Azure assets (as created by openshift-installer)",
@@ -46,7 +48,6 @@ func NewDeprovisionAzureCommand() *cobra.Command {
4648
},
4749
}
4850
flags := cmd.Flags()
49-
flags.StringVar(&opt.logLevel, "loglevel", "info", "log level, one of: debug, info, warn, error, fatal, panic")
5051
flags.StringVar(&opt.cloudName, "azure-cloud-name", installertypesazure.PublicCloud.Name(), "The name of the Azure cloud environment used to configure the Azure SDK")
5152
flags.StringVar(&opt.resourceGroupName, "azure-resource-group-name", "", "The name of the custom Azure resource group in which the cluster was created when not using the default installer-created resource group")
5253
flags.StringVar(&opt.baseDomainResourceGroupName, "azure-base-domain-resource-group-name", "", "The name of the custom Azure resource group in which the cluster's DNS records were created when not using the default installer-created resource group or custom resource group")
Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,101 @@
11
package deprovision
22

33
import (
4+
"encoding/json"
5+
"log"
6+
"os"
7+
8+
"github.com/openshift/installer/pkg/destroy/providers"
9+
"github.com/openshift/installer/pkg/types"
10+
11+
"github.com/openshift/hive/contrib/pkg/utils"
12+
"github.com/openshift/hive/pkg/constants"
13+
414
"github.com/spf13/cobra"
515
)
616

717
// NewDeprovisionCommand is the entrypoint to create the 'deprovision' subcommand
818
func NewDeprovisionCommand() *cobra.Command {
919
var credsDir string
20+
var mjSecretName string
21+
var logLevel string
1022
cmd := &cobra.Command{
1123
Use: "deprovision",
1224
Short: "Deprovision clusters in supported cloud providers",
25+
Long: `Platform subcommands use a legacy code path and are deprecated. \
26+
To run the generic destroyer, use the --metadata-json-secret-name parameter.`,
1327
Run: func(cmd *cobra.Command, args []string) {
14-
cmd.Usage()
28+
if mjSecretName == "" {
29+
cmd.Usage()
30+
return
31+
}
32+
33+
// Generic deprovision flow using metadata.json
34+
logger, err := utils.NewLogger(logLevel)
35+
if err != nil {
36+
log.Fatalf("failed to create logger: %s", err)
37+
}
38+
39+
client, err := utils.GetClient("hiveutil-deprovision-generic")
40+
if err != nil {
41+
logger.WithError(err).Fatal("failed to create kube client")
42+
}
43+
44+
// TODO: Refactor LoadSecretOrDie to avoid this setenv/getenv cycle
45+
k := "METADATA_JSON_SECRET_NAME"
46+
os.Setenv(k, mjSecretName)
47+
mjSecret := utils.LoadSecretOrDie(client, k)
48+
if mjSecret == nil {
49+
// This should not be reachable -- we should have Fatal()ed in LoadSecretOrDie()
50+
logger.WithField("secretName", mjSecretName).Fatal("failed to load metadata.json Secret")
51+
}
52+
53+
mjBytes, ok := mjSecret.Data[constants.MetadataJSONSecretKey]
54+
if !ok {
55+
logger.Fatalf("metadata.json Secret did not contain %q key", constants.MetadataJSONSecretKey)
56+
}
57+
58+
var metadata *types.ClusterMetadata
59+
if err = json.Unmarshal(mjBytes, &metadata); err != nil {
60+
logger.WithError(err).Fatal("failed to unmarshal metadata.json")
61+
}
62+
63+
platform := metadata.Platform()
64+
if platform == "" {
65+
logger.Fatal("no platform configured in metadata.json")
66+
}
67+
68+
destroyerBuilder, ok := providers.Registry[platform]
69+
if !ok {
70+
logger.WithField("platform", platform).Fatal("no destroyers registered for platform")
71+
}
72+
73+
destroyer, err := destroyerBuilder(logger, metadata)
74+
if err != nil {
75+
logger.WithError(err).Fatal("failed to create destroyer")
76+
}
77+
78+
// Ignore quota return
79+
_, err = destroyer.Run()
80+
if err != nil {
81+
logger.WithError(err).Fatal("destroyer returned an error")
82+
}
1583
},
1684
}
1785
flags := cmd.PersistentFlags()
86+
// TODO: Unused -- remove from here and generate.go
1887
flags.StringVar(&credsDir, "creds-dir", "", "directory of the creds. Changes in the creds will cause the program to terminate")
19-
cmd.AddCommand(NewDeprovisionAzureCommand())
20-
cmd.AddCommand(NewDeprovisionGCPCommand())
21-
cmd.AddCommand(NewDeprovisionIBMCloudCommand())
22-
cmd.AddCommand(NewDeprovisionOpenStackCommand())
23-
cmd.AddCommand(NewDeprovisionvSphereCommand())
24-
cmd.AddCommand(NewDeprovisionOvirtCommand())
25-
cmd.AddCommand(NewDeprovisionNutanixCommand())
88+
// TODO: Make this more useful to CLI users by accepting a path to a metadata.json file in the file system
89+
flags.StringVar(&mjSecretName, "metadata-json-secret-name", "", "name of a Secret in the current namespace containing `metadata.json` from the installer")
90+
flags.StringVar(&logLevel, "loglevel", "info", "log level, one of: debug, info, warn, error, fatal, panic")
91+
92+
// Legacy destroyers
93+
cmd.AddCommand(NewDeprovisionAzureCommand(logLevel))
94+
cmd.AddCommand(NewDeprovisionGCPCommand(logLevel))
95+
cmd.AddCommand(NewDeprovisionIBMCloudCommand(logLevel))
96+
cmd.AddCommand(NewDeprovisionOpenStackCommand(logLevel))
97+
cmd.AddCommand(NewDeprovisionvSphereCommand(logLevel))
98+
cmd.AddCommand(NewDeprovisionOvirtCommand(logLevel))
99+
cmd.AddCommand(NewDeprovisionNutanixCommand(logLevel))
26100
return cmd
27101
}

contrib/pkg/deprovision/gcp.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ type gcpOptions struct {
2626
}
2727

2828
// NewDeprovisionGCPCommand is the entrypoint to create the GCP deprovision subcommand
29-
func NewDeprovisionGCPCommand() *cobra.Command {
30-
opt := &gcpOptions{}
29+
func NewDeprovisionGCPCommand(logLevel string) *cobra.Command {
30+
opt := &gcpOptions{
31+
logLevel: logLevel,
32+
}
3133
cmd := &cobra.Command{
3234
Use: "gcp INFRAID --region=REGION",
3335
Short: "Deprovision GCP assets (as created by openshift-installer)",
@@ -45,7 +47,6 @@ func NewDeprovisionGCPCommand() *cobra.Command {
4547
},
4648
}
4749
flags := cmd.Flags()
48-
flags.StringVar(&opt.logLevel, "loglevel", "info", "log level, one of: debug, info, warn, error, fatal, panic")
4950
flags.StringVar(&opt.region, "region", "", "GCP region where the cluster is installed")
5051
flags.StringVar(&opt.networkProjectID, "network-project-id", "", "For shared VPC setups")
5152
return cmd

contrib/pkg/deprovision/ibmcloud.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ type ibmCloudDeprovisionOptions struct {
3030
}
3131

3232
// NewDeprovisionIBMCloudCommand is the entrypoint to create the IBM Cloud deprovision subcommand
33-
func NewDeprovisionIBMCloudCommand() *cobra.Command {
34-
opt := &ibmCloudDeprovisionOptions{}
33+
func NewDeprovisionIBMCloudCommand(logLevel string) *cobra.Command {
34+
opt := &ibmCloudDeprovisionOptions{
35+
logLevel: logLevel,
36+
}
3537
cmd := &cobra.Command{
3638
Use: "ibmcloud INFRAID --region=us-east --base-domain=BASE_DOMAIN --cluster-name=CLUSTERNAME",
3739
Short: "Deprovision IBM Cloud assets (as created by openshift-installer)",
@@ -50,7 +52,6 @@ func NewDeprovisionIBMCloudCommand() *cobra.Command {
5052
}
5153

5254
flags := cmd.Flags()
53-
flags.StringVar(&opt.logLevel, "loglevel", "info", "log level, one of: debug, info, warn, error, fatal, panic")
5455

5556
// Required flags
5657
flags.StringVar(&opt.baseDomain, "base-domain", "", "cluster's base domain")

contrib/pkg/deprovision/nutanix.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ type nutanixOptions struct {
2626
password string
2727
}
2828

29-
func NewDeprovisionNutanixCommand() *cobra.Command {
30-
opt := &nutanixOptions{}
29+
func NewDeprovisionNutanixCommand(logLevel string) *cobra.Command {
30+
opt := &nutanixOptions{
31+
logLevel: logLevel,
32+
}
3133

3234
cmd := &cobra.Command{
3335
Use: "nutanix INFRAID",
@@ -46,7 +48,6 @@ func NewDeprovisionNutanixCommand() *cobra.Command {
4648
},
4749
}
4850
flags := cmd.Flags()
49-
flags.StringVar(&opt.logLevel, "loglevel", "info", "log level, one of: debug, info, warn, error, fatal, panic")
5051
flags.StringVar(&opt.endpoint, constants.CliNutanixPcAddressOpt, "", "Domain name or IP address of the Nutanix Prism Central endpoint")
5152
flags.StringVar(&opt.port, constants.CliNutanixPcPortOpt, "", "Port of the Nutanix Prism Central endpoint")
5253
return cmd

contrib/pkg/deprovision/openstack.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ type openStackOptions struct {
2323
}
2424

2525
// NewDeprovisionOpenStackCommand is the entrypoint to create the OpenStack deprovision subcommand
26-
func NewDeprovisionOpenStackCommand() *cobra.Command {
27-
opt := &openStackOptions{}
26+
func NewDeprovisionOpenStackCommand(logLevel string) *cobra.Command {
27+
opt := &openStackOptions{
28+
logLevel: logLevel,
29+
}
2830
cmd := &cobra.Command{
2931
Use: "openstack INFRAID --cloud=OS_CLOUD",
3032
Short: "Deprovision OpenStack assets (as created by openshift-installer)",
@@ -42,7 +44,6 @@ func NewDeprovisionOpenStackCommand() *cobra.Command {
4244
},
4345
}
4446
flags := cmd.Flags()
45-
flags.StringVar(&opt.logLevel, "loglevel", "info", "log level, one of: debug, info, warn, error, fatal, panic")
4647
flags.StringVar(&opt.cloud, "cloud", "", "OpenStack cloud entry name from clouds.yaml for access/authentication")
4748
return cmd
4849
}

contrib/pkg/deprovision/ovirt.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ type oVirtOptions struct {
2020
}
2121

2222
// NewDeprovisionOvirtCommand is the entrypoint to create the oVirt deprovision subcommand
23-
func NewDeprovisionOvirtCommand() *cobra.Command {
24-
opt := &oVirtOptions{}
23+
func NewDeprovisionOvirtCommand(logLevel string) *cobra.Command {
24+
opt := &oVirtOptions{
25+
logLevel: logLevel,
26+
}
2527
cmd := &cobra.Command{
2628
Use: "ovirt INFRAID",
2729
Short: "Deprovision oVirt assets (as created by openshift-installer)",
@@ -39,7 +41,6 @@ func NewDeprovisionOvirtCommand() *cobra.Command {
3941
},
4042
}
4143
flags := cmd.Flags()
42-
flags.StringVar(&opt.logLevel, "loglevel", "info", "log level, one of: debug, info, warn, error, fatal, panic")
4344
flags.StringVar(&opt.clusterID, "ovirt-cluster-id", "", "oVirt cluster ID")
4445
return cmd
4546
}

0 commit comments

Comments
 (0)