~juju-qa/ubuntu/xenial/juju/xenial-2.0-beta3

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/cmd/juju/service/deploy_test.go

  • Committer: Martin Packman
  • Date: 2016-03-30 19:31:08 UTC
  • mfrom: (1.1.41)
  • Revision ID: martin.packman@canonical.com-20160330193108-h9iz3ak334uk0z5r
Merge new upstream source 2.0~beta3

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
        "net/url"
13
13
        "os"
14
14
        "path"
 
15
        "path/filepath"
15
16
        "sort"
16
17
        "strings"
17
18
 
24
25
        "gopkg.in/juju/charm.v6-unstable"
25
26
        "gopkg.in/juju/charmrepo.v2-unstable"
26
27
        "gopkg.in/juju/charmrepo.v2-unstable/csclient"
 
28
        csclientparams "gopkg.in/juju/charmrepo.v2-unstable/csclient/params"
27
29
        "gopkg.in/juju/charmstore.v5-unstable"
28
30
        "gopkg.in/macaroon-bakery.v1/bakery"
29
31
        "gopkg.in/macaroon-bakery.v1/bakery/checkers"
39
41
        "github.com/juju/juju/environs/config"
40
42
        "github.com/juju/juju/instance"
41
43
        "github.com/juju/juju/juju/testing"
 
44
        "github.com/juju/juju/provider/dummy"
42
45
        "github.com/juju/juju/state"
43
46
        "github.com/juju/juju/storage/poolmanager"
44
47
        "github.com/juju/juju/storage/provider"
119
122
        c.Assert(err, gc.ErrorMatches, `charm or bundle URL has invalid form: "/home/nowhere"`)
120
123
}
121
124
 
 
125
func (s *DeploySuite) TestInvalidFileFormat(c *gc.C) {
 
126
        path := filepath.Join(c.MkDir(), "bundle.yaml")
 
127
        err := ioutil.WriteFile(path, []byte(":"), 0600)
 
128
        c.Assert(err, jc.ErrorIsNil)
 
129
        err = runDeploy(c, path)
 
130
        c.Assert(err, gc.ErrorMatches, `invalid charm or bundle provided at ".*bundle.yaml"`)
 
131
}
 
132
 
122
133
func (s *DeploySuite) TestPathWithNoCharm(c *gc.C) {
123
134
        err := runDeploy(c, c.MkDir())
124
135
        c.Assert(err, gc.ErrorMatches, `no charm or bundle found at .*`)
305
316
        })
306
317
}
307
318
 
 
319
// TODO(ericsnow) Add tests for charmstore-based resources once the
 
320
// endpoints are implemented.
 
321
 
