Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,5 @@ export KUBECONFIG="${DIR}/auth/kubeconfig"
Destroy the cluster and release associated resources with:

```sh
openshift-install destroy-cluster
openshift-install destroy cluster
```
34 changes: 33 additions & 1 deletion cmd/openshift-install/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,36 @@ import (
"github.com/spf13/cobra"

"github.com/openshift/installer/pkg/destroy"
"github.com/openshift/installer/pkg/destroy/bootstrap"
_ "github.com/openshift/installer/pkg/destroy/libvirt"
)

func newDestroyCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "destroy",
Short: "Destroy part of an OpenShift cluster",
Long: "",
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
}
cmd.AddCommand(newDestroyBootstrapCmd())
cmd.AddCommand(newDestroyClusterCmd())
return cmd
}

func newLegacyDestroyClusterCmd() *cobra.Command {
return &cobra.Command{
Use: "destroy-cluster",
Short: "DEPRECATED: Use 'destroy cluster' instead.",
RunE: runDestroyCmd,
}
}

func newDestroyClusterCmd() *cobra.Command {
return &cobra.Command{
Use: "cluster",
Short: "Destroy an OpenShift cluster",
Long: "",
RunE: runDestroyCmd,
}
}
Expand All @@ -29,3 +51,13 @@ func runDestroyCmd(cmd *cobra.Command, args []string) error {
}
return nil
}

func newDestroyBootstrapCmd() *cobra.Command {
return &cobra.Command{
Use: "bootstrap",
Short: "Destroy the bootstrap resources",
RunE: func(cmd *cobra.Command, args []string) error {
return bootstrap.Destroy(rootOpts.dir)
},
}
}
1 change: 1 addition & 0 deletions cmd/openshift-install/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func main() {
}
subCmds = append(subCmds,
newDestroyCmd(),
newLegacyDestroyClusterCmd(),
newVersionCmd(),
newGraphCmd(),
)
Expand Down
4 changes: 2 additions & 2 deletions docs/dev/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ The following dependencies must be installed on your system before you can build
sudo dnf install golang-bin gcc-c++
```

If you need support for [libvirt destroy](libvirt-howto#cleanup), you should also install `libvirt-devel`.
If you need support for [libvirt destroy](libvirt-howto.md#cleanup), you should also install `libvirt-devel`.

### CentOS, RHEL

```sh
sudo yum install golang-bin gcc-c++
```

If you need support for [libvirt destroy](libvirt-howto#cleanup), you should also install `libvirt-devel`.
If you need support for [libvirt destroy](libvirt-howto.md#cleanup), you should also install `libvirt-devel`.

## Go

Expand Down
4 changes: 2 additions & 2 deletions docs/dev/libvirt-howto.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ EOF
## Build and run the installer

With [libvirt configured](#install-and-enable-libvirt), you can proceed with [the usual quick-start](../../README.md#quick-start).
Set `TAGS` when building if you need `destroy-cluster` support for libvirt; this is not enabled by default because it requires [cgo][]:
Set `TAGS` when building if you need `destroy cluster` support for libvirt; this is not enabled by default because it requires [cgo][]:

```sh
TAGS=libvirt_destroy hack/build.sh
Expand All @@ -205,7 +205,7 @@ export OPENSHIFT_INSTALL_LIBVIRT_URI=qemu+tcp://192.168.122.1/system
If you compiled with `libvirt_destroy`, you can use:

```sh
openshift-install destroy-cluster
openshift-install destroy cluster
```

If you did not compile with `libvirt_destroy`, you can use [`virsh-cleanup.sh`](../../scripts/maintenance/virsh-cleanup.sh), but note it will currently destroy *all* libvirt resources.
Expand Down
47 changes: 21 additions & 26 deletions pkg/asset/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"

"github.com/openshift/installer/data"
"github.com/openshift/installer/pkg/asset"
"github.com/openshift/installer/pkg/asset/installconfig"
"github.com/openshift/installer/pkg/asset/kubeconfig"
Expand All @@ -19,10 +18,8 @@ import (
)

const (
// MetadataFilename is name of the file where clustermetadata is stored.
MetadataFilename = "metadata.json"

stateFileName = "terraform.tfstate"
// metadataFileName is name of the file where clustermetadata is stored.
metadataFileName = "metadata.json"
)

// Cluster uses the terraform executable to launch a cluster
Expand Down Expand Up @@ -67,19 +64,14 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
return errors.Wrap(err, "failed to write terraform.tfvars file")
}

platform := installConfig.Config.Platform.Name()
if err := data.Unpack(tmpDir, platform); err != nil {
return err
}

metadata := &types.ClusterMetadata{
ClusterName: installConfig.Config.ObjectMeta.Name,
}

