Skip to content

Commit fe228b1

Browse files
committed
Merge 2.2 tip
2 parents ba41d4d + ad99c76 commit fe228b1

File tree

10 files changed

+3202
-591
lines changed

10 files changed

+3202
-591
lines changed

cmd/juju/application/bundle.go

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"time"
1515

1616
"github.com/juju/bundlechanges"
17+
"github.com/juju/cmd"
1718
"github.com/juju/errors"
1819
"github.com/juju/utils"
1920
"gopkg.in/juju/charm.v6-unstable"
@@ -61,7 +62,7 @@ func deployBundle(
6162
bundleConfigFile string,
6263
channel csparams.Channel,
6364
apiRoot DeployAPI,
64-
log deploymentLogger,
65+
ctx *cmd.Context,
6566
bundleStorage map[string]map[string]storage.Constraints,
6667
) (map[*charm.URL]*macaroon.Macaroon, error) {
6768

@@ -78,6 +79,10 @@ func deployBundle(
7879
}
7980
var verifyError error
8081
if bundleDir == "" {
82+
// Process includes in the bundle data.
83+
if err := processBundleIncludes(ctx.Dir, data); err != nil {
84+
return nil, errors.Annotate(err, "unable to process includes")
85+
}
8186
verifyError = data.Verify(verifyConstraints, verifyStorage)
8287
} else {
8388
// Process includes in the bundle data.
@@ -128,7 +133,7 @@ func deployBundle(
128133
channel: channel,
129134
api: apiRoot,
130135
bundleStorage: bundleStorage,
131-
log: log,
136+
ctx: ctx,
132137
data: data,
133138
unitStatus: unitStatus,
134139
ignoredMachines: make(map[string]bool, len(data.Applications)),
@@ -211,9 +216,10 @@ type bundleHandler struct {
211216
// in the bundle itself.
212217
bundleStorage map[string]map[string]storage.Constraints
213218

214-
// log is used to output messages to the user, so that the user can keep
215-
// track of the bundle deployment progress.
216-
log deploymentLogger
219+
// ctx is the command context, which is used to output messages to the
220+
// user, so that the user can keep track of the bundle deployment
221+
// progress.
222+
ctx *cmd.Context
217223

218224
// data is the original bundle data that we want to deploy.
219225
data *charm.BundleData
@@ -341,6 +347,9 @@ func (h *bundleHandler) addService(
341347
}
342348
resources := make(map[string]string)
343349
for resName, path := range p.LocalResources {
350+
if !filepath.IsAbs(path) {
351+
path = filepath.Clean(filepath.Join(h.bundleDir, path))
352+
}
344353
resources[resName] = path
345354
}
346355
for resName, revision := range p.Resources {
@@ -385,7 +394,7 @@ func (h *bundleHandler) addService(
385394

386395
// Deploy the application.
387396
logger.Debugf("application %s is deploying (charm %s)", p.Application, ch)
388-
h.log.Infof("Deploying charm %q", ch)
397+
h.ctx.Infof("Deploying charm %q", ch)
389398
if err := api.Deploy(application.DeployArgs{
390399
CharmID: chID,
391400
Cons: cons,
@@ -397,7 +406,7 @@ func (h *bundleHandler) addService(
397406
EndpointBindings: p.EndpointBindings,
398407
}); err == nil {
399408
for resName := range resNames2IDs {
400-
h.log.Infof("added resource %s", resName)
409+
h.ctx.Infof("added resource %s", resName)
401410
}
402411
return nil
403412
} else if !isErrServiceExists(err) {
@@ -420,15 +429,15 @@ func (h *bundleHandler) addService(
420429
// by the application Deploy call above.
421430
return errors.Annotatef(err, "cannot update options for application %q", p.Application)
422431
}
423-
h.log.Infof("configuration updated for application %s", p.Application)
432+
h.ctx.Infof("configuration updated for application %s", p.Application)
424433
}
425434
// Update application constraints.
426435
if p.Constraints != "" {
427436
if err := h.api.SetConstraints(p.Application, cons); err != nil {
428437
// This should never happen, as the bundle is already verified.
429438
return errors.Annotatef(err, "cannot update constraints for application %q", p.Application)
430439
}
431-
h.log.Infof("constraints applied for application %s", p.Application)
440+
h.ctx.Infof("constraints applied for application %s", p.Application)
432441
}
433442
return nil
434443
}
@@ -465,7 +474,7 @@ func (h *bundleHandler) addMachine(id string, p bundlechanges.AddMachineParams)
465474
default:
466475
msg = strings.Join(notify[:svcLen-1], ", ") + " and " + notify[svcLen-1]
467476
}
468-
h.log.Infof("avoid creating other machines to host %s units", msg)
477+
h.ctx.Infof("avoid creating other machines to host %s units", msg)
469478
return nil
470479
}
471480
cons, err := constraints.Parse(p.Constraints)
@@ -483,7 +492,7 @@ func (h *bundleHandler) addMachine(id string, p bundlechanges.AddMachineParams)
483492
// placement directives as lxd.
484493
if ct == "lxc" {
485494
if !h.warnedLXC {
486-
h.log.Infof("Bundle has one or more containers specified as lxc. lxc containers are deprecated in Juju 2.0. lxd containers will be deployed instead.")
495+
h.ctx.Infof("Bundle has one or more containers specified as lxc. lxc containers are deprecated in Juju 2.0. lxd containers will be deployed instead.")
487496
h.warnedLXC = true
488497
}
489498
ct = string(instance.LXD)
@@ -527,7 +536,7 @@ func (h *bundleHandler) addRelation(id string, p bundlechanges.AddRelationParams
527536
_, err := h.api.AddRelation([]string{ep1, ep2}, nil)
528537
if err == nil {
529538
// A new relation has been established.
530-
h.log.Infof("Related %q and %q", ep1, ep2)
539+
h.ctx.Infof("Related %q and %q", ep1, ep2)
531540
return nil
532541
}
533542
if isErrRelationExists(err) {
@@ -555,7 +564,7 @@ func (h *bundleHandler) addUnit(id string, p bundlechanges.AddUnitParams) error
555564
} else {
556565
msg = fmt.Sprintf("%d units already present", num)
557566
}
558-
h.log.Infof("avoid adding new units to application %s: %s", applicationName, msg)
567+
h.ctx.Infof("avoid adding new units to application %s: %s", applicationName, msg)
559568
}
560569
return nil
561570
}
@@ -605,7 +614,7 @@ func (h *bundleHandler) exposeService(id string, p bundlechanges.ExposeParams) e
605614
if err := h.api.Expose(application); err != nil {
606615
return errors.Annotatef(err, "cannot expose application %s", application)
607616
}
608-
h.log.Infof("application %s exposed", application)
617+
h.ctx.Infof("application %s exposed", application)
609618
return nil
610619
}
611620

@@ -834,7 +843,7 @@ func (h *bundleHandler) upgradeCharm(
834843
return errors.Annotatef(err, "cannot retrieve info for application %q", applicationName)
835844
}
836845
if existing.String() == id {
837-
h.log.Infof("reusing application %s (charm: %s)", applicationName, id)
846+
h.ctx.Infof("reusing application %s (charm: %s)", applicationName, id)
838847
return nil
839848
}
840849
url, err := charm.ParseURL(id)
@@ -876,9 +885,9 @@ func (h *bundleHandler) upgradeCharm(
876885
if err := h.api.SetCharm(cfg); err != nil {
877886
return errors.Annotatef(err, "cannot upgrade charm to %q", id)
878887
}
879-
h.log.Infof("upgraded charm for existing application %s (from %s to %s)", applicationName, existing, id)
888+
h.ctx.Infof("upgraded charm for existing application %s (from %s to %s)", applicationName, existing, id)
880889
for resName := range resNames2IDs {
881-
h.log.Infof("added resource %s", resName)
890+
h.ctx.Infof("added resource %s", resName)
882891
}
883892
return nil
884893
}
@@ -902,6 +911,8 @@ func isErrRelationExists(err error) bool {
902911
func processBundleIncludes(baseDir string, data *charm.BundleData) error {
903912

904913
for app, appData := range data.Applications {
914+
// A bundle isn't valid if there are no applications, and applications must
915+
// specify a charm at least, so we know appData must be non-nil.
905916
for key, value := range appData.Options {
906917
result, processed, err := processValue(baseDir, value)
907918
if err != nil {
@@ -923,6 +934,9 @@ func processBundleIncludes(baseDir string, data *charm.BundleData) error {
923934
}
924935

925936
for machine, machineData := range data.Machines {
937+
if machineData == nil {
938+
continue
939+
}
926940
for key, value := range machineData.Annotations {
927941
result, processed, err := processValue(baseDir, value)
928942
if err != nil {

cmd/juju/application/bundle_test.go

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"io/ioutil"
1010
"os"
1111
"path/filepath"
12+
"runtime"
1213
"sort"
1314
"strings"
1415
"time"
@@ -231,9 +232,6 @@ func (s *BundleDeployCharmStoreSuite) TestDeployBundleLocalPath(c *gc.C) {
231232
}
232233

233234
func (s *BundleDeployCharmStoreSuite) TestDeployBundleLocalResources(c *gc.C) {
234-
dir := c.MkDir()
235-
testcharms.Repo.ClonedDir(dir, "dummy-resource")
236-
path := filepath.Join(dir, "mybundle")
237235
data := `
238236
series: quantal
239237
applications:
@@ -242,12 +240,14 @@ func (s *BundleDeployCharmStoreSuite) TestDeployBundleLocalResources(c *gc.C) {
242240
series: quantal
243241
num_units: 1
244242
resources:
245-
dummy: %s
243+
dummy: ./dummy-resource.zip
246244
`
247-
data = fmt.Sprintf(data, filepath.Join(dir, "dummy-resource", "dummy-resource.zip"))
248-
err := ioutil.WriteFile(path, []byte(data), 0644)
249-
c.Assert(err, jc.ErrorIsNil)
250-
_, err = runDeploy(c, path)
245+
dir := s.makeBundleDir(c, data)
246+
testcharms.Repo.ClonedDir(dir, "dummy-resource")
247+
c.Assert(
248+
ioutil.WriteFile(filepath.Join(dir, "dummy-resource.zip"), []byte("zip file"), 0644),
249+
jc.ErrorIsNil)
250+
_, err := runDeploy(c, dir)
251251
c.Assert(err, jc.ErrorIsNil)
252252
s.assertCharmsUploaded(c, "local:quantal/dummy-resource-0")
253253
s.assertApplicationsDeployed(c, map[string]serviceInfo{
@@ -401,15 +401,19 @@ func (s *BundleDeployCharmStoreSuite) Client() *csclient.Client {
401401
// local repository and then deploy it. It returns the bundle deployment output
402402
// and error.
403403
func (s *BundleDeployCharmStoreSuite) DeployBundleYAML(c *gc.C, content string, extraArgs ...string) (string, error) {
404+
bundlePath := s.makeBundleDir(c, content)
405+
args := append([]string{bundlePath}, extraArgs...)
406+
return runDeploy(c, args...)
407+
}
408+
409+
func (s *BundleDeployCharmStoreSuite) makeBundleDir(c *gc.C, content string) string {
404410
bundlePath := filepath.Join(c.MkDir(), "example")
405411
c.Assert(os.Mkdir(bundlePath, 0777), jc.ErrorIsNil)
406-
defer os.RemoveAll(bundlePath)
407412
err := ioutil.WriteFile(filepath.Join(bundlePath, "bundle.yaml"), []byte(content), 0644)
408413
c.Assert(err, jc.ErrorIsNil)
409414
err = ioutil.WriteFile(filepath.Join(bundlePath, "README.md"), []byte("README"), 0644)
410415
c.Assert(err, jc.ErrorIsNil)
411-
args := append([]string{bundlePath}, extraArgs...)
412-
return runDeploy(c, args...)
416+
return bundlePath
413417
}
414418

415419
var deployBundleErrorsTests = []struct {
@@ -425,7 +429,7 @@ var deployBundleErrorsTests = []struct {
425429
num_units: 1
426430
`,
427431
err: `the provided bundle has the following errors:
428-
charm path in application "mysql" does not exist: mysql`,
432+
charm path in application "mysql" does not exist: .*mysql`,
429433
}, {
430434
about: "charm store charm not found",
431435
content: `
@@ -640,7 +644,7 @@ func (s *BundleDeployCharmStoreSuite) TestDeployBundleLocalDeploymentBadConfig(c
640644
- ["wordpress:db", "mysql:server"]
641645
`, wordpressPath, mysqlPath),
642646
"--bundle-config", "missing-file")
643-
c.Assert(err, gc.ErrorMatches, "unable to open bundle-config file: open .*missing-file: no such file or directory")
647+
c.Assert(err, gc.ErrorMatches, "unable to open bundle-config file: "+missingFileRegex("missing-file"))
644648
}
645649

646650
func (s *BundleDeployCharmStoreSuite) TestDeployBundleLocalDeploymentWithBundleConfig(c *gc.C) {
@@ -1473,7 +1477,7 @@ func (*ProcessIncludesSuite) TestMissingFile(c *gc.C) {
14731477
value := "include-file://simple"
14741478
result, changed, err := processValue("", value)
14751479

1476-
c.Check(err, gc.ErrorMatches, "unable to read file: open simple: no such file or directory")
1480+
c.Check(err, gc.ErrorMatches, "unable to read file: "+missingFileRegex("simple"))
14771481
c.Check(changed, jc.IsFalse)
14781482
c.Check(result, gc.IsNil)
14791483
}
@@ -1559,6 +1563,7 @@ func (*ProcessIncludesSuite) TestBundleReplacements(c *gc.C) {
15591563
machines:
15601564
1:
15611565
annotations: {foo: bar, baz: "include-file://machine" }
1566+
2:
15621567
`
15631568

15641569
baseDir := c.MkDir()
@@ -1655,7 +1660,7 @@ func (s *ProcessBundleConfigSuite) TestNoFile(c *gc.C) {
16551660

16561661
func (s *ProcessBundleConfigSuite) TestBadFile(c *gc.C) {
16571662
err := processBundleConfig(s.bundleData, "bad")
1658-
c.Assert(err, gc.ErrorMatches, "unable to open bundle-config file: open .*bad: no such file or directory")
1663+
c.Assert(err, gc.ErrorMatches, "unable to open bundle-config file: "+missingFileRegex("bad"))
16591664
}
16601665

16611666
func (s *ProcessBundleConfigSuite) TestGoodYAML(c *gc.C) {
@@ -1775,3 +1780,11 @@ func (s *ProcessBundleConfigSuite) TestRemainingFields(c *gc.C) {
17751780
c.Check(django.EndpointBindings, jc.DeepEquals, map[string]string{
17761781
"where": "dmz"})
17771782
}
1783+
1784+
func missingFileRegex(filename string) string {
1785+
text := "no such file or directory"
1786+
if runtime.GOOS == "windows" {
1787+
text = "The system cannot find the file specified."
1788+
}
1789+
return fmt.Sprintf("open .*%s: %s", filename, text)
1790+
}

cmd/juju/application/deploy.go

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -774,28 +774,27 @@ func (c *DeployCommand) maybePredeployedLocalCharm() (deployFn, error) {
774774

775775
func (c *DeployCommand) maybeReadLocalBundle() (deployFn, error) {
776776
bundleFile := c.CharmOrBundle
777-
var (
778-
bundleFilePath string
779-
resolveRelativeBundleFilePath bool
780-
)
777+
var bundleDir string
778+
isDir := false
779+
resolveDir := false
781780

782781
bundleData, err := charmrepo.ReadBundleFile(bundleFile)
783782
if err != nil {
784783
// We may have been given a local bundle archive or exploded directory.
785-
bundle, url, pathErr := charmrepo.NewBundleAtPath(bundleFile)
784+
bundle, _, pathErr := charmrepo.NewBundleAtPath(bundleFile)
786785
if charmrepo.IsInvalidPathError(pathErr) {
787786
return nil, errors.Errorf(""+
788787
"The charm or bundle %q is ambiguous.\n"+
789788
"To deploy a local charm or bundle, run `juju deploy ./%[1]s`.\n"+
790789
"To deploy a charm or bundle from the store, run `juju deploy cs:%[1]s`.",
791-
c.CharmOrBundle,
790+
bundleFile,
792791
)
793792
}
794793
if pathErr != nil {
795794
// If the bundle files existed but we couldn't read them,
796795
// then return that error rather than trying to interpret
797796
// as a charm.
798-
if info, statErr := os.Stat(c.CharmOrBundle); statErr == nil {
797+
if info, statErr := os.Stat(bundleFile); statErr == nil {
799798
if info.IsDir() {
800799
if _, ok := pathErr.(*charmrepo.NotFoundError); !ok {
801800
return nil, pathErr
@@ -808,28 +807,34 @@ func (c *DeployCommand) maybeReadLocalBundle() (deployFn, error) {
808807
}
809808

810809
bundleData = bundle.Data()
811-
bundleFile = url.String()
812810
if info, err := os.Stat(bundleFile); err == nil && info.IsDir() {
813-
bundleFilePath = bundleFile
811+
resolveDir = true
812+
isDir = true
814813
}
815814
} else {
816-
resolveRelativeBundleFilePath = true
815+
resolveDir = true
817816
}
818817

819818
if err := c.validateBundleFlags(); err != nil {
820819
return nil, errors.Trace(err)
821820
}
822821

823822
return func(ctx *cmd.Context, apiRoot DeployAPI) error {
824-
// For local bundles, we extract the local path of the bundle
825-
// directory.
826-
if resolveRelativeBundleFilePath {
827-
bundleFilePath = filepath.Dir(ctx.AbsPath(bundleFile))
823+
if resolveDir {
824+
if isDir {
825+
// If we get to here bundleFile is a directory, in which case
826+
// we should use the absolute path as the bundFilePath, or it is
827+
// an archive, in which case we should pass the empty string.
828+
bundleDir = ctx.AbsPath(bundleFile)
829+
} else {
830+
// If the bundle is defined with just a yaml file, the bundle
831+
// path is the directory that holds the file.
832+
bundleDir = filepath.Dir(ctx.AbsPath(bundleFile))
833+
}
828834
}
829-
830835
return errors.Trace(c.deployBundle(
831836
ctx,
832-
bundleFilePath,
837+
bundleDir,
833838
bundleData,
834839
c.Channel,
835840
apiRoot,

cmd/jujud/agent/machine.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ func upgradeCertificateDNSNames(config agent.ConfigSetter) error {
459459
}
460460

461461
update := false
462-
requiredDNSNames := []string{"local", "juju-apiserver", "juju-mongodb"}
462+
requiredDNSNames := []string{"localhost", "juju-apiserver", "juju-mongodb"}
463463
for _, dnsName := range requiredDNSNames {
464464
if dnsNames.Contains(dnsName) {
465465
continue

cmd/jujud/agent/machine_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ func (s *MachineSuite) testCertificateDNSUpdated(c *gc.C, a *MachineAgent) {
11251125
stateInfo, _ := a.CurrentConfig().StateServingInfo()
11261126
srvCert, _, err := cert.ParseCertAndKey(stateInfo.Cert, stateInfo.PrivateKey)
11271127
c.Assert(err, jc.ErrorIsNil)
1128-
expectedDnsNames := set.NewStrings("local", "juju-apiserver", "juju-mongodb")
1128+
expectedDnsNames := set.NewStrings("localhost", "juju-apiserver", "juju-mongodb")
11291129
certDnsNames := set.NewStrings(srvCert.DNSNames...)
11301130
c.Check(expectedDnsNames.Difference(certDnsNames).IsEmpty(), jc.IsTrue)
11311131

0 commit comments

Comments
 (0)