github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/core/description/application_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package description 5 6 import ( 7 jc "github.com/juju/testing/checkers" 8 gc "gopkg.in/check.v1" 9 "gopkg.in/juju/names.v2" 10 "gopkg.in/yaml.v2" 11 ) 12 13 type ApplicationSerializationSuite struct { 14 SliceSerializationSuite 15 StatusHistoryMixinSuite 16 } 17 18 var _ = gc.Suite(&ApplicationSerializationSuite{}) 19 20 func (s *ApplicationSerializationSuite) SetUpTest(c *gc.C) { 21 s.SliceSerializationSuite.SetUpTest(c) 22 s.importName = "applications" 23 s.sliceName = "applications" 24 s.importFunc = func(m map[string]interface{}) (interface{}, error) { 25 return importApplications(m) 26 } 27 s.testFields = func(m map[string]interface{}) { 28 m["applications"] = []interface{}{} 29 } 30 s.StatusHistoryMixinSuite.creator = func() HasStatusHistory { 31 return minimalApplication() 32 } 33 s.StatusHistoryMixinSuite.serializer = func(c *gc.C, initial interface{}) HasStatusHistory { 34 return s.exportImport(c, initial.(*application)) 35 } 36 } 37 38 func minimalApplicationMap() map[interface{}]interface{} { 39 return map[interface{}]interface{}{ 40 "name": "ubuntu", 41 "series": "trusty", 42 "charm-url": "cs:trusty/ubuntu", 43 "cs-channel": "stable", 44 "charm-mod-version": 1, 45 "status": minimalStatusMap(), 46 "status-history": emptyStatusHistoryMap(), 47 "settings": map[interface{}]interface{}{ 48 "key": "value", 49 }, 50 "leader": "ubuntu/0", 51 "leadership-settings": map[interface{}]interface{}{ 52 "leader": true, 53 }, 54 "metrics-creds": "c2Vrcml0", // base64 encoded 55 "units": map[interface{}]interface{}{ 56 "version": 1, 57 "units": []interface{}{ 58 minimalUnitMap(), 59 }, 60 }, 61 } 62 } 63 64 func minimalApplication(args ...ApplicationArgs) *application { 65 if len(args) == 0 { 66 args = []ApplicationArgs{minimalApplicationArgs()} 67 } 68 s := newApplication(args[0]) 69 s.SetStatus(minimalStatusArgs()) 70 u := s.AddUnit(minimalUnitArgs()) 71 u.SetAgentStatus(minimalStatusArgs()) 72 u.SetWorkloadStatus(minimalStatusArgs()) 73 u.SetTools(minimalAgentToolsArgs()) 74 return s 75 } 76 77 func addMinimalApplication(model Model) { 78 s := model.AddApplication(minimalApplicationArgs()) 79 s.SetStatus(minimalStatusArgs()) 80 u := s.AddUnit(minimalUnitArgs()) 81 u.SetAgentStatus(minimalStatusArgs()) 82 u.SetWorkloadStatus(minimalStatusArgs()) 83 u.SetTools(minimalAgentToolsArgs()) 84 } 85 86 func minimalApplicationArgs() ApplicationArgs { 87 return ApplicationArgs{ 88 Tag: names.NewApplicationTag("ubuntu"), 89 Series: "trusty", 90 CharmURL: "cs:trusty/ubuntu", 91 Channel: "stable", 92 CharmModifiedVersion: 1, 93 Settings: map[string]interface{}{ 94 "key": "value", 95 }, 96 Leader: "ubuntu/0", 97 LeadershipSettings: map[string]interface{}{ 98 "leader": true, 99 }, 100 MetricsCredentials: []byte("sekrit"), 101 } 102 } 103 104 func (s *ApplicationSerializationSuite) TestNewApplication(c *gc.C) { 105 args := ApplicationArgs{ 106 Tag: names.NewApplicationTag("magic"), 107 Series: "zesty", 108 Subordinate: true, 109 CharmURL: "cs:zesty/magic", 110 Channel: "stable", 111 CharmModifiedVersion: 1, 112 ForceCharm: true, 113 Exposed: true, 114 MinUnits: 42, // no judgement is made by the migration code 115 Settings: map[string]interface{}{ 116 "key": "value", 117 }, 118 Leader: "magic/1", 119 LeadershipSettings: map[string]interface{}{ 120 "leader": true, 121 }, 122 MetricsCredentials: []byte("sekrit"), 123 } 124 application := newApplication(args) 125 126 c.Assert(application.Name(), gc.Equals, "magic") 127 c.Assert(application.Tag(), gc.Equals, names.NewApplicationTag("magic")) 128 c.Assert(application.Series(), gc.Equals, "zesty") 129 c.Assert(application.Subordinate(), jc.IsTrue) 130 c.Assert(application.CharmURL(), gc.Equals, "cs:zesty/magic") 131 c.Assert(application.Channel(), gc.Equals, "stable") 132 c.Assert(application.CharmModifiedVersion(), gc.Equals, 1) 133 c.Assert(application.ForceCharm(), jc.IsTrue) 134 c.Assert(application.Exposed(), jc.IsTrue) 135 c.Assert(application.MinUnits(), gc.Equals, 42) 136 c.Assert(application.Settings(), jc.DeepEquals, args.Settings) 137 c.Assert(application.Leader(), gc.Equals, "magic/1") 138 c.Assert(application.LeadershipSettings(), jc.DeepEquals, args.LeadershipSettings) 139 c.Assert(application.MetricsCredentials(), jc.DeepEquals, []byte("sekrit")) 140 } 141 142 func (s *ApplicationSerializationSuite) TestMinimalApplicationValid(c *gc.C) { 143 application := minimalApplication() 144 c.Assert(application.Validate(), jc.ErrorIsNil) 145 } 146 147 func (s *ApplicationSerializationSuite) TestMinimalMatches(c *gc.C) { 148 bytes, err := yaml.Marshal(minimalApplication()) 149 c.Assert(err, jc.ErrorIsNil) 150 151 var source map[interface{}]interface{} 152 err = yaml.Unmarshal(bytes, &source) 153 c.Assert(err, jc.ErrorIsNil) 154 c.Assert(source, jc.DeepEquals, minimalApplicationMap()) 155 } 156 157 func (s *ApplicationSerializationSuite) exportImport(c *gc.C, application_ *application) *application { 158 initial := applications{ 159 Version: 1, 160 Applications_: []*application{application_}, 161 } 162 163 bytes, err := yaml.Marshal(initial) 164 c.Assert(err, jc.ErrorIsNil) 165 166 var source map[string]interface{} 167 err = yaml.Unmarshal(bytes, &source) 168 c.Assert(err, jc.ErrorIsNil) 169 170 applications, err := importApplications(source) 171 c.Assert(err, jc.ErrorIsNil) 172 c.Assert(applications, gc.HasLen, 1) 173 return applications[0] 174 } 175 176 func (s *ApplicationSerializationSuite) TestParsingSerializedData(c *gc.C) { 177 svc := minimalApplication() 178 application := s.exportImport(c, svc) 179 c.Assert(application, jc.DeepEquals, svc) 180 } 181 182 func (s *ApplicationSerializationSuite) TestAnnotations(c *gc.C) { 183 initial := minimalApplication() 184 annotations := map[string]string{ 185 "string": "value", 186 "another": "one", 187 } 188 initial.SetAnnotations(annotations) 189 190 application := s.exportImport(c, initial) 191 c.Assert(application.Annotations(), jc.DeepEquals, annotations) 192 } 193 194 func (s *ApplicationSerializationSuite) TestConstraints(c *gc.C) { 195 initial := minimalApplication() 196 args := ConstraintsArgs{ 197 Architecture: "amd64", 198 Memory: 8 * gig, 199 RootDisk: 40 * gig, 200 } 201 initial.SetConstraints(args) 202 203 application := s.exportImport(c, initial) 204 c.Assert(application.Constraints(), jc.DeepEquals, newConstraints(args)) 205 } 206 207 func (s *ApplicationSerializationSuite) TestStorageConstraints(c *gc.C) { 208 args := minimalApplicationArgs() 209 args.StorageConstraints = map[string]StorageConstraintArgs{ 210 "first": {Pool: "first", Size: 1234, Count: 1}, 211 "second": {Pool: "second", Size: 4321, Count: 7}, 212 } 213 initial := minimalApplication(args) 214 215 application := s.exportImport(c, initial) 216 217 constraints := application.StorageConstraints() 218 c.Assert(constraints, gc.HasLen, 2) 219 first, found := constraints["first"] 220 c.Assert(found, jc.IsTrue) 221 c.Check(first.Pool(), gc.Equals, "first") 222 c.Check(first.Size(), gc.Equals, uint64(1234)) 223 c.Check(first.Count(), gc.Equals, uint64(1)) 224 225 second, found := constraints["second"] 226 c.Assert(found, jc.IsTrue) 227 c.Check(second.Pool(), gc.Equals, "second") 228 c.Check(second.Size(), gc.Equals, uint64(4321)) 229 c.Check(second.Count(), gc.Equals, uint64(7)) 230 } 231 232 func (s *ApplicationSerializationSuite) TestLeaderValid(c *gc.C) { 233 args := minimalApplicationArgs() 234 args.Leader = "ubuntu/1" 235 application := newApplication(args) 236 application.SetStatus(minimalStatusArgs()) 237 238 err := application.Validate() 239 c.Assert(err, gc.ErrorMatches, `missing unit for leader "ubuntu/1" not valid`) 240 }