github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/resource/api/helpers_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package api_test
     5  
     6  import (
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/juju/errors"
    11  	"github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  	charmresource "gopkg.in/juju/charm.v6-unstable/resource"
    15  	"gopkg.in/juju/names.v2"
    16  
    17  	"github.com/juju/juju/apiserver/params"
    18  	"github.com/juju/juju/resource"
    19  	"github.com/juju/juju/resource/api"
    20  	"github.com/juju/juju/resource/resourcetesting"
    21  )
    22  
    23  const fingerprint = "123456789012345678901234567890123456789012345678"
    24  
    25  func newFingerprint(c *gc.C, data string) charmresource.Fingerprint {
    26  	fp, err := charmresource.GenerateFingerprint(strings.NewReader(data))
    27  	c.Assert(err, jc.ErrorIsNil)
    28  	return fp
    29  }
    30  
    31  type HelpersSuite struct {
    32  	testing.IsolationSuite
    33  }
    34  
    35  var _ = gc.Suite(&HelpersSuite{})
    36  
    37  func (HelpersSuite) TestResource2API(c *gc.C) {
    38  	fp, err := charmresource.NewFingerprint([]byte(fingerprint))
    39  	c.Assert(err, jc.ErrorIsNil)
    40  	now := time.Now()
    41  	res := resource.Resource{
    42  		Resource: charmresource.Resource{
    43  			Meta: charmresource.Meta{
    44  				Name:        "spam",
    45  				Type:        charmresource.TypeFile,
    46  				Path:        "spam.tgz",
    47  				Description: "you need it",
    48  			},
    49  			Origin:      charmresource.OriginUpload,
    50  			Revision:    1,
    51  			Fingerprint: fp,
    52  			Size:        10,
    53  		},
    54  		ID:            "a-application/spam",
    55  		PendingID:     "some-unique-ID",
    56  		ApplicationID: "a-application",
    57  		Username:      "a-user",
    58  		Timestamp:     now,
    59  	}
    60  	err = res.Validate()
    61  	c.Assert(err, jc.ErrorIsNil)
    62  	apiRes := api.Resource2API(res)
    63  
    64  	c.Check(apiRes, jc.DeepEquals, api.Resource{
    65  		CharmResource: api.CharmResource{
    66  			Name:        "spam",
    67  			Type:        "file",
    68  			Path:        "spam.tgz",
    69  			Description: "you need it",
    70  			Origin:      "upload",
    71  			Revision:    1,
    72  			Fingerprint: []byte(fingerprint),
    73  			Size:        10,
    74  		},
    75  		ID:            "a-application/spam",
    76  		PendingID:     "some-unique-ID",
    77  		ApplicationID: "a-application",
    78  		Username:      "a-user",
    79  		Timestamp:     now,
    80  	})
    81  }
    82  
    83  func (HelpersSuite) TestAPIResult2ServiceResourcesOkay(c *gc.C) {
    84  	fp, err := charmresource.NewFingerprint([]byte(fingerprint))
    85  	c.Assert(err, jc.ErrorIsNil)
    86  	now := time.Now()
    87  	expected := resource.Resource{
    88  		Resource: charmresource.Resource{
    89  			Meta: charmresource.Meta{
    90  				Name:        "spam",
    91  				Type:        charmresource.TypeFile,
    92  				Path:        "spam.tgz",
    93  				Description: "you need it",
    94  			},
    95  			Origin:      charmresource.OriginUpload,
    96  			Revision:    1,
    97  			Fingerprint: fp,
    98  			Size:        10,
    99  		},
   100  		ID:            "a-application/spam",
   101  		PendingID:     "some-unique-ID",
   102  		ApplicationID: "a-application",
   103  		Username:      "a-user",
   104  		Timestamp:     now,
   105  	}
   106  	err = expected.Validate()
   107  	c.Assert(err, jc.ErrorIsNil)
   108  
   109  	unitExpected := resource.Resource{
   110  		Resource: charmresource.Resource{
   111  			Meta: charmresource.Meta{
   112  				Name:        "unitspam",
   113  				Type:        charmresource.TypeFile,
   114  				Path:        "unitspam.tgz",
   115  				Description: "you need it",
   116  			},
   117  			Origin:      charmresource.OriginUpload,
   118  			Revision:    1,
   119  			Fingerprint: fp,
   120  			Size:        10,
   121  		},
   122  		ID:            "a-application/spam",
   123  		PendingID:     "some-unique-ID",
   124  		ApplicationID: "a-application",
   125  		Username:      "a-user",
   126  		Timestamp:     now,
   127  	}
   128  	err = unitExpected.Validate()
   129  	c.Assert(err, jc.ErrorIsNil)
   130  
   131  	apiRes := api.Resource{
   132  		CharmResource: api.CharmResource{
   133  			Name:        "spam",
   134  			Type:        "file",
   135  			Path:        "spam.tgz",
   136  			Description: "you need it",
   137  			Origin:      "upload",
   138  			Revision:    1,
   139  			Fingerprint: []byte(fingerprint),
   140  			Size:        10,
   141  		},
   142  		ID:            "a-application/spam",
   143  		PendingID:     "some-unique-ID",
   144  		ApplicationID: "a-application",
   145  		Username:      "a-user",
   146  		Timestamp:     now,
   147  	}
   148  
   149  	unitRes := api.Resource{
   150  		CharmResource: api.CharmResource{
   151  			Name:        "unitspam",
   152  			Type:        "file",
   153  			Path:        "unitspam.tgz",
   154  			Description: "you need it",
   155  			Origin:      "upload",
   156  			Revision:    1,
   157  			Fingerprint: []byte(fingerprint),
   158  			Size:        10,
   159  		},
   160  		ID:            "a-application/spam",
   161  		PendingID:     "some-unique-ID",
   162  		ApplicationID: "a-application",
   163  		Username:      "a-user",
   164  		Timestamp:     now,
   165  	}
   166  
   167  	fp2, err := charmresource.GenerateFingerprint(strings.NewReader("boo!"))
   168  	c.Assert(err, jc.ErrorIsNil)
   169  
   170  	chRes := api.CharmResource{
   171  		Name:        "unitspam2",
   172  		Type:        "file",
   173  		Path:        "unitspam.tgz2",
   174  		Description: "you need it2",
   175  		Origin:      "upload",
   176  		Revision:    2,
   177  		Fingerprint: fp2.Bytes(),
   178  		Size:        11,
   179  	}
   180  
   181  	chExpected := charmresource.Resource{
   182  		Meta: charmresource.Meta{
   183  			Name:        "unitspam2",
   184  			Type:        charmresource.TypeFile,
   185  			Path:        "unitspam.tgz2",
   186  			Description: "you need it2",
   187  		},
   188  		Origin:      charmresource.OriginUpload,
   189  		Revision:    2,
   190  		Fingerprint: fp2,
   191  		Size:        11,
   192  	}
   193  
   194  	resources, err := api.APIResult2ServiceResources(api.ResourcesResult{
   195  		Resources: []api.Resource{
   196  			apiRes,
   197  		},
   198  		CharmStoreResources: []api.CharmResource{
   199  			chRes,
   200  		},
   201  		UnitResources: []api.UnitResources{
   202  			{
   203  				Entity: params.Entity{
   204  					Tag: "unit-foo-0",
   205  				},
   206  				Resources: []api.Resource{
   207  					unitRes,
   208  				},
   209  				DownloadProgress: map[string]int64{
   210  					unitRes.Name: 8,
   211  				},
   212  			},
   213  		},
   214  	})
   215  	c.Assert(err, jc.ErrorIsNil)
   216  
   217  	serviceResource := resource.ServiceResources{
   218  		Resources: []resource.Resource{
   219  			expected,
   220  		},
   221  		CharmStoreResources: []charmresource.Resource{
   222  			chExpected,
   223  		},
   224  		UnitResources: []resource.UnitResources{
   225  			{
   226  				Tag: names.NewUnitTag("foo/0"),
   227  				Resources: []resource.Resource{
   228  					unitExpected,
   229  				},
   230  				DownloadProgress: map[string]int64{
   231  					unitRes.Name: 8,
   232  				},
   233  			},
   234  		},
   235  	}
   236  
   237  	c.Check(resources, jc.DeepEquals, serviceResource)
   238  }
   239  
   240  func (HelpersSuite) TestAPIResult2ServiceResourcesBadUnitTag(c *gc.C) {
   241  	fp, err := charmresource.NewFingerprint([]byte(fingerprint))
   242  	c.Assert(err, jc.ErrorIsNil)
   243  	now := time.Now()
   244  	expected := resource.Resource{
   245  		Resource: charmresource.Resource{
   246  			Meta: charmresource.Meta{
   247  				Name:        "spam",
   248  				Type:        charmresource.TypeFile,
   249  				Path:        "spam.tgz",
   250  				Description: "you need it",
   251  			},
   252  			Origin:      charmresource.OriginUpload,
   253  			Revision:    1,
   254  			Fingerprint: fp,
   255  			Size:        10,
   256  		},
   257  		ID:            "a-application/spam",
   258  		PendingID:     "some-unique-ID",
   259  		ApplicationID: "a-application",
   260  		Username:      "a-user",
   261  		Timestamp:     now,
   262  	}
   263  	err = expected.Validate()
   264  	c.Assert(err, jc.ErrorIsNil)
   265  
   266  	unitExpected := resource.Resource{
   267  		Resource: charmresource.Resource{
   268  			Meta: charmresource.Meta{
   269  				Name:        "unitspam",
   270  				Type:        charmresource.TypeFile,
   271  				Path:        "unitspam.tgz",
   272  				Description: "you need it",
   273  			},
   274  			Origin:      charmresource.OriginUpload,
   275  			Revision:    1,
   276  			Fingerprint: fp,
   277  			Size:        10,
   278  		},
   279  		ID:            "a-application/spam",
   280  		PendingID:     "some-unique-ID",
   281  		ApplicationID: "a-application",
   282  		Username:      "a-user",
   283  		Timestamp:     now,
   284  	}
   285  	err = unitExpected.Validate()
   286  	c.Assert(err, jc.ErrorIsNil)
   287  
   288  	apiRes := api.Resource{
   289  		CharmResource: api.CharmResource{
   290  			Name:        "spam",
   291  			Type:        "file",
   292  			Path:        "spam.tgz",
   293  			Description: "you need it",
   294  			Origin:      "upload",
   295  			Revision:    1,
   296  			Fingerprint: []byte(fingerprint),
   297  			Size:        10,
   298  		},
   299  		ID:            "a-application/spam",
   300  		PendingID:     "some-unique-ID",
   301  		ApplicationID: "a-application",
   302  		Username:      "a-user",
   303  		Timestamp:     now,
   304  	}
   305  
   306  	unitRes := api.Resource{
   307  		CharmResource: api.CharmResource{
   308  			Name:        "unitspam",
   309  			Type:        "file",
   310  			Path:        "unitspam.tgz",
   311  			Description: "you need it",
   312  			Origin:      "upload",
   313  			Revision:    1,
   314  			Fingerprint: []byte(fingerprint),
   315  			Size:        10,
   316  		},
   317  		ID:            "a-application/spam",
   318  		PendingID:     "some-unique-ID",
   319  		ApplicationID: "a-application",
   320  		Username:      "a-user",
   321  		Timestamp:     now,
   322  	}
   323  
   324  	_, err = api.APIResult2ServiceResources(api.ResourcesResult{
   325  		Resources: []api.Resource{
   326  			apiRes,
   327  		},
   328  		UnitResources: []api.UnitResources{
   329  			{
   330  				Entity: params.Entity{
   331  					Tag: "THIS IS NOT A GOOD UNIT TAG",
   332  				},
   333  				Resources: []api.Resource{
   334  					unitRes,
   335  				},
   336  			},
   337  		},
   338  	})
   339  	c.Assert(err, gc.ErrorMatches, ".*got bad data from server.*")
   340  }
   341  
   342  func (HelpersSuite) TestAPIResult2ServiceResourcesFailure(c *gc.C) {
   343  	apiRes := api.Resource{
   344  		CharmResource: api.CharmResource{
   345  			Name:        "spam",
   346  			Type:        "file",
   347  			Path:        "spam.tgz",
   348  			Origin:      "upload",
   349  			Revision:    1,
   350  			Fingerprint: []byte(fingerprint),
   351  			Size:        10,
   352  		},
   353  		ID:            "a-application/spam",
   354  		ApplicationID: "a-application",
   355  	}
   356  	failure := errors.New("<failure>")
   357  
   358  	_, err := api.APIResult2ServiceResources(api.ResourcesResult{
   359  		ErrorResult: params.ErrorResult{
   360  			Error: &params.Error{
   361  				Message: failure.Error(),
   362  			},
   363  		},
   364  		Resources: []api.Resource{
   365  			apiRes,
   366  		},
   367  	})
   368  
   369  	c.Check(err, gc.ErrorMatches, "<failure>")
   370  	c.Check(errors.Cause(err), gc.Not(gc.Equals), failure)
   371  }
   372  
   373  func (HelpersSuite) TestAPIResult2ServiceResourcesNotFound(c *gc.C) {
   374  	apiRes := api.Resource{
   375  		CharmResource: api.CharmResource{
   376  			Name:        "spam",
   377  			Type:        "file",
   378  			Path:        "spam.tgz",
   379  			Origin:      "upload",
   380  			Revision:    1,
   381  			Fingerprint: []byte(fingerprint),
   382  			Size:        10,
   383  		},
   384  		ID:            "a-application/spam",
   385  		ApplicationID: "a-application",
   386  	}
   387  
   388  	_, err := api.APIResult2ServiceResources(api.ResourcesResult{
   389  		ErrorResult: params.ErrorResult{
   390  			Error: &params.Error{
   391  				Message: `application "a-application" not found`,
   392  				Code:    params.CodeNotFound,
   393  			},
   394  		},
   395  		Resources: []api.Resource{
   396  			apiRes,
   397  		},
   398  	})
   399  
   400  	c.Check(err, jc.Satisfies, errors.IsNotFound)
   401  }
   402  
   403  func (HelpersSuite) TestAPI2Resource(c *gc.C) {
   404  	now := time.Now()
   405  	res, err := api.API2Resource(api.Resource{
   406  		CharmResource: api.CharmResource{
   407  			Name:        "spam",
   408  			Type:        "file",
   409  			Path:        "spam.tgz",
   410  			Description: "you need it",
   411  			Origin:      "upload",
   412  			Revision:    1,
   413  			Fingerprint: []byte(fingerprint),
   414  			Size:        10,
   415  		},
   416  		ID:            "a-application/spam",
   417  		PendingID:     "some-unique-ID",
   418  		ApplicationID: "a-application",
   419  		Username:      "a-user",
   420  		Timestamp:     now,
   421  	})
   422  	c.Assert(err, jc.ErrorIsNil)
   423  
   424  	fp, err := charmresource.NewFingerprint([]byte(fingerprint))
   425  	c.Assert(err, jc.ErrorIsNil)
   426  	expected := resource.Resource{
   427  		Resource: charmresource.Resource{
   428  			Meta: charmresource.Meta{
   429  				Name:        "spam",
   430  				Type:        charmresource.TypeFile,
   431  				Path:        "spam.tgz",
   432  				Description: "you need it",
   433  			},
   434  			Origin:      charmresource.OriginUpload,
   435  			Revision:    1,
   436  			Fingerprint: fp,
   437  			Size:        10,
   438  		},
   439  		ID:            "a-application/spam",
   440  		PendingID:     "some-unique-ID",
   441  		ApplicationID: "a-application",
   442  		Username:      "a-user",
   443  		Timestamp:     now,
   444  	}
   445  	err = expected.Validate()
   446  	c.Assert(err, jc.ErrorIsNil)
   447  
   448  	c.Check(res, jc.DeepEquals, expected)
   449  }
   450  
   451  func (HelpersSuite) TestCharmResource2API(c *gc.C) {
   452  	fp, err := charmresource.NewFingerprint([]byte(fingerprint))
   453  	c.Assert(err, jc.ErrorIsNil)
   454  	res := charmresource.Resource{
   455  		Meta: charmresource.Meta{
   456  			Name:        "spam",
   457  			Type:        charmresource.TypeFile,
   458  			Path:        "spam.tgz",
   459  			Description: "you need it",
   460  		},
   461  		Origin:      charmresource.OriginUpload,
   462  		Revision:    1,
   463  		Fingerprint: fp,
   464  		Size:        10,
   465  	}
   466  	err = res.Validate()
   467  	c.Assert(err, jc.ErrorIsNil)
   468  	apiInfo := api.CharmResource2API(res)
   469  
   470  	c.Check(apiInfo, jc.DeepEquals, api.CharmResource{
   471  		Name:        "spam",
   472  		Type:        "file",
   473  		Path:        "spam.tgz",
   474  		Description: "you need it",
   475  		Origin:      "upload",
   476  		Revision:    1,
   477  		Fingerprint: []byte(fingerprint),
   478  		Size:        10,
   479  	})
   480  }
   481  
   482  func (HelpersSuite) TestAPI2CharmResource(c *gc.C) {
   483  	res, err := api.API2CharmResource(api.CharmResource{
   484  		Name:        "spam",
   485  		Type:        "file",
   486  		Path:        "spam.tgz",
   487  		Description: "you need it",
   488  		Origin:      "upload",
   489  		Revision:    1,
   490  		Fingerprint: []byte(fingerprint),
   491  		Size:        10,
   492  	})
   493  	c.Assert(err, jc.ErrorIsNil)
   494  
   495  	fp, err := charmresource.NewFingerprint([]byte(fingerprint))
   496  	c.Assert(err, jc.ErrorIsNil)
   497  	expected := charmresource.Resource{
   498  		Meta: charmresource.Meta{
   499  			Name:        "spam",
   500  			Type:        charmresource.TypeFile,
   501  			Path:        "spam.tgz",
   502  			Description: "you need it",
   503  		},
   504  		Origin:      charmresource.OriginUpload,
   505  		Revision:    1,
   506  		Fingerprint: fp,
   507  		Size:        10,
   508  	}
   509  	err = expected.Validate()
   510  	c.Assert(err, jc.ErrorIsNil)
   511  
   512  	c.Check(res, jc.DeepEquals, expected)
   513  }
   514  
   515  func (HelpersSuite) TestServiceResources2API(c *gc.C) {
   516  	res1 := resourcetesting.NewResource(c, nil, "res1", "a-application", "data").Resource
   517  	res2 := resourcetesting.NewResource(c, nil, "res2", "a-application", "data2").Resource
   518  
   519  	tag0 := names.NewUnitTag("a-application/0")
   520  	tag1 := names.NewUnitTag("a-application/1")
   521  
   522  	chres1 := res1.Resource
   523  	chres2 := res2.Resource
   524  	chres1.Revision++
   525  	chres2.Revision++
   526  
   527  	svcRes := resource.ServiceResources{
   528  		Resources: []resource.Resource{
   529  			res1,
   530  			res2,
   531  		},
   532  		UnitResources: []resource.UnitResources{
   533  			{
   534  				Tag: tag0,
   535  				Resources: []resource.Resource{
   536  					res1,
   537  					res2,
   538  				},
   539  				DownloadProgress: map[string]int64{
   540  					res2.Name: 2,
   541  				},
   542  			},
   543  			{
   544  				Tag: tag1,
   545  			},
   546  		},
   547  		CharmStoreResources: []charmresource.Resource{
   548  			chres1,
   549  			chres2,
   550  		},
   551  	}
   552  
   553  	result := api.ServiceResources2APIResult(svcRes)
   554  
   555  	apiRes1 := api.Resource2API(res1)
   556  	apiRes2 := api.Resource2API(res2)
   557  
   558  	apiChRes1 := api.CharmResource2API(chres1)
   559  	apiChRes2 := api.CharmResource2API(chres2)
   560  
   561  	c.Check(result, jc.DeepEquals, api.ResourcesResult{
   562  		Resources: []api.Resource{
   563  			apiRes1,
   564  			apiRes2,
   565  		},
   566  		UnitResources: []api.UnitResources{
   567  			{
   568  				Entity: params.Entity{
   569  					Tag: "unit-a-application-0",
   570  				},
   571  				Resources: []api.Resource{
   572  					apiRes1,
   573  					apiRes2,
   574  				},
   575  				DownloadProgress: map[string]int64{
   576  					res2.Name: 2,
   577  				},
   578  			},
   579  			{
   580  				// we should have a listing for every unit, even if they
   581  				// have no resources.
   582  				Entity: params.Entity{
   583  					Tag: "unit-a-application-1",
   584  				},
   585  			},
   586  		},
   587  		CharmStoreResources: []api.CharmResource{
   588  			apiChRes1,
   589  			apiChRes2,
   590  		},
   591  	})
   592  }