Skip to content

Commit

Permalink
Merge trunk and fix conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
wallyworld committed Jun 9, 2014
2 parents 78042c9 + d3f76d4 commit 1a799af
Show file tree
Hide file tree
Showing 412 changed files with 3,041 additions and 8,600 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Expand Up @@ -3,8 +3,8 @@ cmd/jujud/jujud
cmd/builddb/builddb
cmd/charmd/charmd
cmd/charmload/charmload
./tags
./TAGS
tags
TAGS
.emacs.desktop
.emacs.desktop.lock
*.test
Expand Down
44 changes: 29 additions & 15 deletions CONTRIBUTING.md
Expand Up @@ -60,6 +60,35 @@ $ ln -s ../../scripts/pre-push.bash .git/hooks/pre-push
Using pre-push requires git 1.8.2 or later, alternatively running the check as a
pre-commit hook also works.


## Dependency management

In the top-level directory of the juju repo, there is a file, dependencies.tsv, that holds the
revision ids of all the external projects that juju depends on. This file is used by [godeps](launchpad.net/godeps)
to freeze the code in external repositories so that juju is insulated from changes to those repos.

After getting the juju code, you need to get godeps:

```shell
go get launchpad.net/godeps
```

This installs the godeps application. You can then run godeps from the root of juju, to set the revision number on the external repositories:

```shell
godeps -u dependencies.tsv
```

Now you're ready to build, run, test, etc.

Note that you'll need to do this any time you switch to a branch that has a different dependencies.tsv file. In practice, you can wait until you get a compile error about an external package not existing/having an incorrect API, and then rerun godeps.

If you update a repo that juju depends on, you'll need to recreate depdencies.tsv:

```shell
$ godeps -t $(go list github.com/juju/juju/...) > dependencies.tsv
```

## Working

All development should be done on feature branches based on a current copy of master.
Expand Down Expand Up @@ -207,22 +236,7 @@ After a proposal has received an LGTM, the landing must be notified to test and
the code into master. This is done by a member of the juju project adding the magic
string $$merge$$ in a comment.

## Dependency management

In the top-level directory, there is a file, dependencies.tsv, that holds the
revision ids of all the external projects that juju depends on. The tab-separated
columns in the file are the project name, the type version control system used by
that project, and the revision id and number respectively.

