github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/provider/common/state_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 "io/ioutil" 8 "net/http" 9 "net/http/httptest" 10 "os" 11 "path/filepath" 12 13 jc "github.com/juju/testing/checkers" 14 gc "gopkg.in/check.v1" 15 goyaml "gopkg.in/yaml.v2" 16 17 "github.com/juju/juju/environs" 18 "github.com/juju/juju/environs/storage" 19 envtesting "github.com/juju/juju/environs/testing" 20 "github.com/juju/juju/instance" 21 "github.com/juju/juju/provider/common" 22 coretesting "github.com/juju/juju/testing" 23 ) 24 25 type StateSuite struct { 26 coretesting.BaseSuite 27 } 28 29 var _ = gc.Suite(&StateSuite{}) 30 31 func (suite *StateSuite) newStorageWithDataDir(c *gc.C) (storage.Storage, string) { 32 closer, stor, dataDir := envtesting.CreateLocalTestStorage(c) 33 suite.AddCleanup(func(*gc.C) { closer.Close() }) 34 envtesting.UploadFakeTools(c, stor, "released", "released") 35 return stor, dataDir 36 } 37 38 func (suite *StateSuite) newStorage(c *gc.C) storage.Storage { 39 stor, _ := suite.newStorageWithDataDir(c) 40 return stor 41 } 42 43 // testingHTTPSServer creates a tempdir backed https server with internal 44 // self-signed certs that will not be accepted as valid. 45 func (suite *StateSuite) testingHTTPSServer(c *gc.C) (string, string) { 46 dataDir := c.MkDir() 47 mux := http.NewServeMux() 48 mux.Handle("/", http.FileServer(http.Dir(dataDir))) 49 server := httptest.NewTLSServer(mux) 50 suite.AddCleanup(func(*gc.C) { server.Close() }) 51 return server.URL, dataDir 52 } 53 54 func (suite *StateSuite) TestCreateStateFileWritesEmptyStateFile(c *gc.C) { 55 stor := suite.newStorage(c) 56 57 url, err := common.CreateStateFile(stor) 58 c.Assert(err, jc.ErrorIsNil) 59 60 reader, err := storage.Get(stor, common.StateFile) 61 c.Assert(err, jc.ErrorIsNil) 62 data, err := ioutil.ReadAll(reader) 63 c.Assert(err, jc.ErrorIsNil) 64 c.Check(string(data), gc.Equals, "") 65 c.Assert(url, gc.NotNil) 66 expectedURL, err := stor.URL(common.StateFile) 67 c.Assert(err, jc.ErrorIsNil) 68 c.Check(url, gc.Equals, expectedURL) 69 } 70 71 func (suite *StateSuite) TestDeleteStateFile(c *gc.C) { 72 closer, stor, dataDir := envtesting.CreateLocalTestStorage(c) 73 defer closer.Close() 74 75 err := common.DeleteStateFile(stor) 76 c.Assert(err, jc.ErrorIsNil) // doesn't exist, juju don't care 77 78 _, err = common.CreateStateFile(stor) 79 c.Assert(err, jc.ErrorIsNil) 80 _, err = os.Stat(filepath.Join(dataDir, common.StateFile)) 81 c.Assert(err, jc.ErrorIsNil) 82 83 err = common.DeleteStateFile(stor) 84 c.Assert(err, jc.ErrorIsNil) 85 _, err = os.Stat(filepath.Join(dataDir, common.StateFile)) 86 c.Assert(err, jc.Satisfies, os.IsNotExist) 87 } 88 89 func (suite *StateSuite) TestSaveStateWritesStateFile(c *gc.C) { 90 stor := suite.newStorage(c) 91 state := common.BootstrapState{ 92 StateInstances: []instance.Id{instance.Id("an-instance-id")}, 93 } 94 marshaledState, err := goyaml.Marshal(state) 95 c.Assert(err, jc.ErrorIsNil) 96 97 err = common.SaveState(stor, &state) 98 c.Assert(err, jc.ErrorIsNil) 99 100 loadedState, err := storage.Get(stor, common.StateFile) 101 c.Assert(err, jc.ErrorIsNil) 102 content, err := ioutil.ReadAll(loadedState) 103 c.Assert(err, jc.ErrorIsNil) 104 c.Check(content, gc.DeepEquals, marshaledState) 105 } 106 107 func (suite *StateSuite) setUpSavedState(c *gc.C, dataDir string) common.BootstrapState { 108 state := common.BootstrapState{ 109 StateInstances: []instance.Id{instance.Id("an-instance-id")}, 110 } 111 content, err := goyaml.Marshal(state) 112 c.Assert(err, jc.ErrorIsNil) 113 err = ioutil.WriteFile(filepath.Join(dataDir, common.StateFile), []byte(content), 0644) 114 c.Assert(err, jc.ErrorIsNil) 115 return state 116 } 117 118 func (suite *StateSuite) TestLoadStateReadsStateFile(c *gc.C) { 119 storage, dataDir := suite.newStorageWithDataDir(c) 120 state := suite.setUpSavedState(c, dataDir) 121 storedState, err := common.LoadState(storage) 122 c.Assert(err, jc.ErrorIsNil) 123 c.Check(*storedState, gc.DeepEquals, state) 124 } 125 126 func (suite *StateSuite) TestLoadStateMissingFile(c *gc.C) { 127 stor := suite.newStorage(c) 128 _, err := common.LoadState(stor) 129 c.Check(err, gc.Equals, environs.ErrNotBootstrapped) 130 } 131 132 func (suite *StateSuite) TestLoadStateIntegratesWithSaveState(c *gc.C) { 133 storage := suite.newStorage(c) 134 state := common.BootstrapState{ 135 StateInstances: []instance.Id{instance.Id("an-instance-id")}, 136 } 137 err := common.SaveState(storage, &state) 138 c.Assert(err, jc.ErrorIsNil) 139 storedState, err := common.LoadState(storage) 140 c.Assert(err, jc.ErrorIsNil) 141 142 c.Check(*storedState, gc.DeepEquals, state) 143 } 144 145 func (suite *StateSuite) TestAddStateInstance(c *gc.C) { 146 storage := suite.newStorage(c) 147 for _, str := range []string{"a", "b", "c"} { 148 id := instance.Id(str) 149 err := common.AddStateInstance(storage, instance.Id(id)) 150 c.Assert(err, jc.ErrorIsNil) 151 } 152 153 storedState, err := common.LoadState(storage) 154 c.Assert(err, jc.ErrorIsNil) 155 c.Check(storedState, gc.DeepEquals, &common.BootstrapState{ 156 StateInstances: []instance.Id{ 157 instance.Id("a"), 158 instance.Id("b"), 159 instance.Id("c"), 160 }, 161 }) 162 } 163 164 func (suite *StateSuite) TestRemoveStateInstancesPartial(c *gc.C) { 165 storage := suite.newStorage(c) 166 state := common.BootstrapState{ 167 StateInstances: []instance.Id{ 168 instance.Id("a"), 169 instance.Id("b"), 170 instance.Id("c"), 171 }, 172 } 173 err := common.SaveState(storage, &state) 174 c.Assert(err, jc.ErrorIsNil) 175 176 err = common.RemoveStateInstances( 177 storage, 178 state.StateInstances[0], 179 instance.Id("not-there"), 180 state.StateInstances[2], 181 ) 182 c.Assert(err, jc.ErrorIsNil) 183 184 storedState, err := common.LoadState(storage) 185 c.Assert(storedState, gc.DeepEquals, &common.BootstrapState{ 186 StateInstances: []instance.Id{ 187 state.StateInstances[1], 188 }, 189 }) 190 } 191 192 func (suite *StateSuite) TestRemoveStateInstancesNone(c *gc.C) { 193 storage := suite.newStorage(c) 194 state := common.BootstrapState{ 195 StateInstances: []instance.Id{instance.Id("an-instance-id")}, 196 } 197 err := common.SaveState(storage, &state) 198 c.Assert(err, jc.ErrorIsNil) 199 200 err = common.RemoveStateInstances( 201 storage, 202 instance.Id("not-there"), 203 ) 204 c.Assert(err, jc.ErrorIsNil) 205 206 storedState, err := common.LoadState(storage) 207 c.Assert(storedState, gc.DeepEquals, &state) 208 } 209 210 func (suite *StateSuite) TestRemoveStateInstancesNoProviderState(c *gc.C) { 211 storage := suite.newStorage(c) 212 err := common.RemoveStateInstances(storage, instance.Id("id")) 213 // No error if the id is missing, so no error if the entire 214 // provider-state file is missing. This is the case if 215 // bootstrap failed. 216 c.Assert(err, jc.ErrorIsNil) 217 }