defer func() {
if data, err2 := json.Marshal(metadata); err2 == nil {
c.FileList = append(c.FileList, &asset.File{
Filename: MetadataFilename,
Filename: metadataFileName,
Data: data,
})
} else {
Expand Down Expand Up @@ -116,27 +108,16 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
return fmt.Errorf("no known platform")
}

if err := data.Unpack(filepath.Join(tmpDir, "config.tf"), "config.tf"); err != nil {
return err
}

logrus.Infof("Using Terraform to create cluster...")

// This runs the terraform in a temp directory, the tfstate file will be returned
// to the asset store to persist it on the disk.
if err := terraform.Init(tmpDir); err != nil {
return errors.Wrap(err, "failed to initialize terraform")
}

stateFile, err := terraform.Apply(tmpDir)
stateFile, err := terraform.Apply(tmpDir, installConfig.Config.Platform.Name())
if err != nil {
err = errors.Wrap(err, "failed to run terraform")
}

data, err2 := ioutil.ReadFile(stateFile)
if err2 == nil {
c.FileList = append(c.FileList, &asset.File{
Filename: stateFileName,
Filename: terraform.StateFileName,
Data: data,
})
} else {
Expand All @@ -159,13 +140,27 @@ func (c *Cluster) Files() []*asset.File {
// Load returns error if the tfstate file is already on-disk, because we want to
// prevent user from accidentally re-launching the cluster.
func (c *Cluster) Load(f asset.FileFetcher) (found bool, err error) {
_, err = f.FetchByName(stateFileName)
_, err = f.FetchByName(terraform.StateFileName)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}

return true, fmt.Errorf("%q already exisits. There may already be a running cluster", stateFileName)
return true, fmt.Errorf("%q already exisits. There may already be a running cluster", terraform.StateFileName)
}

// LoadMetadata loads the cluster metadata from an asset directory.
func LoadMetadata(dir string) (cmetadata *types.ClusterMetadata, err error) {
raw, err := ioutil.ReadFile(filepath.Join(dir, metadataFileName))
if err != nil {
return nil, errors.Wrapf(err, "failed to read %s file", metadataFileName)
}

if err = json.Unmarshal(raw, &cmetadata); err != nil {
return nil, errors.Wrapf(err, "failed to Unmarshal data from %s file to types.ClusterMetadata", metadataFileName)
}

return cmetadata, err
}
7 changes: 4 additions & 3 deletions pkg/asset/cluster/tfvars.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import (
)

const (
tfvarsFilename = "terraform.tfvars"
// TfVarsFileName is the filename for Terraform variables.
TfVarsFileName = "terraform.tfvars"
tfvarsAssetName = "Terraform Variables"
)

Expand Down Expand Up @@ -62,7 +63,7 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error {
return errors.Wrap(err, "failed to get Tfvars")
}
t.File = &asset.File{
Filename: tfvarsFilename,
Filename: TfVarsFileName,
Data: data,
}

Expand All @@ -79,7 +80,7 @@ func (t *TerraformVariables) Files() []*asset.File {

// Load reads the terraform.tfvars from disk.
func (t *TerraformVariables) Load(f asset.FileFetcher) (found bool, err error) {
file, err := f.FetchByName(tfvarsFilename)
file, err := f.FetchByName(TfVarsFileName)
if err != nil {
if os.IsNotExist(err) {
return false, nil
Expand Down
56 changes: 56 additions & 0 deletions pkg/destroy/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Package bootstrap uses Terraform to remove bootstrap resources.
package bootstrap

import (
"io/ioutil"
"os"
"path/filepath"

"github.com/openshift/installer/pkg/asset/cluster"
"github.com/openshift/installer/pkg/terraform"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)

// Destroy uses Terraform to remove bootstrap resources.
func Destroy(dir string) (err error) {
metadata, err := cluster.LoadMetadata(dir)
if err != nil {
return err
}

platform := metadata.Platform()
if platform == "" {
return errors.New("no platform configured in metadata")
}

tempDir, err := ioutil.TempDir("", "openshift-install-")
if err != nil {
return errors.Wrap(err, "failed to create temporary directory for Terraform execution")
}
defer os.RemoveAll(tempDir)

for _, filename := range []string{terraform.StateFileName, cluster.TfVarsFileName} {
err = copy(filepath.Join(dir, filename), filepath.Join(tempDir, filename))
if err != nil {
return errors.Wrapf(err, "failed to copy %s to the temporary directory", filename)
}
}

logrus.Infof("Using Terraform to destroy bootstrap resources...")
err = terraform.Destroy(tempDir, platform, "-target=module.bootstrap")
if err != nil {
err = errors.Wrap(err, "failed to run terraform")
}

return os.Rename(filepath.Join(dir, terraform.StateFileName), filepath.Join(tempDir, terraform.StateFileName))
}

func copy(from string, to string) error {
data, err := ioutil.ReadFile(from)
if err != nil {
return err
}

return ioutil.WriteFile(to, data, 0666)
}
20 changes: 5 additions & 15 deletions pkg/destroy/destroyer.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package destroy

import (
"encoding/json"
"io/ioutil"
"path/filepath"

"github.com/pkg/errors"
"github.com/sirupsen/logrus"

Expand All @@ -26,25 +22,19 @@ var Registry = make(map[string]NewFunc)

// New returns a Destroyer based on `metadata.json` in `rootDir`.
func New(logger logrus.FieldLogger, rootDir string) (Destroyer, error) {
path := filepath.Join(rootDir, cluster.MetadataFilename)
raw, err := ioutil.ReadFile(filepath.Join(rootDir, cluster.MetadataFilename))
metadata, err := cluster.LoadMetadata(rootDir)
if err != nil {
return nil, errors.Wrapf(err, "failed to read %s file", cluster.MetadataFilename)
}

var cmetadata *types.ClusterMetadata
if err := json.Unmarshal(raw, &cmetadata); err != nil {
return nil, errors.Wrapf(err, "failed to Unmarshal data from %s file to types.ClusterMetadata", cluster.MetadataFilename)
return nil, err
}

platform := cmetadata.Platform()
platform := metadata.Platform()
if platform == "" {
return nil, errors.Errorf("no platform configured in %q", path)
return nil, errors.New("no platform configured in metadata")
}

creator, ok := Registry[platform]
if !ok {
return nil, errors.Errorf("no destroyers registered for %q", platform)
}
return creator(logger, cmetadata)
return creator(logger, metadata)
}
Loading