github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/api/caasunitprovisioner/client_test.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package caasunitprovisioner_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/testing"
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  	"gopkg.in/juju/names.v2"
    12  
    13  	basetesting "github.com/juju/juju/api/base/testing"
    14  	"github.com/juju/juju/api/caasunitprovisioner"
    15  	"github.com/juju/juju/apiserver/params"
    16  	"github.com/juju/juju/core/application"
    17  	"github.com/juju/juju/core/constraints"
    18  	"github.com/juju/juju/core/devices"
    19  	"github.com/juju/juju/core/life"
    20  	"github.com/juju/juju/core/status"
    21  	"github.com/juju/juju/storage"
    22  )
    23  
    24  type unitprovisionerSuite struct {
    25  	testing.IsolationSuite
    26  }
    27  
    28  var _ = gc.Suite(&unitprovisionerSuite{})
    29  
    30  func newClient(f basetesting.APICallerFunc) *caasunitprovisioner.Client {
    31  	return caasunitprovisioner.NewClient(basetesting.BestVersionCaller{f, 1})
    32  }
    33  
    34  func (s *unitprovisionerSuite) TestProvisioningInfo(c *gc.C) {
    35  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
    36  		c.Check(objType, gc.Equals, "CAASUnitProvisioner")
    37  		c.Check(version, gc.Equals, 0)
    38  		c.Check(id, gc.Equals, "")
    39  		c.Check(request, gc.Equals, "ProvisioningInfo")
    40  		c.Check(arg, jc.DeepEquals, params.Entities{
    41  			Entities: []params.Entity{{
    42  				Tag: "application-gitlab",
    43  			}},
    44  		})
    45  		c.Assert(result, gc.FitsTypeOf, &params.KubernetesProvisioningInfoResults{})
    46  		*(result.(*params.KubernetesProvisioningInfoResults)) = params.KubernetesProvisioningInfoResults{
    47  			Results: []params.KubernetesProvisioningInfoResult{{
    48  				Result: &params.KubernetesProvisioningInfo{
    49  					PodSpec:     "foo",
    50  					Tags:        map[string]string{"foo": "bar"},
    51  					Placement:   "a=b,c=d",
    52  					Constraints: constraints.MustParse("mem=4G"),
    53  					Filesystems: []params.KubernetesFilesystemParams{{
    54  						StorageName: "database",
    55  						Size:        uint64(100),
    56  						Provider:    "k8s",
    57  						Tags:        map[string]string{"tag": "resource"},
    58  						Attributes:  map[string]interface{}{"key": "value"},
    59  						Attachment: &params.KubernetesFilesystemAttachmentParams{
    60  							Provider:   "k8s",
    61  							MountPoint: "/path/to/here",
    62  							ReadOnly:   true,
    63  						}},
    64  					},
    65  					Devices: []params.KubernetesDeviceParams{
    66  						{
    67  							Type:       "nvidia.com/gpu",
    68  							Count:      3,
    69  							Attributes: map[string]string{"gpu": "nvidia-tesla-p100"},
    70  						},
    71  					},
    72  				},
    73  			}},
    74  		}
    75  		return nil
    76  	})
    77  
    78  	client := caasunitprovisioner.NewClient(apiCaller)
    79  	info, err := client.ProvisioningInfo("gitlab")
    80  	c.Assert(err, jc.ErrorIsNil)
    81  	c.Assert(info, jc.DeepEquals, &caasunitprovisioner.ProvisioningInfo{
    82  		PodSpec:     "foo",
    83  		Tags:        map[string]string{"foo": "bar"},
    84  		Placement:   "a=b,c=d",
    85  		Constraints: constraints.MustParse("mem=4G"),
    86  		Filesystems: []storage.KubernetesFilesystemParams{{
    87  			StorageName:  "database",
    88  			Size:         uint64(100),
    89  			Provider:     storage.ProviderType("k8s"),
    90  			ResourceTags: map[string]string{"tag": "resource"},
    91  			Attributes:   map[string]interface{}{"key": "value"},
    92  			Attachment: &storage.KubernetesFilesystemAttachmentParams{
    93  				Path: "/path/to/here",
    94  				AttachmentParams: storage.AttachmentParams{
    95  					Provider: storage.ProviderType("k8s"),
    96  					ReadOnly: true,
    97  				},
    98  			},
    99  		}},
   100  		Devices: []devices.KubernetesDeviceParams{{
   101  			Type:       devices.DeviceType("nvidia.com/gpu"),
   102  			Count:      3,
   103  			Attributes: map[string]string{"gpu": "nvidia-tesla-p100"},
   104  		}},
   105  	})
   106  }
   107  
   108  func (s *unitprovisionerSuite) TestProvisioningInfoError(c *gc.C) {
   109  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   110  		*(result.(*params.KubernetesProvisioningInfoResults)) = params.KubernetesProvisioningInfoResults{
   111  			Results: []params.KubernetesProvisioningInfoResult{{Error: &params.Error{
   112  				Code:    params.CodeNotFound,
   113  				Message: "bletch",
   114  			}}},
   115  		}
   116  		return nil
   117  	})
   118  
   119  	client := caasunitprovisioner.NewClient(apiCaller)
   120  	_, err := client.ProvisioningInfo("gitlab")
   121  	c.Assert(err, gc.ErrorMatches, "bletch")
   122  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   123  }
   124  
   125  func (s *unitprovisionerSuite) TestProvisioningInfoNoUnits(c *gc.C) {
   126  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   127  		*(result.(*params.KubernetesProvisioningInfoResults)) = params.KubernetesProvisioningInfoResults{
   128  			Results: []params.KubernetesProvisioningInfoResult{{}},
   129  		}
   130  		return nil
   131  	})
   132  
   133  	client := caasunitprovisioner.NewClient(apiCaller)
   134  	_, err := client.ProvisioningInfo("gitlab")
   135  	c.Assert(err, jc.DeepEquals, caasunitprovisioner.ErrNoUnits)
   136  }
   137  
   138  func (s *unitprovisionerSuite) TestProvisioningInfoInvalidApplicationName(c *gc.C) {
   139  	client := caasunitprovisioner.NewClient(basetesting.APICallerFunc(func(_ string, _ int, _, _ string, _, _ interface{}) error {
   140  		return errors.New("should not be called")
   141  	}))
   142  	_, err := client.ProvisioningInfo("gitlab/0")
   143  	c.Assert(err, gc.ErrorMatches, `application name "gitlab/0" not valid`)
   144  }
   145  
   146  func (s *unitprovisionerSuite) TestLife(c *gc.C) {
   147  	s.testLife(c, names.NewApplicationTag("gitlab"))
   148  	s.testLife(c, names.NewUnitTag("gitlab/0"))
   149  }
   150  
   151  func (s *unitprovisionerSuite) testLife(c *gc.C, tag names.Tag) {
   152  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   153  		c.Check(objType, gc.Equals, "CAASUnitProvisioner")
   154  		c.Check(version, gc.Equals, 0)
   155  		c.Check(id, gc.Equals, "")
   156  		c.Check(request, gc.Equals, "Life")
   157  		c.Check(arg, jc.DeepEquals, params.Entities{
   158  			Entities: []params.Entity{{
   159  				Tag: tag.String(),
   160  			}},
   161  		})
   162  		c.Assert(result, gc.FitsTypeOf, &params.LifeResults{})
   163  		*(result.(*params.LifeResults)) = params.LifeResults{
   164  			Results: []params.LifeResult{{
   165  				Life: params.Alive,
   166  			}},
   167  		}
   168  		return nil
   169  	})
   170  
   171  	client := caasunitprovisioner.NewClient(apiCaller)
   172  	lifeValue, err := client.Life(tag.Id())
   173  	c.Assert(err, jc.ErrorIsNil)
   174  	c.Assert(lifeValue, gc.Equals, life.Alive)
   175  }
   176  
   177  func (s *unitprovisionerSuite) TestLifeError(c *gc.C) {
   178  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   179  		*(result.(*params.LifeResults)) = params.LifeResults{
   180  			Results: []params.LifeResult{{Error: &params.Error{
   181  				Code:    params.CodeNotFound,
   182  				Message: "bletch",
   183  			}}},
   184  		}
   185  		return nil
   186  	})
   187  
   188  	client := caasunitprovisioner.NewClient(apiCaller)
   189  	_, err := client.Life("gitlab/0")
   190  	c.Assert(err, gc.ErrorMatches, "bletch")
   191  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   192  }
   193  
   194  func (s *unitprovisionerSuite) TestLifeInvalidEntityame(c *gc.C) {
   195  	client := caasunitprovisioner.NewClient(basetesting.APICallerFunc(func(_ string, _ int, _, _ string, _, _ interface{}) error {
   196  		return errors.New("should not be called")
   197  	}))
   198  	_, err := client.Life("")
   199  	c.Assert(err, gc.ErrorMatches, `application or unit name "" not valid`)
   200  }
   201  
   202  func (s *unitprovisionerSuite) TestWatchApplications(c *gc.C) {
   203  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   204  		c.Check(objType, gc.Equals, "CAASUnitProvisioner")
   205  		c.Check(version, gc.Equals, 0)
   206  		c.Check(id, gc.Equals, "")
   207  		c.Check(request, gc.Equals, "WatchApplications")
   208  		c.Assert(result, gc.FitsTypeOf, &params.StringsWatchResult{})
   209  		*(result.(*params.StringsWatchResult)) = params.StringsWatchResult{
   210  			Error: &params.Error{Message: "FAIL"},
   211  		}
   212  		return nil
   213  	})
   214  
   215  	client := caasunitprovisioner.NewClient(apiCaller)
   216  	watcher, err := client.WatchApplications()
   217  	c.Assert(watcher, gc.IsNil)
   218  	c.Assert(err, gc.ErrorMatches, "FAIL")
   219  }
   220  
   221  func (s *unitprovisionerSuite) TestWatchApplicationScale(c *gc.C) {
   222  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   223  		c.Check(objType, gc.Equals, "CAASUnitProvisioner")
   224  		c.Check(version, gc.Equals, 0)
   225  		c.Check(id, gc.Equals, "")
   226  		c.Check(request, gc.Equals, "WatchApplicationsScale")
   227  		c.Assert(arg, jc.DeepEquals, params.Entities{
   228  			Entities: []params.Entity{{
   229  				Tag: "application-gitlab",
   230  			}},
   231  		})
   232  		c.Assert(result, gc.FitsTypeOf, &params.NotifyWatchResults{})
   233  		*(result.(*params.NotifyWatchResults)) = params.NotifyWatchResults{
   234  			Results: []params.NotifyWatchResult{{
   235  				Error: &params.Error{Message: "FAIL"},
   236  			}},
   237  		}
   238  		return nil
   239  	})
   240  
   241  	client := caasunitprovisioner.NewClient(apiCaller)
   242  	watcher, err := client.WatchApplicationScale("gitlab")
   243  	c.Assert(watcher, gc.IsNil)
   244  	c.Assert(err, gc.ErrorMatches, "FAIL")
   245  }
   246  
   247  func (s *unitprovisionerSuite) TestApplicationScale(c *gc.C) {
   248  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   249  		c.Check(objType, gc.Equals, "CAASUnitProvisioner")
   250  		c.Check(version, gc.Equals, 0)
   251  		c.Check(id, gc.Equals, "")
   252  		c.Check(request, gc.Equals, "ApplicationsScale")
   253  		c.Assert(arg, jc.DeepEquals, params.Entities{
   254  			Entities: []params.Entity{{
   255  				Tag: "application-gitlab",
   256  			}},
   257  		})
   258  		c.Assert(result, gc.FitsTypeOf, &params.IntResults{})
   259  		*(result.(*params.IntResults)) = params.IntResults{
   260  			Results: []params.IntResult{{
   261  				Result: 5,
   262  			}},
   263  		}
   264  		return nil
   265  	})
   266  
   267  	client := caasunitprovisioner.NewClient(apiCaller)
   268  	scale, err := client.ApplicationScale("gitlab")
   269  	c.Assert(err, jc.ErrorIsNil)
   270  	c.Assert(scale, gc.Equals, 5)
   271  }
   272  
   273  func (s *unitprovisionerSuite) TestWatchPodSpec(c *gc.C) {
   274  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   275  		c.Check(objType, gc.Equals, "CAASUnitProvisioner")
   276  		c.Check(version, gc.Equals, 0)
   277  		c.Check(id, gc.Equals, "")
   278  		c.Check(request, gc.Equals, "WatchPodSpec")
   279  		c.Assert(arg, jc.DeepEquals, params.Entities{
   280  			Entities: []params.Entity{{
   281  				Tag: "application-gitlab",
   282  			}},
   283  		})
   284  		c.Assert(result, gc.FitsTypeOf, &params.NotifyWatchResults{})
   285  		*(result.(*params.NotifyWatchResults)) = params.NotifyWatchResults{
   286  			Results: []params.NotifyWatchResult{{
   287  				Error: &params.Error{Message: "FAIL"},
   288  			}},
   289  		}
   290  		return nil
   291  	})
   292  
   293  	client := caasunitprovisioner.NewClient(apiCaller)
   294  	watcher, err := client.WatchPodSpec("gitlab")
   295  	c.Assert(watcher, gc.IsNil)
   296  	c.Assert(err, gc.ErrorMatches, "FAIL")
   297  }
   298  
   299  func (s *unitprovisionerSuite) TestApplicationConfig(c *gc.C) {
   300  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   301  		c.Check(objType, gc.Equals, "CAASUnitProvisioner")
   302  		c.Check(version, gc.Equals, 0)
   303  		c.Check(id, gc.Equals, "")
   304  		c.Check(request, gc.Equals, "ApplicationsConfig")
   305  		c.Assert(arg, jc.DeepEquals, params.Entities{
   306  			Entities: []params.Entity{{
   307  				Tag: "application-gitlab",
   308  			}},
   309  		})
   310  		c.Assert(result, gc.FitsTypeOf, &params.ApplicationGetConfigResults{})
   311  		*(result.(*params.ApplicationGetConfigResults)) = params.ApplicationGetConfigResults{
   312  			Results: []params.ConfigResult{{
   313  				Config: map[string]interface{}{"foo": "bar"},
   314  			}},
   315  		}
   316  		return nil
   317  	})
   318  
   319  	client := caasunitprovisioner.NewClient(apiCaller)
   320  	cfg, err := client.ApplicationConfig("gitlab")
   321  	c.Assert(err, jc.ErrorIsNil)
   322  	c.Assert(cfg, jc.DeepEquals, application.ConfigAttributes{"foo": "bar"})
   323  }
   324  
   325  func (s *unitprovisionerSuite) TestUpdateUnits(c *gc.C) {
   326  	var called bool
   327  	client := newClient(func(objType string, version int, id, request string, a, result interface{}) error {
   328  		called = true
   329  		c.Check(objType, gc.Equals, "CAASUnitProvisioner")
   330  		c.Check(id, gc.Equals, "")
   331  		c.Assert(request, gc.Equals, "UpdateApplicationsUnits")
   332  		c.Assert(a, jc.DeepEquals, params.UpdateApplicationUnitArgs{
   333  			Args: []params.UpdateApplicationUnits{
   334  				{
   335  					ApplicationTag: "application-app",
   336  					Units: []params.ApplicationUnitParams{
   337  						{ProviderId: "uuid", UnitTag: "unit-gitlab-0", Address: "address", Ports: []string{"port"},
   338  							Status: "active", Info: "message"},
   339  					},
   340  				},
   341  			},
   342  		})
   343  		c.Assert(result, gc.FitsTypeOf, &params.ErrorResults{})
   344  		*(result.(*params.ErrorResults)) = params.ErrorResults{
   345  			Results: []params.ErrorResult{{}},
   346  		}
   347  		return nil
   348  	})
   349  	err := client.UpdateUnits(params.UpdateApplicationUnits{
   350  		ApplicationTag: names.NewApplicationTag("app").String(),
   351  		Units: []params.ApplicationUnitParams{
   352  			{ProviderId: "uuid", UnitTag: "unit-gitlab-0", Address: "address", Ports: []string{"port"},
   353  				Status: "active", Info: "message"},
   354  		},
   355  	})
   356  	c.Check(err, jc.ErrorIsNil)
   357  	c.Check(called, jc.IsTrue)
   358  }
   359  
   360  func (s *unitprovisionerSuite) TestUpdateUnitsCount(c *gc.C) {
   361  	client := newClient(func(objType string, version int, id, request string, a, result interface{}) error {
   362  		*(result.(*params.ErrorResults)) = params.ErrorResults{
   363  			Results: []params.ErrorResult{
   364  				{Error: &params.Error{Message: "FAIL"}},
   365  				{Error: &params.Error{Message: "FAIL"}},
   366  			},
   367  		}
   368  		return nil
   369  	})
   370  	err := client.UpdateUnits(params.UpdateApplicationUnits{
   371  		ApplicationTag: names.NewApplicationTag("app").String(),
   372  		Units: []params.ApplicationUnitParams{
   373  			{ProviderId: "uuid", Address: "address"},
   374  		},
   375  	})
   376  	c.Check(err, gc.ErrorMatches, `expected 1 result\(s\), got 2`)
   377  }
   378  
   379  func (s *unitprovisionerSuite) TestUpdateApplicationService(c *gc.C) {
   380  	var called bool
   381  	client := newClient(func(objType string, version int, id, request string, a, result interface{}) error {
   382  		called = true
   383  		c.Check(objType, gc.Equals, "CAASUnitProvisioner")
   384  		c.Check(id, gc.Equals, "")
   385  		c.Assert(request, gc.Equals, "UpdateApplicationsService")
   386  		c.Assert(a, jc.DeepEquals, params.UpdateApplicationServiceArgs{
   387  			Args: []params.UpdateApplicationServiceArg{
   388  				{
   389  					ApplicationTag: "application-app",
   390  					ProviderId:     "id",
   391  					Addresses:      []params.Address{{Value: "10.0.0.1"}},
   392  				},
   393  			},
   394  		})
   395  		c.Assert(result, gc.FitsTypeOf, &params.ErrorResults{})
   396  		*(result.(*params.ErrorResults)) = params.ErrorResults{
   397  			Results: []params.ErrorResult{{}},
   398  		}
   399  		return nil
   400  	})
   401  	err := client.UpdateApplicationService(params.UpdateApplicationServiceArg{
   402  		ApplicationTag: names.NewApplicationTag("app").String(),
   403  		ProviderId:     "id",
   404  		Addresses:      []params.Address{{Value: "10.0.0.1"}},
   405  	})
   406  	c.Check(err, jc.ErrorIsNil)
   407  	c.Check(called, jc.IsTrue)
   408  }
   409  
   410  func (s *unitprovisionerSuite) TestUpdateApplicationServiceCount(c *gc.C) {
   411  	client := newClient(func(objType string, version int, id, request string, a, result interface{}) error {
   412  		*(result.(*params.ErrorResults)) = params.ErrorResults{
   413  			Results: []params.ErrorResult{
   414  				{Error: &params.Error{Message: "FAIL"}},
   415  				{Error: &params.Error{Message: "FAIL"}},
   416  			},
   417  		}
   418  		return nil
   419  	})
   420  	err := client.UpdateApplicationService(params.UpdateApplicationServiceArg{
   421  		ApplicationTag: names.NewApplicationTag("app").String(),
   422  		ProviderId:     "id",
   423  		Addresses:      []params.Address{{Value: "10.0.0.1"}},
   424  	})
   425  	c.Check(err, gc.ErrorMatches, `expected 1 result\(s\), got 2`)
   426  }
   427  
   428  func (s *unitprovisionerSuite) TestSetOperatorStatus(c *gc.C) {
   429  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   430  		c.Check(objType, gc.Equals, "CAASUnitProvisioner")
   431  		c.Check(version, gc.Equals, 0)
   432  		c.Check(id, gc.Equals, "")
   433  		c.Check(request, gc.Equals, "SetOperatorStatus")
   434  		c.Assert(arg, jc.DeepEquals, params.SetStatus{
   435  			Entities: []params.EntityStatusArgs{{
   436  				Tag:    "application-gitlab",
   437  				Status: "error",
   438  				Info:   "broken",
   439  				Data:   map[string]interface{}{"foo": "bar"},
   440  			}},
   441  		})
   442  		c.Assert(result, gc.FitsTypeOf, &params.ErrorResults{})
   443  		*(result.(*params.ErrorResults)) = params.ErrorResults{
   444  			Results: []params.ErrorResult{{
   445  				Error: &params.Error{Message: "FAIL"},
   446  			}},
   447  		}
   448  		return nil
   449  	})
   450  
   451  	client := caasunitprovisioner.NewClient(apiCaller)
   452  	err := client.SetOperatorStatus("gitlab", status.Error, "broken", map[string]interface{}{"foo": "bar"})
   453  	c.Assert(err, gc.ErrorMatches, "FAIL")
   454  }