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  }