308
322
func (s *DeploySuite) TestNetworksIsDeprecated(c *gc.C) {
309
323
        testcharms.Repo.CharmArchivePath(s.SeriesPath, "dummy")
310
324
        err := runDeploy(c, "local:dummy", "--networks", ", net1, net2 , ", "--constraints", "mem=2G cpu-cores=2 networks=net1,net0,^net3,^net4")
539
553
 
540
554
        for i, test := range deploySeriesTests {
541
555
                c.Logf("test %d", i)
542
 
                cfg, err := config.New(config.UseDefaults, map[string]interface{}{
543
 
                        "name":            "test",
544
 
                        "type":            "dummy",
545
 
                        "uuid":            coretesting.ModelTag.Id(),
546
 
                        "ca-cert":         coretesting.CACert,
547
 
                        "ca-private-key":  coretesting.CAKey,
548
 
                        "authorized-keys": coretesting.FakeAuthKeys,
549
 
                        "default-series":  test.modelSeries,
550
 
                })
 
556
                cfg, err := config.New(config.UseDefaults, dummy.SampleConfig().Merge(coretesting.Attrs{
 
557
                        "default-series": test.modelSeries,
 
558
                }))
551
559
                c.Assert(err, jc.ErrorIsNil)
552
560
                series, msg, err := charmSeries(test.requestedSeries, test.seriesFromCharm, test.supportedSeries, test.force, cfg)
553
561
                if test.err != "" {
713
721
Deployment under prior agreement to terms: term1/1 term3/1
714
722
`
715
723
        c.Assert(output, gc.Equals, strings.TrimSpace(expectedOutput))
716
 
        s.assertCharmsUplodaded(c, "cs:trusty/terms1-1")
 
724
        s.assertCharmsUploaded(c, "cs:trusty/terms1-1")
717
725
        s.assertServicesDeployed(c, map[string]serviceInfo{
718
726
                "terms1": {charm: "cs:trusty/terms1-1"},
719
727
        })
732
740
        c.Assert(err, gc.ErrorMatches, expectedError)
733
741
}
734
742
 
 
743
func (s *DeployCharmStoreSuite) TestDeployWithChannel(c *gc.C) {
 
744
        ch := testcharms.Repo.CharmArchive(c.MkDir(), "wordpress")
 
745
        id := charm.MustParseURL("cs:~client-username/precise/wordpress-0")
 
746
        err := s.client.UploadCharmWithRevision(id, ch, -1)
 
747
        c.Assert(err, gc.IsNil)
 
748
 
 
749
        err = s.client.Publish(id, []csclientparams.Channel{csclientparams.DevelopmentChannel}, nil)
 
750
        c.Assert(err, gc.IsNil)
 
751
 
 
752
        _, err = runDeployCommand(c, "--channel", "development", "~client-username/wordpress")
 
753
        c.Assert(err, gc.IsNil)
 
754
        s.assertCharmsUploaded(c, "cs:~client-username/precise/wordpress-0")
 
755
        s.assertServicesDeployed(c, map[string]serviceInfo{
 
756
                "wordpress": {charm: "cs:~client-username/precise/wordpress-0"},
 
757
        })
 
758
}
 
759
 
735
760
const (
736
761
        // clientUserCookie is the name of the cookie which is
737
762
        // used to signal to the charmStoreSuite macaroon discharger
799
824
                PublicKeyLocator: keyring,
800
825
                TermsLocation:    s.termsDischarger.Location(),
801
826
        }
802
 
        handler, err := charmstore.NewServer(db, nil, "", params, charmstore.V4)
 
827
        handler, err := charmstore.NewServer(db, nil, "", params, charmstore.V5)
803
828
        c.Assert(err, jc.ErrorIsNil)
804
829
        s.handler = handler
805
830
        s.srv = httptest.NewServer(handler)
 
831
        c.Logf("started charmstore on %v", s.srv.URL)
806
832
        s.client = csclient.New(csclient.Params{
807
833
                URL:      s.srv.URL,
808
834
                User:     params.AuthUsername,
813
839
        s.PatchValue(&charmrepo.CacheDir, c.MkDir())
814
840
 
815
841
        // Point the CLI to the charm store testing server.
816
 
        original := newCharmStoreClient
817
 
        s.PatchValue(&newCharmStoreClient, func(httpClient *http.Client) *csClient {
818
 
                csclient := original(httpClient)
819
 
                csclient.params.URL = s.srv.URL
 
842
        s.PatchValue(&newCharmStoreClient, func(client *httpbakery.Client) *csclient.Client {
820
843
                // Add a cookie so that the discharger can detect whether the
821
844
                // HTTP client is the juju environment or the juju client.
822
845
                lurl, err := url.Parse(s.discharger.Location())
823
846
                c.Assert(err, jc.ErrorIsNil)
824
 
                csclient.params.HTTPClient.Jar.SetCookies(lurl, []*http.Cookie{{
 
847
                client.Jar.SetCookies(lurl, []*http.Cookie{{
825
848
                        Name:  clientUserCookie,
826
849
                        Value: clientUserName,
827
850
                }})
828
 
                return csclient
 
851
                return csclient.New(csclient.Params{
 
852
                        URL:          s.srv.URL,
 
853
                        BakeryClient: client,
 
854
                })
829
855
        })
830
856
 
831
857
        // Point the Juju API server to the charm store testing server.
832
858
        s.PatchValue(&csclient.ServerURL, s.srv.URL)
833
859
 
834
 
        s.PatchValue(&getApiClient, func(*http.Client) (apiClient, error) { return &mockBudgetAPIClient{&jujutesting.Stub{}}, nil })
 
860
        s.PatchValue(&getApiClient, func(*httpbakery.Client) (apiClient, error) {
 
861
                return &mockBudgetAPIClient{&jujutesting.Stub{}}, nil
 
862
        })
835
863
}
836
864
 
837
865
func (s *charmStoreSuite) TearDownTest(c *gc.C) {
848
876
        c.Assert(err, jc.ErrorIsNil)
849
877
}
850
878
 
851
 
// assertCharmsUplodaded checks that the given charm ids have been uploaded.
852
 
func (s *charmStoreSuite) assertCharmsUplodaded(c *gc.C, ids ...string) {
 
879
// assertCharmsUploaded checks that the given charm ids have been uploaded.
 
880
func (s *charmStoreSuite) assertCharmsUploaded(c *gc.C, ids ...string) {
853
881
        charms, err := s.State.AllCharms()
854
882
        c.Assert(err, jc.ErrorIsNil)
855
883
        uploaded := make([]string, len(charms))
989
1017
        c.Assert(err, jc.ErrorIsNil)
990
1018
        c.Assert(ch.URL(), gc.DeepEquals, curl)
991
1019
        c.Assert(called, jc.IsTrue)
992
 
        modelUUID, _ := s.Environ.Config().UUID()
 
1020
        modelUUID := s.Environ.Config().UUID()
993
1021
        stub.CheckCalls(c, []jujutesting.StubCall{{
994
1022
                "Authorize", []interface{}{metricRegistrationPost{
995
1023
                        ModelUUID:   modelUUID,
1036
1064
        c.Assert(err, jc.ErrorIsNil)
1037
1065
        c.Assert(ch.URL(), gc.DeepEquals, curl)
1038
1066
        c.Assert(called, jc.IsTrue)
1039
 
        modelUUID, _ := s.Environ.Config().UUID()
 
1067
        modelUUID := s.Environ.Config().UUID()
1040
1068
        stub.CheckCalls(c, []jujutesting.StubCall{{
1041
1069
                "DefaultPlan", []interface{}{"cs:quantal/metered-1"},
1042
1070
        }, {
1083
1111
        c.Assert(command.flagSet, jc.DeepEquals, flagSet)
1084
1112
        // Add to the slice below if a new flag is introduced which is valid for
1085
1113
        // both charms and bundles.
1086
 
        charmAndBundleFlags := []string{"repository", "storage"}
 
1114
        charmAndBundleFlags := []string{"channel", "repository", "storage"}
1087
1115
        var allFlags []string
1088
1116
        flagSet.VisitAll(func(flag *gnuflag.Flag) {
1089
1117
                allFlags = append(allFlags, flag.Name)
1100
1128
        _, err = s.State.AddSpace("public", "", nil, false)
1101
1129
        c.Assert(err, jc.ErrorIsNil)
1102
1130
 
1103
 
        testcharms.UploadCharm(c, s.client, "cs:quantal/wordpress-1", "wordpress")
1104
 
        err = runDeploy(c, "cs:quantal/wordpress-1", "--bind", "db=db public")
 
1131
        testcharms.UploadCharm(c, s.client, "cs:quantal/wordpress-extra-bindings-1", "wordpress-extra-bindings")
 
1132
        err = runDeploy(c, "cs:quantal/wordpress-extra-bindings-1", "--bind", "db=db db-client=db public admin-api=public")
1105
1133
        c.Assert(err, jc.ErrorIsNil)
1106
1134
        s.assertServicesDeployed(c, map[string]serviceInfo{
1107
 
                "wordpress": {charm: "cs:quantal/wordpress-1"},
 
1135
                "wordpress-extra-bindings": {charm: "cs:quantal/wordpress-extra-bindings-1"},
1108
1136
        })
1109
1137
        s.assertDeployedServiceBindings(c, map[string]serviceInfo{
1110
 
                "wordpress": {
 
1138
                "wordpress-extra-bindings": {
1111
1139
                        endpointBindings: map[string]string{
1112
1140
                                "cache":           "public",
1113
1141
                                "url":             "public",
1114
1142
                                "logging-dir":     "public",
1115
1143
                                "monitoring-port": "public",
1116
1144
                                "db":              "db",
 
1145
                                "db-client":       "db",
 
1146
                                "admin-api":       "public",
 
1147
                                "foo-bar":         "public",
 
1148
                                "cluster":         "public",
1117
1149
                        },
1118
1150
                },
1119
1151
        })
1149
1181
 
1150
1182
var _ = gc.Suite(&ParseBindSuite{})
1151
1183
 
1152
 
func (s *ParseBindSuite) TestBindParseEmpty(c *gc.C) {
1153
 
        deploy := &DeployCommand{BindToSpaces: ""}
1154
 
        err := deploy.parseBind()
1155
 
        c.Assert(err, jc.ErrorIsNil)
1156
 
        c.Assert(deploy.Bindings, gc.IsNil)
1157
 
}
1158
 
 
1159
 
func (s *ParseBindSuite) TestBindParseOK(c *gc.C) {
1160
 
        deploy := &DeployCommand{BindToSpaces: "foo=a bar=b"}
1161
 
        err := deploy.parseBind()
1162
 
        c.Assert(err, jc.ErrorIsNil)
1163
 
        c.Assert(deploy.Bindings, jc.DeepEquals, map[string]string{"foo": "a", "bar": "b"})
1164
 
}
1165
 
 
1166
 
func (s *ParseBindSuite) TestBindParseServiceDefault(c *gc.C) {
1167
 
        deploy := &DeployCommand{BindToSpaces: "service-default"}
1168
 
        err := deploy.parseBind()
1169
 
        c.Assert(err, jc.ErrorIsNil)
1170
 
        c.Assert(deploy.Bindings, jc.DeepEquals, map[string]string{"": "service-default"})
1171
 
}
1172
 
 
1173
 
func (s *ParseBindSuite) TestBindParseNoEndpoint(c *gc.C) {
1174
 
        deploy := &DeployCommand{BindToSpaces: "=bad"}
1175
 
        err := deploy.parseBind()
1176
 
        c.Assert(err.Error(), gc.Equals, parseBindErrorPrefix+"Found = without relation name. Use a lone space name to set the default.")
1177
 
        c.Assert(deploy.Bindings, gc.IsNil)
1178
 
}
1179
 
 
1180
 
func (s *ParseBindSuite) TestBindParseBadList(c *gc.C) {
1181
 
        deploy := &DeployCommand{BindToSpaces: "foo=bar=baz"}
1182
 
        err := deploy.parseBind()
1183
 
        c.Assert(err.Error(), gc.Equals, parseBindErrorPrefix+"Found multiple = in binding. Did you forget to space-separate the binding list?")
1184
 
        c.Assert(deploy.Bindings, gc.IsNil)
1185
 
}
1186
 
 
1187
 
func (s *ParseBindSuite) TestBindParseDefaultAndEndpoints(c *gc.C) {
1188
 
        deploy := &DeployCommand{BindToSpaces: "rel1=space1  rel2=space2 space3"}
1189
 
        err := deploy.parseBind()
1190
 
        c.Assert(err, jc.ErrorIsNil)
1191
 
        c.Assert(deploy.Bindings, jc.DeepEquals, map[string]string{"rel1": "space1", "rel2": "space2", "": "space3"})
1192
 
}
1193
 
 
1194
 
func (s *ParseBindSuite) TestBindParseDefaultAndEndpoints2(c *gc.C) {
1195
 
        deploy := &DeployCommand{BindToSpaces: "rel1=space1  space3 rel2=space2"}
1196
 
        err := deploy.parseBind()
1197
 
        c.Assert(err, jc.ErrorIsNil)
1198
 
        c.Assert(deploy.Bindings, jc.DeepEquals, map[string]string{"rel1": "space1", "rel2": "space2", "": "space3"})
1199
 
}
1200
 
 
1201
 
func (s *ParseBindSuite) TestBindParseDefaultAndEndpoints3(c *gc.C) {
1202
 
        deploy := &DeployCommand{BindToSpaces: "space3  rel1=space1 rel2=space2"}
1203
 
        err := deploy.parseBind()
1204
 
        c.Assert(err, jc.ErrorIsNil)
1205
 
        c.Assert(deploy.Bindings, jc.DeepEquals, map[string]string{"rel1": "space1", "rel2": "space2", "": "space3"})
1206
 
}
1207
 
 
1208
 
func (s *ParseBindSuite) TestBindParseBadSpace(c *gc.C) {
1209
 
        deploy := &DeployCommand{BindToSpaces: "rel1=spa#ce1"}
1210
 
        err := deploy.parseBind()
1211
 
        c.Assert(err.Error(), gc.Equals, parseBindErrorPrefix+"Space name invalid.")
1212
 
        c.Assert(deploy.Bindings, gc.IsNil)
 
1184
func (s *ParseBindSuite) TestParseSuccessWithEmptyArgs(c *gc.C) {
 
1185
        s.checkParseOKForArgs(c, "", nil)
 
1186
}
 
1187
 
 
1188
func (s *ParseBindSuite) TestParseSuccessWithEndpointsOnly(c *gc.C) {
 
1189
        s.checkParseOKForArgs(c, "foo=a bar=b", map[string]string{"foo": "a", "bar": "b"})
 
1190
}
 
1191
 
 
1192
func (s *ParseBindSuite) TestParseSuccessWithServiceDefaultSpaceOnly(c *gc.C) {
 
1193
        s.checkParseOKForArgs(c, "service-default", map[string]string{"": "service-default"})
 
1194
}
 
1195
 
 
1196
func (s *ParseBindSuite) TestBindingsOrderForDefaultSpaceAndEndpointsDoesNotMatter(c *gc.C) {
 
1197
        expectedBindings := map[string]string{
 
1198
                "ep1": "sp1",
 
1199
                "ep2": "sp2",
 
1200
                "":    "sp3",
 
1201
        }
 
1202
        s.checkParseOKForArgs(c, "ep1=sp1 ep2=sp2 sp3", expectedBindings)
 
1203
        s.checkParseOKForArgs(c, "ep1=sp1 sp3 ep2=sp2", expectedBindings)
 
1204
        s.checkParseOKForArgs(c, "ep2=sp2 ep1=sp1 sp3", expectedBindings)
 
1205
        s.checkParseOKForArgs(c, "ep2=sp2 sp3 ep1=sp1", expectedBindings)
 
1206
        s.checkParseOKForArgs(c, "sp3 ep1=sp1 ep2=sp2", expectedBindings)
 
1207
        s.checkParseOKForArgs(c, "sp3 ep2=sp2 ep1=sp1", expectedBindings)
 
1208
}
 
1209
 
 
1210
func (s *ParseBindSuite) TestParseFailsWithSpaceNameButNoEndpoint(c *gc.C) {
 
1211
        s.checkParseFailsForArgs(c, "=bad", "Found = without endpoint name. Use a lone space name to set the default.")
 
1212
}
 
1213
 
 
1214
func (s *ParseBindSuite) TestParseFailsWithTooManyEqualsSignsInArgs(c *gc.C) {
 
1215
        s.checkParseFailsForArgs(c, "foo=bar=baz", "Found multiple = in binding. Did you forget to space-separate the binding list?")
 
1216
}
 
1217
 
 
1218
func (s *ParseBindSuite) TestParseFailsWithBadSpaceName(c *gc.C) {
 
1219
        s.checkParseFailsForArgs(c, "rel1=spa#ce1", "Space name invalid.")
 
1220
}
 
1221
 
 
1222
func (s *ParseBindSuite) runParseBindWithArgs(args string) (error, map[string]string) {
 
1223
        deploy := &DeployCommand{BindToSpaces: args}
 
1224
        return deploy.parseBind(), deploy.Bindings
 
1225
}
 
1226
 
 
1227
func (s *ParseBindSuite) checkParseOKForArgs(c *gc.C, args string, expectedBindings map[string]string) {
 
1228
        err, parsedBindings := s.runParseBindWithArgs(args)
 
1229
        c.Check(err, jc.ErrorIsNil)
 
1230
        c.Check(parsedBindings, jc.DeepEquals, expectedBindings)
 
1231
}
 
1232
 
 
1233
func (s *ParseBindSuite) checkParseFailsForArgs(c *gc.C, args string, expectedErrorSuffix string) {
 
1234
        err, parsedBindings := s.runParseBindWithArgs(args)
 
1235
        c.Check(err.Error(), gc.Equals, parseBindErrorPrefix+expectedErrorSuffix)
 
1236
        c.Check(parsedBindings, gc.IsNil)
1213
1237
}