This file is generated by running the godeps command (which you can obtain using the
command `go get launchpad.net/godeps') on a juju installation with all freshly
downloaded directories.

The bash commands used to generate it from scratch are as follows:

```shell
$ export GOPATH=/tmp/juju-build
$ go get github.com/juju/juju/...
$ go test github.com/juju/juju/...
$ godeps -t $(go list github.com/juju/juju/...) > dependencies.tsv
```
2 changes: 1 addition & 1 deletion agent/agent.go
Expand Up @@ -17,12 +17,12 @@ import (

"github.com/juju/errors"
"github.com/juju/loggo"
"github.com/juju/utils"

"github.com/juju/juju/instance"
"github.com/juju/juju/state"
"github.com/juju/juju/state/api"
"github.com/juju/juju/state/api/params"
"github.com/juju/juju/utils"
"github.com/juju/juju/version"
)

Expand Down
2 changes: 1 addition & 1 deletion agent/bootstrap.go
Expand Up @@ -7,13 +7,13 @@ import (
"fmt"

"github.com/juju/names"
"github.com/juju/utils"

"github.com/juju/juju/constraints"
"github.com/juju/juju/environs/config"
"github.com/juju/juju/instance"
"github.com/juju/juju/state"
"github.com/juju/juju/state/api/params"
"github.com/juju/juju/utils"
"github.com/juju/juju/version"
)

Expand Down
2 changes: 1 addition & 1 deletion agent/bootstrap_test.go
Expand Up @@ -5,6 +5,7 @@ package agent_test

import (
jc "github.com/juju/testing/checkers"
"github.com/juju/utils"
gc "launchpad.net/gocheck"

"github.com/juju/juju/agent"
Expand All @@ -16,7 +17,6 @@ import (
"github.com/juju/juju/state"
"github.com/juju/juju/state/api/params"
"github.com/juju/juju/testing"
"github.com/juju/juju/utils"
"github.com/juju/juju/version"
)

Expand Down
2 changes: 1 addition & 1 deletion agent/format-1.16_whitebox_test.go
Expand Up @@ -12,10 +12,10 @@ import (
"path/filepath"

jc "github.com/juju/testing/checkers"
"github.com/juju/utils"
gc "launchpad.net/gocheck"

"github.com/juju/juju/testing"
"github.com/juju/juju/utils"
"github.com/juju/juju/version"
)

Expand Down
2 changes: 1 addition & 1 deletion agent/format-1.18_whitebox_test.go
Expand Up @@ -11,11 +11,11 @@ import (
"path/filepath"

jc "github.com/juju/testing/checkers"
"github.com/juju/utils"
gc "launchpad.net/gocheck"

"github.com/juju/juju/state/api/params"
"github.com/juju/juju/testing"
"github.com/juju/juju/utils"
"github.com/juju/juju/version"
)

Expand Down
2 changes: 1 addition & 1 deletion agent/format.go
Expand Up @@ -8,7 +8,7 @@ import (
"fmt"
"strings"

"github.com/juju/juju/utils"
"github.com/juju/utils"
)

// Current agent config format is defined as follows:
Expand Down
2 changes: 1 addition & 1 deletion agent/identity.go
Expand Up @@ -7,7 +7,7 @@ import (
"fmt"
"os"

"github.com/juju/juju/utils"
"github.com/juju/utils"
)

func WriteSystemIdentityFile(c Config) error {
Expand Down
4 changes: 2 additions & 2 deletions agent/mongo/mongo.go
Expand Up @@ -15,14 +15,14 @@ import (
"path/filepath"

"github.com/juju/loggo"
"github.com/juju/utils"
"github.com/juju/utils/apt"
"labix.org/v2/mgo"

"github.com/juju/juju/instance"
"github.com/juju/juju/replicaset"
"github.com/juju/juju/state/api/params"
"github.com/juju/juju/upstart"
"github.com/juju/juju/utils"
"github.com/juju/juju/utils/apt"
"github.com/juju/juju/version"
)

Expand Down
2 changes: 1 addition & 1 deletion agent/mongo/mongo_test.go
Expand Up @@ -16,14 +16,14 @@ import (

"github.com/juju/testing"
jc "github.com/juju/testing/checkers"
"github.com/juju/utils"
gc "launchpad.net/gocheck"

"github.com/juju/juju/agent/mongo"
"github.com/juju/juju/instance"
"github.com/juju/juju/state/api/params"
coretesting "github.com/juju/juju/testing"
"github.com/juju/juju/upstart"
"github.com/juju/juju/utils"
"github.com/juju/juju/version"
)

Expand Down
2 changes: 1 addition & 1 deletion agent/tools/tools_test.go
Expand Up @@ -38,7 +38,7 @@ func (t *ToolsSuite) TestPackageDependencies(c *gc.C) {
// resulting slice has that prefix removed to keep the output short.
c.Assert(testing.FindJujuCoreImports(c, "github.com/juju/juju/agent/tools"),
gc.DeepEquals,
[]string{"juju/arch", "tools", "utils/set", "version"})
[]string{"juju/arch", "tools", "version"})
}

const toolsFile = "downloaded-tools.txt"
Expand Down
1 change: 0 additions & 1 deletion audit/audit_test.go
Expand Up @@ -7,7 +7,6 @@ import (
"testing"

"github.com/juju/loggo"

jc "github.com/juju/testing/checkers"
gc "launchpad.net/gocheck"
)
Expand Down
85 changes: 79 additions & 6 deletions charm/actions.go
Expand Up @@ -4,6 +4,7 @@
package charm

import (
"errors"
"fmt"
"io"
"io/ioutil"
Expand All @@ -19,7 +20,7 @@ var paramNameRule = regexp.MustCompile("^[a-z$](?:[a-z-]*[a-z])?$")
// Actions defines the available actions for the charm. Additional params
// may be added as metadata at a future time (e.g. version.)
type Actions struct {
ActionSpecs map[string]ActionSpec `yaml:"actions"`
ActionSpecs map[string]ActionSpec `yaml:"actions,omitempty" bson:",omitempty"`
}

// ActionSpec is a definition of the parameters and traits of an Action.
Expand All @@ -30,6 +31,10 @@ type ActionSpec struct {
Params map[string]interface{}
}

func NewActions() *Actions {
return &Actions{}
}

// ReadActions builds an Actions spec from a charm's actions.yaml.
func ReadActionsYaml(r io.Reader) (*Actions, error) {
data, err := ioutil.ReadAll(r)
Expand All @@ -45,16 +50,84 @@ func ReadActionsYaml(r io.Reader) (*Actions, error) {
if valid := actionNameRule.MatchString(name); !valid {
return nil, fmt.Errorf("bad action name %s", name)
}
_, err := gojsonschema.NewJsonSchemaDocument(actionSpec.Params)
if err != nil {
return nil, fmt.Errorf("invalid params schema for action schema %s: %v", name, err)
}

for paramName, _ := range unmarshaledActions.ActionSpecs[name].Params {
// Make sure the parameters are acceptable.
cleansedParams := make(map[string]interface{})
for paramName, param := range unmarshaledActions.ActionSpecs[name].Params {
if valid := paramNameRule.MatchString(paramName); !valid {
return nil, fmt.Errorf("bad param name %s", paramName)
}

// Clean any map[interface{}]interface{}s out so they don't
// cause problems with BSON serialization later.
cleansedParam, err := cleanse(param)
if err != nil {
return nil, err
}
cleansedParams[paramName] = cleansedParam
}

// Now substitute the cleansed map into the original.
var swap = unmarshaledActions.ActionSpecs[name]
swap.Params = cleansedParams
unmarshaledActions.ActionSpecs[name] = swap

// Make sure the new Params doc conforms to JSON-Schema
// Draft 4 (http://json-schema.org/latest/json-schema-core.html)
_, err = gojsonschema.NewJsonSchemaDocument(actionSpec.Params)
if err != nil {
return nil, fmt.Errorf("invalid params schema for action schema %s: %v", name, err)
}

}
return &unmarshaledActions, nil
}

func cleanse(input interface{}) (interface{}, error) {
switch typedInput := input.(type) {

// In this case, recurse in.
case map[string]interface{}:
newMap := make(map[string]interface{})
for key, value := range typedInput {
newValue, err := cleanse(value)
if err != nil {
return nil, err
}
newMap[key] = newValue
}
return newMap, nil

// Coerce keys to strings and error out if there's a problem; then recurse.
case map[interface{}]interface{}:
newMap := make(map[string]interface{})
for key, value := range typedInput {
typedKey, ok := key.(string)
if !ok {
return nil, errors.New("map keyed with non-string value")
}
newMapValue, err := cleanse(value)
if err != nil {
return nil, err
}
newMap[typedKey] = newMapValue
}
return newMap, nil

// Recurse
case []interface{}:
newSlice := make([]interface{}, 0)
for _, sliceValue := range typedInput {
newSliceValue, err := cleanse(sliceValue)
if err != nil {
return nil, errors.New("map keyed with non-string value")
}
newSlice = append(newSlice, newSliceValue)
}
return newSlice, nil

// Other kinds of values are OK.
default:
return input, nil
}
}

0 comments on commit 1a799af

Please sign in to comment.