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  }