github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/annotations_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "github.com/juju/errors" 8 jc "github.com/juju/testing/checkers" 9 "github.com/juju/utils" 10 gc "gopkg.in/check.v1" 11 "gopkg.in/juju/names.v2" 12 13 "github.com/juju/juju/state" 14 "github.com/juju/juju/storage" 15 "github.com/juju/juju/testing" 16 ) 17 18 type AnnotationsSuite struct { 19 ConnSuite 20 // any entity that implements 21 // state.GlobalEntity will do 22 testEntity *state.Machine 23 } 24 25 var _ = gc.Suite(&AnnotationsSuite{}) 26 27 func (s *AnnotationsSuite) SetUpTest(c *gc.C) { 28 s.ConnSuite.SetUpTest(c) 29 30 var err error 31 s.testEntity, err = s.State.AddMachine("quantal", state.JobHostUnits) 32 c.Assert(err, jc.ErrorIsNil) 33 } 34 35 func (s *AnnotationsSuite) TestSetAnnotationsInvalidKey(c *gc.C) { 36 key := "tes.tkey" 37 expected := "typo" 38 err := s.setAnnotationResult(c, key, expected) 39 c.Assert(errors.Cause(err), gc.ErrorMatches, ".*invalid key.*") 40 } 41 42 func (s *AnnotationsSuite) TestSetAnnotationsCreate(c *gc.C) { 43 s.createTestAnnotation(c) 44 } 45 46 func (s *AnnotationsSuite) createTestAnnotation(c *gc.C) string { 47 key := "testkey" 48 expected := "typo" 49 s.assertSetAnnotation(c, key, expected) 50 assertAnnotation(c, s.State, s.testEntity, key, expected) 51 return key 52 } 53 54 func (s *AnnotationsSuite) setAnnotationResult(c *gc.C, key, value string) error { 55 annts := map[string]string{key: value} 56 return s.State.SetAnnotations(s.testEntity, annts) 57 } 58 59 func (s *AnnotationsSuite) assertSetAnnotation(c *gc.C, key, value string) { 60 err := s.setAnnotationResult(c, key, value) 61 c.Assert(err, jc.ErrorIsNil) 62 } 63 64 func assertAnnotation(c *gc.C, st *state.State, entity state.GlobalEntity, key, expected string) { 65 value, err := st.Annotation(entity, key) 66 c.Assert(err, jc.ErrorIsNil) 67 c.Assert(value, gc.DeepEquals, expected) 68 } 69 70 func (s *AnnotationsSuite) TestSetAnnotationsUpdate(c *gc.C) { 71 key := s.createTestAnnotation(c) 72 updated := "fixed" 73 74 s.assertSetAnnotation(c, key, updated) 75 assertAnnotation(c, s.State, s.testEntity, key, updated) 76 } 77 78 func (s *AnnotationsSuite) TestSetAnnotationsRemove(c *gc.C) { 79 key := s.createTestAnnotation(c) 80 updated := "" 81 s.assertSetAnnotation(c, key, updated) 82 assertAnnotation(c, s.State, s.testEntity, key, updated) 83 84 annts, err := s.State.Annotations(s.testEntity) 85 c.Assert(err, jc.ErrorIsNil) 86 87 // we are expecting not to find this key... 88 for akey := range annts { 89 c.Assert(akey == key, jc.IsFalse) 90 } 91 } 92 93 func (s *AnnotationsSuite) TestSetAnnotationsDestroyedEntity(c *gc.C) { 94 key := s.createTestAnnotation(c) 95 96 err := s.testEntity.ForceDestroy() 97 c.Assert(err, jc.ErrorIsNil) 98 err = s.testEntity.EnsureDead() 99 c.Assert(err, jc.ErrorIsNil) 100 err = s.testEntity.Remove() 101 c.Assert(err, jc.ErrorIsNil) 102 _, err = s.State.Machine(s.testEntity.Id()) 103 c.Assert(errors.Cause(err), gc.ErrorMatches, ".*not found.*") 104 105 annts, err := s.State.Annotations(s.testEntity) 106 c.Assert(err, jc.ErrorIsNil) 107 c.Assert(annts, gc.DeepEquals, map[string]string{}) 108 109 annts[key] = "oops" 110 err = s.State.SetAnnotations(s.testEntity, annts) 111 c.Assert(errors.Cause(err), gc.ErrorMatches, ".*no longer exists.*") 112 c.Assert(err, gc.ErrorMatches, ".*cannot update annotations.*") 113 } 114 115 func (s *AnnotationsSuite) TestSetAnnotationsNonExistentEntity(c *gc.C) { 116 annts := map[string]string{"key": "oops"} 117 err := s.State.SetAnnotations(state.MockGlobalEntity{}, annts) 118 119 c.Assert(errors.Cause(err), gc.ErrorMatches, ".*no longer exists.*") 120 c.Assert(err, gc.ErrorMatches, ".*cannot update annotations.*") 121 } 122 123 func (s *AnnotationsSuite) TestSetAnnotationsConcurrently(c *gc.C) { 124 key := "conkey" 125 first := "alpha" 126 last := "omega" 127 128 setAnnotations := func() { 129 s.assertSetAnnotation(c, key, first) 130 assertAnnotation(c, s.State, s.testEntity, key, first) 131 } 132 defer state.SetBeforeHooks(c, s.State, setAnnotations).Check() 133 s.assertSetAnnotation(c, key, last) 134 assertAnnotation(c, s.State, s.testEntity, key, last) 135 } 136 137 type AnnotationsEnvSuite struct { 138 ConnSuite 139 } 140 141 var _ = gc.Suite(&AnnotationsEnvSuite{}) 142 143 func (s *AnnotationsEnvSuite) SetUpTest(c *gc.C) { 144 s.ConnSuite.SetUpTest(c) 145 s.ConnSuite.PatchValue(&state.TagToCollectionAndId, func(st *state.State, tag names.Tag) (string, interface{}, error) { 146 return "", nil, errors.Errorf("this error should not be reached with current implementation %v", tag) 147 }) 148 } 149 150 func (s *AnnotationsEnvSuite) TestSetAnnotationsDestroyedEnvironment(c *gc.C) { 151 env, st := s.createTestEnv(c) 152 defer st.Close() 153 154 key := "key" 155 expected := "oops" 156 annts := map[string]string{key: expected} 157 err := st.SetAnnotations(env, annts) 158 c.Assert(err, jc.ErrorIsNil) 159 assertAnnotation(c, st, env, key, expected) 160 161 err = env.Destroy() 162 c.Assert(err, jc.ErrorIsNil) 163 err = st.RemoveAllModelDocs() 164 c.Assert(err, jc.ErrorIsNil) 165 err = st.Close() 166 c.Assert(err, jc.ErrorIsNil) 167 168 expected = "fail" 169 annts[key] = expected 170 err = s.State.SetAnnotations(env, annts) 171 c.Assert(errors.Cause(err), gc.ErrorMatches, ".*model not found.*") 172 c.Assert(err, gc.ErrorMatches, ".*cannot update annotations.*") 173 } 174 175 func (s *AnnotationsEnvSuite) createTestEnv(c *gc.C) (*state.Model, *state.State) { 176 uuid, err := utils.NewUUID() 177 c.Assert(err, jc.ErrorIsNil) 178 cfg := testing.CustomModelConfig(c, testing.Attrs{ 179 "name": "testing", 180 "uuid": uuid.String(), 181 }) 182 owner := names.NewUserTag("test@remote") 183 env, st, err := s.State.NewModel(state.ModelArgs{ 184 CloudName: "dummy", CloudRegion: "dummy-region", Config: cfg, Owner: owner, 185 StorageProviderRegistry: storage.StaticProviderRegistry{}, 186 }) 187 c.Assert(err, jc.ErrorIsNil) 188 return env, st 189 }