github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/provider/common/destroy_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common_test
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"strings"
    10  
    11  	gitjujutesting "github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/environs"
    16  	"github.com/juju/juju/instance"
    17  	"github.com/juju/juju/provider/common"
    18  	"github.com/juju/juju/storage"
    19  	"github.com/juju/juju/storage/provider/dummy"
    20  	"github.com/juju/juju/testing"
    21  	jujuversion "github.com/juju/juju/version"
    22  )
    23  
    24  type DestroySuite struct {
    25  	testing.BaseSuite
    26  }
    27  
    28  var _ = gc.Suite(&DestroySuite{})
    29  
    30  func (s *DestroySuite) TestCannotGetInstances(c *gc.C) {
    31  	env := &mockEnviron{
    32  		allInstances: func() ([]instance.Instance, error) {
    33  			return nil, fmt.Errorf("nope")
    34  		},
    35  		config: configGetter(c),
    36  	}
    37  	err := common.Destroy(env)
    38  	c.Assert(err, gc.ErrorMatches, "destroying instances: nope")
    39  }
    40  
    41  func (s *DestroySuite) TestCannotStopInstances(c *gc.C) {
    42  	env := &mockEnviron{
    43  		allInstances: func() ([]instance.Instance, error) {
    44  			return []instance.Instance{
    45  				&mockInstance{id: "one"},
    46  				&mockInstance{id: "another"},
    47  			}, nil
    48  		},
    49  		stopInstances: func(ids []instance.Id) error {
    50  			c.Assert(ids, gc.HasLen, 2)
    51  			c.Assert(ids[0], gc.Equals, instance.Id("one"))
    52  			c.Assert(ids[1], gc.Equals, instance.Id("another"))
    53  			return fmt.Errorf("nah")
    54  		},
    55  		config: configGetter(c),
    56  	}
    57  	err := common.Destroy(env)
    58  	c.Assert(err, gc.ErrorMatches, "destroying instances: nah")
    59  }
    60  
    61  func (s *DestroySuite) TestSuccessWhenStorageErrors(c *gc.C) {
    62  	// common.Destroy doesn't touch provider/object storage anymore,
    63  	// so failing storage should not affect success.
    64  	env := &mockEnviron{
    65  		storage: &mockStorage{removeAllErr: fmt.Errorf("noes!")},
    66  		allInstances: func() ([]instance.Instance, error) {
    67  			return []instance.Instance{
    68  				&mockInstance{id: "one"},
    69  				&mockInstance{id: "another"},
    70  			}, nil
    71  		},
    72  		stopInstances: func(ids []instance.Id) error {
    73  			c.Assert(ids, gc.HasLen, 2)
    74  			c.Assert(ids[0], gc.Equals, instance.Id("one"))
    75  			c.Assert(ids[1], gc.Equals, instance.Id("another"))
    76  			return nil
    77  		},
    78  		config: configGetter(c),
    79  	}
    80  	err := common.Destroy(env)
    81  	c.Assert(err, jc.ErrorIsNil)
    82  }
    83  
    84  func (s *DestroySuite) TestSuccess(c *gc.C) {
    85  	s.PatchValue(&jujuversion.Current, testing.FakeVersionNumber)
    86  	stor := newStorage(s, c)
    87  	err := stor.Put("somewhere", strings.NewReader("stuff"), 5)
    88  	c.Assert(err, jc.ErrorIsNil)
    89  
    90  	env := &mockEnviron{
    91  		storage: stor,
    92  		allInstances: func() ([]instance.Instance, error) {
    93  			return []instance.Instance{
    94  				&mockInstance{id: "one"},
    95  			}, nil
    96  		},
    97  		stopInstances: func(ids []instance.Id) error {
    98  			c.Assert(ids, gc.HasLen, 1)
    99  			c.Assert(ids[0], gc.Equals, instance.Id("one"))
   100  			return nil
   101  		},
   102  		config: configGetter(c),
   103  	}
   104  	err = common.Destroy(env)
   105  	c.Assert(err, jc.ErrorIsNil)
   106  
   107  	// common.Destroy doesn't touch provider/object storage anymore.
   108  	r, err := stor.Get("somewhere")
   109  	c.Assert(err, jc.ErrorIsNil)
   110  	r.Close()
   111  }
   112  
   113  func (s *DestroySuite) TestSuccessWhenNoInstances(c *gc.C) {
   114  	s.PatchValue(&jujuversion.Current, testing.FakeVersionNumber)
   115  	stor := newStorage(s, c)
   116  	err := stor.Put("elsewhere", strings.NewReader("stuff"), 5)
   117  	c.Assert(err, jc.ErrorIsNil)
   118  
   119  	env := &mockEnviron{
   120  		storage: stor,
   121  		allInstances: func() ([]instance.Instance, error) {
   122  			return nil, environs.ErrNoInstances
   123  		},
   124  		config: configGetter(c),
   125  	}
   126  	err = common.Destroy(env)
   127  	c.Assert(err, jc.ErrorIsNil)
   128  }
   129  
   130  func (s *DestroySuite) TestDestroyEnvScopedVolumes(c *gc.C) {
   131  	volumeSource := &dummy.VolumeSource{
   132  		ListVolumesFunc: func() ([]string, error) {
   133  			return []string{"vol-0", "vol-1", "vol-2"}, nil
   134  		},
   135  		DestroyVolumesFunc: func(ids []string) ([]error, error) {
   136  			return make([]error, len(ids)), nil
   137  		},
   138  	}
   139  	storageProvider := &dummy.StorageProvider{
   140  		IsDynamic:    true,
   141  		StorageScope: storage.ScopeEnviron,
   142  		VolumeSourceFunc: func(*storage.Config) (storage.VolumeSource, error) {
   143  			return volumeSource, nil
   144  		},
   145  	}
   146  
   147  	env := &mockEnviron{
   148  		config: configGetter(c),
   149  		allInstances: func() ([]instance.Instance, error) {
   150  			return nil, environs.ErrNoInstances
   151  		},
   152  		storageProviders: storage.StaticProviderRegistry{
   153  			map[storage.ProviderType]storage.Provider{
   154  				"environ": storageProvider,
   155  			},
   156  		},
   157  	}
   158  	err := common.Destroy(env)
   159  	c.Assert(err, jc.ErrorIsNil)
   160  
   161  	// common.Destroy will ignore machine-scoped storage providers.
   162  	storageProvider.CheckCallNames(c, "Dynamic", "Scope", "Supports", "VolumeSource")
   163  	volumeSource.CheckCalls(c, []gitjujutesting.StubCall{
   164  		{"ListVolumes", nil},
   165  		{"DestroyVolumes", []interface{}{[]string{"vol-0", "vol-1", "vol-2"}}},
   166  	})
   167  }
   168  
   169  func (s *DestroySuite) TestDestroyVolumeErrors(c *gc.C) {
   170  	volumeSource := &dummy.VolumeSource{
   171  		ListVolumesFunc: func() ([]string, error) {
   172  			return []string{"vol-0", "vol-1", "vol-2"}, nil
   173  		},
   174  		DestroyVolumesFunc: func(ids []string) ([]error, error) {
   175  			return []error{
   176  				nil,
   177  				errors.New("cannot destroy vol-1"),
   178  				errors.New("cannot destroy vol-2"),
   179  			}, nil
   180  		},
   181  	}
   182  
   183  	storageProvider := &dummy.StorageProvider{
   184  		IsDynamic:    true,
   185  		StorageScope: storage.ScopeEnviron,
   186  		VolumeSourceFunc: func(*storage.Config) (storage.VolumeSource, error) {
   187  			return volumeSource, nil
   188  		},
   189  	}
   190  
   191  	env := &mockEnviron{
   192  		config: configGetter(c),
   193  		allInstances: func() ([]instance.Instance, error) {
   194  			return nil, environs.ErrNoInstances
   195  		},
   196  		storageProviders: storage.StaticProviderRegistry{
   197  			map[storage.ProviderType]storage.Provider{
   198  				"environ": storageProvider,
   199  			},
   200  		},
   201  	}
   202  	err := common.Destroy(env)
   203  	c.Assert(err, gc.ErrorMatches, "destroying storage: destroying volumes: cannot destroy vol-1, cannot destroy vol-2")
   204  }
   205  
   206  func (s *DestroySuite) TestIgnoreStaticVolumes(c *gc.C) {
   207  	staticProvider := &dummy.StorageProvider{
   208  		IsDynamic:    false,
   209  		StorageScope: storage.ScopeEnviron,
   210  	}
   211  
   212  	env := &mockEnviron{
   213  		config: configGetter(c),
   214  		allInstances: func() ([]instance.Instance, error) {
   215  			return nil, environs.ErrNoInstances
   216  		},
   217  		storageProviders: storage.StaticProviderRegistry{
   218  			map[storage.ProviderType]storage.Provider{
   219  				"static": staticProvider,
   220  			},
   221  		},
   222  	}
   223  	err := common.Destroy(env)
   224  	c.Assert(err, jc.ErrorIsNil)
   225  
   226  	// common.Destroy will ignore static storage providers.
   227  	staticProvider.CheckCallNames(c, "Dynamic")
   228  }
   229  
   230  func (s *DestroySuite) TestIgnoreMachineScopedVolumes(c *gc.C) {
   231  	staticProvider := &dummy.StorageProvider{
   232  		IsDynamic:    true,
   233  		StorageScope: storage.ScopeMachine,
   234  	}
   235  
   236  	env := &mockEnviron{
   237  		config: configGetter(c),
   238  		allInstances: func() ([]instance.Instance, error) {
   239  			return nil, environs.ErrNoInstances
   240  		},
   241  		storageProviders: storage.StaticProviderRegistry{
   242  			map[storage.ProviderType]storage.Provider{
   243  				"static": staticProvider,
   244  			},
   245  		},
   246  	}
   247  	err := common.Destroy(env)
   248  	c.Assert(err, jc.ErrorIsNil)
   249  
   250  	// common.Destroy will ignore machine-scoped storage providers.
   251  	staticProvider.CheckCallNames(c, "Dynamic", "Scope")
   252  }
   253  
   254  func (s *DestroySuite) TestIgnoreNoVolumeSupport(c *gc.C) {
   255  	staticProvider := &dummy.StorageProvider{
   256  		IsDynamic:    true,
   257  		StorageScope: storage.ScopeEnviron,
   258  		SupportsFunc: func(storage.StorageKind) bool {
   259  			return false
   260  		},
   261  	}
   262  
   263  	env := &mockEnviron{
   264  		config: configGetter(c),
   265  		allInstances: func() ([]instance.Instance, error) {
   266  			return nil, environs.ErrNoInstances
   267  		},
   268  		storageProviders: storage.StaticProviderRegistry{
   269  			map[storage.ProviderType]storage.Provider{
   270  				"static": staticProvider,
   271  			},
   272  		},
   273  	}
   274  	err := common.Destroy(env)
   275  	c.Assert(err, jc.ErrorIsNil)
   276  
   277  	// common.Destroy will ignore storage providers that don't support
   278  	// volumes (until we have persistent filesystems, that is).
   279  	staticProvider.CheckCallNames(c, "Dynamic", "Scope", "Supports")
   280  }