brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From andreatu...@apache.org
Subject [06/10] brooklyn-client git commit: move rest-client to brooklyn-client
Date Sat, 10 Sep 2016 17:14:43 GMT
http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/entity.go
----------------------------------------------------------------------
diff --git a/cli/commands/entity.go b/cli/commands/entity.go
new file mode 100644
index 0000000..e5903c9
--- /dev/null
+++ b/cli/commands/entity.go
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	"github.com/apache/brooklyn-client/api/entities"
+	"github.com/apache/brooklyn-client/api/entity_sensors"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/apache/brooklyn-client/terminal"
+	"github.com/urfave/cli"
+	"os"
+)
+
+type Entity struct {
+	network *net.Network
+}
+
+func NewEntity(network *net.Network) (cmd *Entity) {
+	cmd = new(Entity)
+	cmd.network = network
+	return
+}
+
+func (cmd *Entity) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "entity",
+		Aliases:     []string{"entities", "ent", "ents"},
+		Description: "Show the entities of an application or entity",
+		Usage:       "BROOKLYN_NAME SCOPE entity [ENTITYID]",
+		Flags: []cli.Flag{
+			cli.StringSliceFlag{
+				Name:  "children, c",
+				Usage: "List children of the entity",
+			},
+		},
+	}
+}
+
+func (cmd *Entity) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	if c.NumFlags() > 0 && c.FlagNames()[0] == "children" {
+		cmd.listentity(scope.Application, c.StringSlice("children")[0])
+	} else {
+		if c.Args().Present() {
+			cmd.show(scope.Application, c.Args().First())
+		} else {
+			if scope.Entity == scope.Application {
+				cmd.listapp(scope.Application)
+			} else {
+				cmd.listentity(scope.Application, scope.Entity)
+			}
+		}
+	}
+}
+
+const serviceStateSensor = "service.state"
+const serviceIsUp = "service.isUp"
+
+func (cmd *Entity) show(application, entity string) {
+	summary, err := entities.GetEntity(cmd.network, application, entity)
+	if nil != err {
+		fmt.Fprintf(os.Stderr, "Error: %s\n", err)
+		os.Exit(1)
+	}
+	table := terminal.NewTable([]string{"Id:", summary.Id})
+	table.Add("Name:", summary.Name)
+	configState, err := entity_sensors.CurrentState(cmd.network, application, entity)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	if serviceState, ok := configState[serviceStateSensor]; ok {
+		table.Add("Status:", fmt.Sprintf("%v", serviceState))
+	}
+	if serviceIsUp, ok := configState[serviceIsUp]; ok {
+		table.Add("ServiceUp:", fmt.Sprintf("%v", serviceIsUp))
+	}
+	table.Add("Type:", summary.Type)
+	table.Add("CatalogItemId:", summary.CatalogItemId)
+	table.Print()
+}
+
+func (cmd *Entity) listapp(application string) {
+	entitiesList, err := entities.EntityList(cmd.network, application)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	table := terminal.NewTable([]string{"Id", "Name", "Type"})
+	for _, entityitem := range entitiesList {
+		table.Add(entityitem.Id, entityitem.Name, entityitem.Type)
+	}
+	table.Print()
+}
+
+func (cmd *Entity) listentity(application string, entity string) {
+	entitiesList, err := entities.Children(cmd.network, application, entity)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+
+	table := terminal.NewTable([]string{"Id", "Name", "Type"})
+	for _, entityitem := range entitiesList {
+		table.Add(entityitem.Id, entityitem.Name, entityitem.Type)
+	}
+	table.Print()
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/invoke.go
----------------------------------------------------------------------
diff --git a/cli/commands/invoke.go b/cli/commands/invoke.go
new file mode 100644
index 0000000..a719ed7
--- /dev/null
+++ b/cli/commands/invoke.go
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"errors"
+	"fmt"
+	"github.com/apache/brooklyn-client/api/entity_effectors"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/urfave/cli"
+	"io/ioutil"
+	"strings"
+)
+
+type Invoke struct {
+	network *net.Network
+}
+
+type Stop struct {
+	Invoke
+}
+
+type Start struct {
+	Invoke
+}
+
+type Restart struct {
+	Invoke
+}
+
+func NewInvoke(network *net.Network) (cmd *Invoke) {
+	cmd = new(Invoke)
+	cmd.network = network
+	return
+}
+
+func NewInvokeStop(network *net.Network) (cmd *Stop) {
+	cmd = new(Stop)
+	cmd.network = network
+	return
+}
+
+func NewInvokeStart(network *net.Network) (cmd *Start) {
+	cmd = new(Start)
+	cmd.network = network
+	return
+}
+
+func NewInvokeRestart(network *net.Network) (cmd *Restart) {
+	cmd = new(Restart)
+	cmd.network = network
+	return
+}
+
+var paramFlags = []cli.Flag{
+	cli.StringSliceFlag{
+		Name:  "param, P",
+		Usage: "Parameter and value separated by '=', e.g. -P x=y. If the parameter value is complex or multi-" +
+		       "lined it may be provided in a file and referenced as: '@<file>', e.g. -P x=@/path/to/file.",
+	},
+}
+
+func (cmd *Invoke) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "invoke",
+		Description: "Invoke an effector of an application and entity",
+		Usage:       "BROOKLYN_NAME EFF-SCOPE invoke [ parameter-options ]",
+		Flags:       paramFlags,
+	}
+}
+
+func (cmd *Stop) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "stop",
+		Description: "Invoke stop effector on an application and entity",
+		Usage:       "BROOKLYN_NAME ENT-SCOPE stop [ parameter-options ]",
+		Flags:       paramFlags,
+	}
+}
+
+func (cmd *Start) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "start",
+		Description: "Invoke start effector on an application and entity",
+		Usage:       "BROOKLYN_NAME ENT-SCOPE start [ parameter-options ]",
+		Flags:       paramFlags,
+	}
+}
+
+func (cmd *Restart) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "restart",
+		Description: "Invoke restart effector on an application and entity",
+		Usage:       "BROOKLYN_NAME ENT-SCOPE restart [ parameter-options ]",
+		Flags:       paramFlags,
+	}
+}
+
+func (cmd *Invoke) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	parms := c.StringSlice("param")
+	invoke(cmd.network, scope.Application, scope.Entity, scope.Effector, parms)
+}
+
+const stopEffector = "stop"
+
+func (cmd *Stop) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	parms := c.StringSlice("param")
+	invoke(cmd.network, scope.Application, scope.Entity, stopEffector, parms)
+}
+
+const startEffector = "start"
+
+func (cmd *Start) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	parms := c.StringSlice("param")
+	invoke(cmd.network, scope.Application, scope.Entity, startEffector, parms)
+}
+
+const restartEffector = "restart"
+
+func (cmd *Restart) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	parms := c.StringSlice("param")
+	invoke(cmd.network, scope.Application, scope.Entity, restartEffector, parms)
+}
+
+func invoke(network *net.Network, application, entity, effector string, parms []string) {
+	names, vals, err := extractParams(parms)
+	result, err := entity_effectors.TriggerEffector(network, application, entity, effector, names, vals)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	} else {
+		if "" != result {
+			fmt.Println(result)
+		}
+	}
+}
+
+func extractParams(parms []string) ([]string, []string, error) {
+	names := make([]string, len(parms))
+	vals := make([]string, len(parms))
+	var err error
+	for i, parm := range parms {
+		index := strings.Index(parm, "=")
+		if index < 0 {
+			return names, vals, errors.New("Parameter value not provided: " + parm)
+		}
+		names[i] = parm[0:index]
+		vals[i], err = extractParamValue(parm[index+1:])
+	}
+	return names, vals, err
+}
+
+const paramDataPrefix string = "@"
+
+func extractParamValue(rawParam string) (string, error) {
+	var err error
+	var val string
+	if strings.HasPrefix(rawParam, paramDataPrefix) {
+		// strip the data prefix from the filename before reading
+		val, err = readParamFromFile(rawParam[len(paramDataPrefix):])
+	} else {
+		val = rawParam
+		err = nil
+	}
+	return val, err
+}
+
+// returning a string rather than byte array, assuming non-binary
+// TODO - if necessary support binary data sending to effector
+func readParamFromFile(filename string) (string, error) {
+	dat, err := ioutil.ReadFile(filename)
+	return string(dat), err
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/list.go
----------------------------------------------------------------------
diff --git a/cli/commands/list.go b/cli/commands/list.go
new file mode 100644
index 0000000..7758568
--- /dev/null
+++ b/cli/commands/list.go
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	"github.com/apache/brooklyn-client/command"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/urfave/cli"
+	"strings"
+)
+
+type List struct {
+	network      *net.Network
+	listCommands map[string]command.Command
+}
+
+func NewList(network *net.Network) (cmd *List) {
+	cmd = new(List)
+	cmd.network = network
+	cmd.listCommands = map[string]command.Command{
+	//		ListApplicationCommand: NewApplications(cmd.network),
+	//		ListEntityCommand: NewEntities(cmd.network),
+	//		ListSensorCommand: NewSensors(cmd.network),
+	//		ListEffectorCommand: NewEffector(cmd.network),
+	}
+	return
+}
+
+const ListApplicationCommand = "application"
+const ListEntityCommand = "entities"
+const ListSensorCommand = "sensors"
+const ListEffectorCommand = "effectors"
+
+var listCommands = []string{
+	ListApplicationCommand,
+	ListEntityCommand,
+	ListSensorCommand,
+	ListEffectorCommand,
+}
+var listCommandsUsage = strings.Join(listCommands, " | ")
+
+func (cmd *List) SubCommandNames() []string {
+	return listCommands
+}
+
+func (cmd *List) SubCommand(name string) command.Command {
+	return cmd.listCommands[name]
+}
+
+func (cmd *List) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "list",
+		Description: "List details for a variety of operands",
+		Usage:       "BROOKLYN_NAME SCOPE list (" + listCommandsUsage + ")",
+		Flags:       []cli.Flag{},
+		Operands: []command_metadata.CommandMetadata{
+			cmd.SubCommand(ListApplicationCommand).Metadata(),
+			cmd.SubCommand(ListEntityCommand).Metadata(),
+			cmd.SubCommand(ListSensorCommand).Metadata(),
+			cmd.SubCommand(ListEffectorCommand).Metadata(),
+		},
+	}
+}
+
+func (cmd *List) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	fmt.Printf("Unrecognised item for list, please use one of (%s)\n", listCommandsUsage)
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/locations.go
----------------------------------------------------------------------
diff --git a/cli/commands/locations.go b/cli/commands/locations.go
new file mode 100644
index 0000000..f197130
--- /dev/null
+++ b/cli/commands/locations.go
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"github.com/apache/brooklyn-client/api/locations"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/apache/brooklyn-client/terminal"
+	"github.com/urfave/cli"
+)
+
+type Locations struct {
+	network *net.Network
+}
+
+func NewLocations(network *net.Network) (cmd *Locations) {
+	cmd = new(Locations)
+	cmd.network = network
+	return
+}
+
+func (cmd *Locations) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "locations",
+		Description: "* List the available locations",
+		Usage:       "BROOKLYN_NAME locations",
+		Flags:       []cli.Flag{},
+	}
+}
+
+func (cmd *Locations) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	locationList, err := locations.LocationList(cmd.network)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	table := terminal.NewTable([]string{"Id", "Name", "Spec"})
+	for _, location := range locationList {
+		table.Add(location.Id, location.Name, location.Spec)
+	}
+	table.Print()
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/login.go
----------------------------------------------------------------------
diff --git a/cli/commands/login.go b/cli/commands/login.go
new file mode 100644
index 0000000..df63b33
--- /dev/null
+++ b/cli/commands/login.go
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	"github.com/apache/brooklyn-client/api/version"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/io"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/urfave/cli"
+	"golang.org/x/crypto/ssh/terminal"
+	"syscall"
+)
+
+type Login struct {
+	network *net.Network
+	config  *io.Config
+}
+
+func NewLogin(network *net.Network, config *io.Config) (cmd *Login) {
+	cmd = new(Login)
+	cmd.network = network
+	cmd.config = config
+	return
+}
+
+func (cmd *Login) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "login",
+		Description: "Login to brooklyn",
+		Usage:       "BROOKLYN_NAME login URL [USER [PASSWORD]]",
+		Flags:       []cli.Flag{},
+	}
+}
+
+func (cmd *Login) Run(scope scope.Scope, c *cli.Context) {
+	if !c.Args().Present() {
+		error_handler.ErrorExit("A URL must be provided as the first argument", error_handler.CLIUsageErrorExitCode)
+	}
+
+	// If an argument was not supplied, it is set to empty string
+	cmd.network.BrooklynUrl = c.Args().Get(0)
+	cmd.network.BrooklynUser = c.Args().Get(1)
+	cmd.network.BrooklynPass = c.Args().Get(2)
+	cmd.network.SkipSslChecks = c.GlobalBool("skipSslChecks")
+
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+
+	// Strip off trailing '/' from URL if present.
+	if cmd.network.BrooklynUrl[len(cmd.network.BrooklynUrl)-1] == '/' {
+		if len(cmd.network.BrooklynUrl) == 1 {
+			error_handler.ErrorExit("URL must not be a single \"/\" character", error_handler.CLIUsageErrorExitCode)
+		}
+		cmd.network.BrooklynUrl = cmd.network.BrooklynUrl[0 : len(cmd.network.BrooklynUrl)-1]
+	}
+
+	// Prompt for password if not supplied (password is not echoed to screen
+	if cmd.network.BrooklynUser != "" && cmd.network.BrooklynPass == "" {
+		fmt.Print("Enter Password: ")
+		bytePassword, err := terminal.ReadPassword(int(syscall.Stdin))
+		if err != nil {
+			error_handler.ErrorExit(err)
+		}
+		fmt.Printf("\n")
+		cmd.network.BrooklynPass = string(bytePassword)
+	}
+
+	if cmd.config.Map == nil {
+		cmd.config.Map = make(map[string]interface{})
+	}
+	// now persist these credentials to the yaml file
+	auth, ok := cmd.config.Map["auth"].(map[string]interface{})
+	if !ok {
+		auth = make(map[string]interface{})
+		cmd.config.Map["auth"] = auth
+	}
+
+	auth[cmd.network.BrooklynUrl] = map[string]string{
+		"username": cmd.network.BrooklynUser,
+		"password": cmd.network.BrooklynPass,
+	}
+
+	cmd.config.Map["target"] = cmd.network.BrooklynUrl
+	cmd.config.Map["skipSslChecks"] = cmd.network.SkipSslChecks
+	cmd.config.Write()
+
+	loginVersion, err := version.Version(cmd.network)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	fmt.Printf("Connected to Brooklyn version %s at %s\n", loginVersion.Version, cmd.network.BrooklynUrl)
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/policy.go
----------------------------------------------------------------------
diff --git a/cli/commands/policy.go b/cli/commands/policy.go
new file mode 100644
index 0000000..1d587fd
--- /dev/null
+++ b/cli/commands/policy.go
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"github.com/apache/brooklyn-client/api/entity_policies"
+	"github.com/apache/brooklyn-client/api/entity_policy_config"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/models"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/apache/brooklyn-client/terminal"
+	"github.com/urfave/cli"
+	"sort"
+)
+
+type Policy struct {
+	network *net.Network
+}
+
+type policyConfigList []models.PolicyConfigList
+
+// Len is the number of elements in the collection.
+func (configs policyConfigList) Len() int {
+	return len(configs)
+}
+
+// Less reports whether the element with
+// index i should sort before the element with index j.
+func (configs policyConfigList) Less(i, j int) bool {
+	return configs[i].Name < configs[j].Name
+}
+
+// Swap swaps the elements with indexes i and j.
+func (configs policyConfigList) Swap(i, j int) {
+	temp := configs[i]
+	configs[i] = configs[j]
+	configs[j] = temp
+}
+
+func NewPolicy(network *net.Network) (cmd *Policy) {
+	cmd = new(Policy)
+	cmd.network = network
+	return
+}
+
+func (cmd *Policy) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "policy",
+		Aliases:     []string{"policies", "pol", "pols"},
+		Description: "Show the policies for an application or entity",
+		Usage:       "BROOKLYN_NAME SCOPE policy [NAME]",
+		Flags:       []cli.Flag{},
+	}
+}
+
+func (cmd *Policy) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	if c.Args().Present() {
+		cmd.show(scope.Application, scope.Entity, c.Args().First())
+	} else {
+		cmd.list(scope.Application, scope.Entity)
+	}
+}
+
+func (cmd *Policy) show(application, entity, policy string) {
+	configs, err := entity_policy_config.GetAllConfigValues(cmd.network, application, entity, policy)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	table := terminal.NewTable([]string{"Name", "Value", "Description"})
+	var theConfigs policyConfigList = configs
+	sort.Sort(theConfigs)
+
+	for _, config := range theConfigs {
+		value, err := entity_policy_config.GetConfigValue(cmd.network, application, entity, policy, config.Name)
+		if nil != err {
+			error_handler.ErrorExit(err)
+		}
+		table.Add(config.Name, value, config.Description)
+	}
+	table.Print()
+}
+
+func (cmd *Policy) list(application, entity string) {
+	policies, err := entity_policies.PolicyList(cmd.network, application, entity)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	table := terminal.NewTable([]string{"Id", "Name", "State"})
+	for _, policy := range policies {
+		table.Add(policy.Id, policy.Name, string(policy.State))
+	}
+	table.Print()
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/rename.go
----------------------------------------------------------------------
diff --git a/cli/commands/rename.go b/cli/commands/rename.go
new file mode 100644
index 0000000..7891971
--- /dev/null
+++ b/cli/commands/rename.go
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	"github.com/apache/brooklyn-client/api/entities"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/urfave/cli"
+)
+
+type Rename struct {
+	network *net.Network
+}
+
+func NewRename(network *net.Network) (cmd *Rename) {
+	cmd = new(Rename)
+	cmd.network = network
+	return
+}
+
+func (cmd *Rename) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "rename",
+		Description: "Rename an application or entity",
+		Usage:       "BROOKLYN_NAME SCOPE rename NEW_NAME",
+		Flags:       []cli.Flag{},
+	}
+}
+
+func (cmd *Rename) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	rename, err := entities.Rename(cmd.network, scope.Application, scope.Entity, c.Args().First())
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	fmt.Println(rename)
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/reset-catalog.go
----------------------------------------------------------------------
diff --git a/cli/commands/reset-catalog.go b/cli/commands/reset-catalog.go
new file mode 100644
index 0000000..6830399
--- /dev/null
+++ b/cli/commands/reset-catalog.go
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"github.com/apache/brooklyn-client/net"
+)
+
+type ResetCatalog struct {
+	network *net.Network
+}
+
+func NewResetCatalog(network *net.Network) (cmd *ResetCatalog) {
+	cmd = new(ResetCatalog)
+	cmd.network = network
+	return
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/sensor.go
----------------------------------------------------------------------
diff --git a/cli/commands/sensor.go b/cli/commands/sensor.go
new file mode 100644
index 0000000..ac75660
--- /dev/null
+++ b/cli/commands/sensor.go
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	"github.com/apache/brooklyn-client/api/entity_sensors"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/models"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/apache/brooklyn-client/terminal"
+	"github.com/urfave/cli"
+	"sort"
+)
+
+type Sensor struct {
+	network *net.Network
+}
+
+type sensorList []models.SensorSummary
+
+// Len is the number of elements in the collection.
+func (sensors sensorList) Len() int {
+	return len(sensors)
+}
+
+// Less reports whether the element with
+// index i should sort before the element with index j.
+func (sensors sensorList) Less(i, j int) bool {
+	return sensors[i].Name < sensors[j].Name
+}
+
+// Swap swaps the elements with indexes i and j.
+func (sensors sensorList) Swap(i, j int) {
+	temp := sensors[i]
+	sensors[i] = sensors[j]
+	sensors[j] = temp
+}
+
+func NewSensor(network *net.Network) (cmd *Sensor) {
+	cmd = new(Sensor)
+	cmd.network = network
+	return
+}
+
+func (cmd *Sensor) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "sensor",
+		Description: "Show values of all sensors or named sensor for an application or entity",
+		Usage:       "BROOKLYN_NAME SCOPE sensor [ SENSOR_NAME ]",
+		Flags:       []cli.Flag{},
+	}
+}
+
+func (cmd *Sensor) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	if c.Args().Present() {
+		cmd.show(scope.Application, scope.Entity, c.Args().First())
+	} else {
+		cmd.list(scope.Application, scope.Entity)
+	}
+}
+
+func (cmd *Sensor) show(application, entity, sensor string) {
+	sensorValue, err := entity_sensors.SensorValue(cmd.network, application, entity, sensor)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	displayValue, err := stringRepresentation(sensorValue)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	fmt.Println(displayValue)
+}
+
+func (cmd *Sensor) list(application, entity string) {
+	sensors, err := entity_sensors.SensorList(cmd.network, application, entity)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	var theSensors sensorList = sensors
+	table := terminal.NewTable([]string{"Name", "Description", "Value"})
+
+	sort.Sort(theSensors)
+
+	for _, sensor := range theSensors {
+		value, err := entity_sensors.SensorValue(cmd.network, application, entity, sensor.Name)
+		if nil != err {
+			error_handler.ErrorExit(err)
+		}
+		displayValue, err := stringRepresentation(value)
+		if nil != err {
+			error_handler.ErrorExit(err)
+		}
+		table.Add(sensor.Name, sensor.Description, displayValue)
+	}
+	table.Print()
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/set.go
----------------------------------------------------------------------
diff --git a/cli/commands/set.go b/cli/commands/set.go
new file mode 100644
index 0000000..ae1a594
--- /dev/null
+++ b/cli/commands/set.go
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	"github.com/apache/brooklyn-client/api/entity_config"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/urfave/cli"
+)
+
+type SetConfig struct {
+	network *net.Network
+}
+
+func NewSetConfig(network *net.Network) (cmd *SetConfig) {
+	cmd = new(SetConfig)
+	cmd.network = network
+	return
+}
+
+func (cmd *SetConfig) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "set",
+		Description: "Set config for an entity",
+		Usage:       "BROOKLYN_NAME CONFIG-SCOPE set VALUE",
+		Flags:       []cli.Flag{},
+	}
+}
+
+func (cmd *SetConfig) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	response, err := entity_config.SetConfig(cmd.network, scope.Application, scope.Entity, scope.Config, c.Args().First())
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	fmt.Println(response)
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/spec.go
----------------------------------------------------------------------
diff --git a/cli/commands/spec.go b/cli/commands/spec.go
new file mode 100644
index 0000000..06819b9
--- /dev/null
+++ b/cli/commands/spec.go
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	"github.com/apache/brooklyn-client/api/entities"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/urfave/cli"
+)
+
+type Spec struct {
+	network *net.Network
+}
+
+func NewSpec(network *net.Network) (cmd *Spec) {
+	cmd = new(Spec)
+	cmd.network = network
+	return
+}
+
+func (cmd *Spec) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "spec",
+		Description: "Get the YAML spec used to create the entity, if available",
+		Usage:       "BROOKLYN_NAME SCOPE spec",
+		Flags:       []cli.Flag{},
+	}
+}
+
+func (cmd *Spec) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	spec, err := entities.Spec(cmd.network, scope.Application, scope.Entity)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	fmt.Println(spec)
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/start-policy.go
----------------------------------------------------------------------
diff --git a/cli/commands/start-policy.go b/cli/commands/start-policy.go
new file mode 100644
index 0000000..68dbec7
--- /dev/null
+++ b/cli/commands/start-policy.go
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	"github.com/apache/brooklyn-client/api/entity_policies"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/urfave/cli"
+)
+
+type StartPolicy struct {
+	network *net.Network
+}
+
+func NewStartPolicy(network *net.Network) (cmd *StartPolicy) {
+	cmd = new(StartPolicy)
+	cmd.network = network
+	return
+}
+
+func (cmd *StartPolicy) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "start-policy",
+		Description: "Start or resume a policy",
+		Usage:       "BROOKLYN_NAME SCOPE start-policy POLICY",
+		Flags:       []cli.Flag{},
+	}
+}
+
+func (cmd *StartPolicy) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	spec, err := entity_policies.StartPolicy(cmd.network, scope.Application, scope.Entity, c.Args().First())
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	fmt.Println(spec)
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/stop-policy.go
----------------------------------------------------------------------
diff --git a/cli/commands/stop-policy.go b/cli/commands/stop-policy.go
new file mode 100644
index 0000000..2700802
--- /dev/null
+++ b/cli/commands/stop-policy.go
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	"github.com/apache/brooklyn-client/api/entity_policies"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/urfave/cli"
+)
+
+type StopPolicy struct {
+	network *net.Network
+}
+
+func NewStopPolicy(network *net.Network) (cmd *StopPolicy) {
+	cmd = new(StopPolicy)
+	cmd.network = network
+	return
+}
+
+func (cmd *StopPolicy) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "stop-policy",
+		Description: "Suspends a policy",
+		Usage:       "BROOKLYN_NAME SCOPE stop-policy POLICY",
+		Flags:       []cli.Flag{},
+	}
+}
+
+func (cmd *StopPolicy) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	spec, err := entity_policies.StopPolicy(cmd.network, scope.Application, scope.Entity, c.Args().First())
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	fmt.Println(spec)
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/tree.go
----------------------------------------------------------------------
diff --git a/cli/commands/tree.go b/cli/commands/tree.go
new file mode 100644
index 0000000..5665997
--- /dev/null
+++ b/cli/commands/tree.go
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	"github.com/apache/brooklyn-client/api/application"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/models"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/urfave/cli"
+)
+
+type Tree struct {
+	network *net.Network
+}
+
+func NewTree(network *net.Network) (cmd *Tree) {
+	cmd = new(Tree)
+	cmd.network = network
+	return
+}
+
+func (cmd *Tree) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "tree",
+		Description: "* Show the tree of all applications",
+		Usage:       "BROOKLYN_NAME tree",
+		Flags:       []cli.Flag{},
+	}
+}
+
+func (cmd *Tree) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	trees, err := application.Tree(cmd.network)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	cmd.printTrees(trees, "")
+}
+
+func (cmd *Tree) printTrees(trees []models.Tree, indent string) {
+	for i, app := range trees {
+		cmd.printTree(app, indent, i == len(trees)-1)
+	}
+}
+
+func (cmd *Tree) printTree(tree models.Tree, indent string, last bool) {
+	fmt.Println(indent+"|-", tree.Name)
+	fmt.Println(indent+"+-", tree.Type)
+
+	if last {
+		indent = indent + "  "
+	} else {
+		indent = indent + "| "
+	}
+	cmd.printTrees(tree.Children, indent)
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/utils.go
----------------------------------------------------------------------
diff --git a/cli/commands/utils.go b/cli/commands/utils.go
new file mode 100644
index 0000000..a4533b1
--- /dev/null
+++ b/cli/commands/utils.go
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"encoding/json"
+)
+
+func stringRepresentation(value interface{}) (string, error) {
+	var result string
+	switch value.(type) {
+	case string:
+		result = value.(string) // use string value as-is
+	default:
+		json, err := json.Marshal(value)
+		if err != nil {
+			return "", err
+		}
+		result = string(json) // return JSON text representation of value object
+	}
+	return result, nil
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/commands/version.go
----------------------------------------------------------------------
diff --git a/cli/commands/version.go b/cli/commands/version.go
new file mode 100644
index 0000000..39de4b6
--- /dev/null
+++ b/cli/commands/version.go
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	"github.com/apache/brooklyn-client/api/version"
+	"github.com/apache/brooklyn-client/command_metadata"
+	"github.com/apache/brooklyn-client/error_handler"
+	"github.com/apache/brooklyn-client/net"
+	"github.com/apache/brooklyn-client/scope"
+	"github.com/urfave/cli"
+)
+
+type Version struct {
+	network *net.Network
+}
+
+func NewVersion(network *net.Network) (cmd *Version) {
+	cmd = new(Version)
+	cmd.network = network
+	return
+}
+
+func (cmd *Version) Metadata() command_metadata.CommandMetadata {
+	return command_metadata.CommandMetadata{
+		Name:        "version",
+		Description: "Display the version of the connected Brooklyn",
+		Usage:       "BROOKLYN_NAME version",
+		Flags:       []cli.Flag{},
+	}
+}
+
+func (cmd *Version) Run(scope scope.Scope, c *cli.Context) {
+	if err := net.VerifyLoginURL(cmd.network); err != nil {
+		error_handler.ErrorExit(err)
+	}
+	version, err := version.Version(cmd.network)
+	if nil != err {
+		error_handler.ErrorExit(err)
+	}
+	fmt.Println(version.Version)
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/error_handler/error.go
----------------------------------------------------------------------
diff --git a/cli/error_handler/error.go b/cli/error_handler/error.go
new file mode 100644
index 0000000..8238c2b
--- /dev/null
+++ b/cli/error_handler/error.go
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package error_handler
+
+import (
+	"fmt"
+	"os"
+)
+
+const CLIUsageErrorExitCode int = 1
+const CliGenericErrorExitCode int = 2
+const CLITrapErrorCode int = 3
+
+func ErrorExit(errorvalue interface{}, errorcode ...int) {
+	switch errorvalue.(type) {
+	case error:
+		fmt.Fprintln(os.Stderr, errorvalue)
+	case string:
+		fmt.Fprintln(os.Stderr, errorvalue)
+	case nil:
+		fmt.Fprintln(os.Stderr, "No error message provided")
+	default:
+		fmt.Fprintln(os.Stderr, "Unknown Error Type: ", errorvalue)
+	}
+	if len(errorcode) > 0 {
+		os.Exit(errorcode[0])
+	} else {
+		os.Exit(CliGenericErrorExitCode)
+	}
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/glide.lock
----------------------------------------------------------------------
diff --git a/cli/glide.lock b/cli/glide.lock
new file mode 100644
index 0000000..f214d4c
--- /dev/null
+++ b/cli/glide.lock
@@ -0,0 +1,10 @@
+hash: 1d87d5643857ae47cd40cc29e7b9b813198980c84b3491376b3561c467e37994
+updated: 2016-06-02T21:50:02.953614402+01:00
+imports:
+- name: github.com/urfave/cli
+  version: 5db74198dee1cfe60cf06a611d03a420361baad6
+- name: golang.org/x/crypto
+  version: 1f22c0103821b9390939b6776727195525381532
+  subpackages:
+  - ssh/terminal
+devImports: []
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/glide.yaml
----------------------------------------------------------------------
diff --git a/cli/glide.yaml b/cli/glide.yaml
new file mode 100644
index 0000000..e2cf5c9
--- /dev/null
+++ b/cli/glide.yaml
@@ -0,0 +1,6 @@
+package: github.com/apache/brooklyn-client
+import:
+- package: github.com/urfave/cli
+- package: golang.org/x/crypto
+  subpackages:
+  - ssh/terminal

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/io/config.go
----------------------------------------------------------------------
diff --git a/cli/io/config.go b/cli/io/config.go
new file mode 100644
index 0000000..ea9ca01
--- /dev/null
+++ b/cli/io/config.go
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io
+
+import (
+	"encoding/json"
+	"os"
+	"path/filepath"
+
+	"github.com/apache/brooklyn-client/error_handler"
+)
+
+type Config struct {
+	FilePath string
+	Map      map[string]interface{}
+}
+
+func GetConfig() (config *Config) {
+	// check to see if $BRCLI_HOME/.brooklyn_cli or $HOME/.brooklyn_cli exists
+	// Then parse it to get user credentials
+	config = new(Config)
+	if os.Getenv("BRCLI_HOME") != "" {
+		config.FilePath = filepath.Join(os.Getenv("BRCLI_HOME"), ".brooklyn_cli")
+	} else {
+		config.FilePath = filepath.Join(os.Getenv("HOME"), ".brooklyn_cli")
+	}
+	if _, err := os.Stat(config.FilePath); os.IsNotExist(err) {
+		config.Map = make(map[string]interface{})
+		config.Write()
+	}
+	config.Read()
+	return
+}
+
+func (config *Config) Write() {
+	// Create file as read/write by user (but does not change perms of existing file)
+	fileToWrite, err := os.OpenFile(config.FilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
+	if err != nil {
+		error_handler.ErrorExit(err)
+	}
+	defer fileToWrite.Close()
+
+	enc := json.NewEncoder(fileToWrite)
+	enc.Encode(config.Map)
+}
+
+func (config *Config) Read() {
+	fileToRead, err := os.Open(config.FilePath)
+	if err != nil {
+		error_handler.ErrorExit(err)
+	}
+	defer fileToRead.Close()
+
+	dec := json.NewDecoder(fileToRead)
+	dec.Decode(&config.Map)
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/models/access.go
----------------------------------------------------------------------
diff --git a/cli/models/access.go b/cli/models/access.go
new file mode 100644
index 0000000..7fbdcbf
--- /dev/null
+++ b/cli/models/access.go
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package models
+
+type AccessSummary struct {
+	Links                       map[string]URI `json:"links"`
+	LocationProvisioningAllowed bool           `json:"locationProvisioningAllowed"`
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/models/applications.go
----------------------------------------------------------------------
diff --git a/cli/models/applications.go b/cli/models/applications.go
new file mode 100644
index 0000000..aa44b8d
--- /dev/null
+++ b/cli/models/applications.go
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package models
+
+type Tree struct {
+	Id            string   `json:"id"`
+	ParentId      string   `json:"parentId"`
+	Name          string   `json:"name"`
+	Type          string   `json:"type"`
+	CatalogItemId string   `json:"catalogItemId"`
+	Children      []Tree   `json:"children"`
+	GroupIds      []string `json:"groupIds"`
+	Members       []string `json:"members"`
+}
+
+type TaskSummary struct {
+	SubmitTimeUtc     int64                              `json:"submitTimeUtc"`
+	EndTimeUtc        int64                              `json:"endTimeUtc"`
+	IsCancelled       bool                               `json:"isCancelled"`
+	CurrentStatus     string                             `json:"currentStatus"`
+	BlockingTask      LinkTaskWithMetadata               `json:"blockingTask"`
+	DisplayName       string                             `json:"displayName"`
+	Streams           map[string]LinkStreamsWithMetadata `json:"streams"`
+	Description       string                             `json:"description"`
+	EntityId          string                             `json:"entityId"`
+	EntityDisplayName string                             `json:"entityDisplayName"`
+	Error             bool                               `json:"error"`
+	SubmittedByTask   LinkTaskWithMetadata               `json:"submittedByTask"`
+	Result            interface{}                        `json:"result"`
+	IsError           bool                               `json:"isError"`
+	DetailedStatus    string                             `json:"detailedStatus"`
+	Children          []LinkTaskWithMetadata             `json:"children"`
+	BlockingDetails   string                             `json:"blockingDetails"`
+	Cancelled         bool                               `json:"cancelled"`
+	Links             map[string]URI                     `json:"links"`
+	Id                string                             `json:"id"`
+	StartTimeUtc      int64                              `json:"startTimeUtc"`
+}
+
+type ApplicationSummary struct {
+	Links  map[string]URI  `json:"links"`
+	Id     string          `json:"id"`
+	Spec   ApplicationSpec `json:"spec"`
+	Status Status          `json:"status"`
+}
+
+type ApplicationSpec struct {
+	Name      string   `json:"name"`
+	Type      string   `json:"type"`
+	Locations []string `json:"locations"`
+}
+
+type Status string
+
+type LinkWithMetadata struct {
+}
+
+type LinkStreamsWithMetadata struct {
+	Link     string             `json:"link"`
+	Metadata LinkStreamMetadata `json:"metadata"`
+}
+
+type LinkStreamMetadata struct {
+	Name     string `json:"name"`
+	Size     int64  `json:"size"`
+	SizeText string `json:"sizeText"`
+}
+
+type LinkTaskWithMetadata struct {
+	Link     string           `json:"link"`
+	Metadata LinkTaskMetadata `json:"metadata"`
+}
+
+type LinkTaskMetadata struct {
+	Id                string `json:"id"`
+	TaskName          string `json:"taskName"`
+	EntityId          string `json:"entityId"`
+	EntityDisplayName string `json:"entityDisplayName"`
+}
+
+type URI string

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/models/catalog.go
----------------------------------------------------------------------
diff --git a/cli/models/catalog.go b/cli/models/catalog.go
new file mode 100644
index 0000000..ef6dabf
--- /dev/null
+++ b/cli/models/catalog.go
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package models
+
+type CatalogItemSummary struct {
+	Name         string                 `json:"name"`
+	JavaType     string                 `json:"javaType"`
+	SymbolicName string                 `json:"symbolicName"`
+	Version      string                 `json:"version"`
+	PlanYaml     string                 `json:"planYaml"`
+	Description  string                 `json:"description"`
+	Deprecated   bool                   `json:"deprecated"`
+	Links        map[string]interface{} `json:"links"`
+	Id           string                 `json:"id"`
+	Type         string                 `json:"type"`
+}
+
+type CatalogPolicySummary struct {
+	symbolicName string         `json:"symbolicName"`
+	version      string         `json:"version"`
+	displayName  string         `json:"name"`
+	javaType     string         `json:"javaType"`
+	planYaml     string         `json:"planYaml"`
+	description  string         `json:"description"`
+	iconUrl      string         `json:"iconUrl"`
+	deprecated   bool           `json:"deprecated"`
+	links        map[string]URI `json:"links"`
+}
+
+type CatalogLocationSummary struct {
+}
+
+type CatalogEntitySummary struct {
+	symbolicName string                 `json:"symbolicName"`
+	version      string                 `json:"version"`
+	displayName  string                 `json:"name"`
+	javaType     string                 `json:"javaType"`
+	planYaml     string                 `json:"planYaml"`
+	description  string                 `json:"description"`
+	Config       []ConfigSummary        `json:"config"`
+	Effectors    []EffectorSummary      `json:"effectors"`
+	Sensors      []SensorSummary        `json:"sensors"`
+	Deprecated   bool                   `json:"deprecated"`
+	Links        map[string]interface{} `json:"links"`
+	Id           string                 `json:"id"`
+	Type         string                 `json:"type"`
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/models/config.go
----------------------------------------------------------------------
diff --git a/cli/models/config.go b/cli/models/config.go
new file mode 100644
index 0000000..bc97650
--- /dev/null
+++ b/cli/models/config.go
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package models
+
+type ConfigSummary struct {
+	Reconfigurable bool                `json:"reconfigurable"`
+	PossibleValues []map[string]string `json:"possibleValues"`
+	DefaultValue   interface{}         `json:"defaultValue"`
+	Name           string              `json:"name"`
+	Description    string              `json:"description"`
+	Links          map[string]URI      `json:"links"`
+	Label          string              `json:"label"`
+	Priority       float64             `json:"priority"`
+	Type           string              `json:"type"`
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/models/effectors.go
----------------------------------------------------------------------
diff --git a/cli/models/effectors.go b/cli/models/effectors.go
new file mode 100644
index 0000000..1b846b7
--- /dev/null
+++ b/cli/models/effectors.go
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package models
+
+type EffectorSummary struct {
+	Name        string             `json:"name"`
+	Description string             `json:"description"`
+	Links       map[string]URI     `json:"links"`
+	Parameters  []ParameterSummary `json:"parameters"`
+	ReturnType  string             `json:"returnType"`
+}
+
+type ParameterSummary struct {
+	Name         string      `json:"name"`
+	Type         string      `json:"type"`
+	Description  string      `json:"description"`
+	DefaultValue interface{} `json:"defaultValue"`
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/models/entities.go
----------------------------------------------------------------------
diff --git a/cli/models/entities.go b/cli/models/entities.go
new file mode 100644
index 0000000..fdb85dc
--- /dev/null
+++ b/cli/models/entities.go
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package models
+
+type EntitySummary struct {
+	CatalogItemId string         `json:"catalogItemId"`
+	Name          string         `json:"name"`
+	Links         map[string]URI `json:"links"`
+	Id            string         `json:"id"`
+	Type          string         `json:"type"`
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/models/locations.go
----------------------------------------------------------------------
diff --git a/cli/models/locations.go b/cli/models/locations.go
new file mode 100644
index 0000000..2505eae
--- /dev/null
+++ b/cli/models/locations.go
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package models
+
+type LocationSummary struct {
+	Id     string                 `json:"id"`
+	Name   string                 `json:"name"`
+	Spec   string                 `json:"spec"`
+	Type   string                 `json:"type"`
+	Config map[string]interface{} `json:"config"`
+	Links  map[string]URI         `json:"links"`
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/models/policies.go
----------------------------------------------------------------------
diff --git a/cli/models/policies.go b/cli/models/policies.go
new file mode 100644
index 0000000..fca9298
--- /dev/null
+++ b/cli/models/policies.go
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package models
+
+type PolicySummary struct {
+	CatalogItemId string         `json:"catalogItemId"`
+	Name          string         `json:"name"`
+	Links         map[string]URI `json:"links"`
+	Id            string         `json:"id"`
+	State         Status         `json:"state"`
+}
+
+type PolicyConfigList struct {
+	Name           string         `json:"name"`
+	Type           string         `json:"type"`
+	DefaultValue   interface{}    `json:"defaultValue`
+	Description    string         `json:"description"`
+	Reconfigurable bool           `json:"reconfigurable"`
+	Label          string         `json:"label"`
+	Priority       int64          `json:"priority"`
+	PossibleValues []interface{}  `json:"possibleValues"`
+	Links          map[string]URI `json:"links"`
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/models/sensors.go
----------------------------------------------------------------------
diff --git a/cli/models/sensors.go b/cli/models/sensors.go
new file mode 100644
index 0000000..67b3b4f
--- /dev/null
+++ b/cli/models/sensors.go
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package models
+
+type SensorSummary struct {
+	Name        string         `json:"name"`
+	Description string         `json:"description"`
+	Links       map[string]URI `json:"links"`
+	Type        string         `json:"type"`
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/models/version.go
----------------------------------------------------------------------
diff --git a/cli/models/version.go b/cli/models/version.go
new file mode 100644
index 0000000..8f12a67
--- /dev/null
+++ b/cli/models/version.go
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package models
+
+type VersionSummary struct {
+	Version     string                   `json:"version"`
+	BuildSha1   string                   `json:"buildSha1"`
+	BuildBranch string                   `json:"buildBranch"`
+	Features    []BrooklynFeatureSummary `json:"features"`
+}
+
+type BrooklynFeatureSummary struct {
+	Name           string            `json:"name"`
+	SymbolicName   string            `json:"symbolicName"`
+	Version        string            `json:"version"`
+	LastModified   string            `json:"lastModified"`
+	AdditionalData map[string]string `json:"additionalData"`
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/net/net.go
----------------------------------------------------------------------
diff --git a/cli/net/net.go b/cli/net/net.go
new file mode 100644
index 0000000..b35a6c3
--- /dev/null
+++ b/cli/net/net.go
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package net
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"crypto/tls"
+)
+
+type Network struct {
+	BrooklynUrl  string
+	BrooklynUser string
+	BrooklynPass string
+	SkipSslChecks bool
+}
+
+func NewNetwork(brooklynUrl, brooklynUser, brooklynPass string, skipSslChecks bool) (net *Network) {
+	net = new(Network)
+	net.BrooklynUrl = brooklynUrl
+	net.BrooklynUser = brooklynUser
+	net.BrooklynPass = brooklynPass
+	net.SkipSslChecks = skipSslChecks
+	return
+}
+
+func (net *Network) NewRequest(method, path string, body io.Reader) *http.Request {
+	req, _ := http.NewRequest(method, net.BrooklynUrl+path, body)
+	req.SetBasicAuth(net.BrooklynUser, net.BrooklynPass)
+	return req
+}
+
+func (net *Network) NewGetRequest(url string) *http.Request {
+	return net.NewRequest("GET", url, nil)
+}
+
+func (net *Network) NewPostRequest(url string, body io.Reader) *http.Request {
+	return net.NewRequest("POST", url, body)
+}
+
+func (net *Network) NewDeleteRequest(url string) *http.Request {
+	return net.NewRequest("DELETE", url, nil)
+}
+
+type HttpError struct {
+	Code    int
+	Status  string
+	Headers http.Header
+	Body    string
+}
+
+func (err HttpError) Error() string {
+	return err.Status
+}
+
+func makeError(resp *http.Response, code int, body []byte) error {
+	theError := HttpError{
+		Code:    code,
+		Status:  resp.Status,
+		Headers: resp.Header,
+	}
+	details := make(map[string]string)
+	if err := json.Unmarshal(body, &details); nil == err {
+		if message, ok := details["message"]; ok {
+			theError.Body = message
+			return theError
+		}
+	}
+	theError.Body = string(body)
+	return theError
+}
+
+func (net *Network) SendRequest(req *http.Request) ([]byte, error) {
+	tr := &http.Transport{
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: net.SkipSslChecks},
+	}
+	client := &http.Client{Transport: tr}
+	resp, err := client.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	body, err := ioutil.ReadAll(resp.Body)
+	if code, failed := unsuccessful(resp.Status); failed {
+		return nil, makeError(resp, code, body)
+	}
+	return body, err
+}
+
+const httpSuccessSeriesFrom = 200
+const httpSuccessSeriesTo = 300
+
+func unsuccessful(status string) (int, bool) {
+	tokens := strings.Split(status, " ")
+	if 0 == len(tokens) {
+		return -1, false
+	}
+	code, err := strconv.Atoi(tokens[0])
+	if nil != err {
+		return -1, false
+	}
+	return code, code < httpSuccessSeriesFrom || httpSuccessSeriesTo <= code
+}
+
+func (net *Network) SendGetRequest(url string) ([]byte, error) {
+	req := net.NewGetRequest(url)
+	req.Header.Set("Accept", "application/json, text/plain")
+	body, err := net.SendRequest(req)
+	return body, err
+}
+
+func (net *Network) SendDeleteRequest(url string) ([]byte, error) {
+	req := net.NewDeleteRequest(url)
+	body, err := net.SendRequest(req)
+	return body, err
+}
+
+func (net *Network) SendEmptyPostRequest(url string) ([]byte, error) {
+	req := net.NewPostRequest(url, nil)
+	body, err := net.SendRequest(req)
+	return body, err
+}
+
+func (net *Network) SendPostRequest(urlStr string, data []byte) ([]byte, error) {
+	req := net.NewPostRequest(urlStr, bytes.NewBuffer(data))
+	req.Header.Set("Content-Type", "application/json")
+	body, err := net.SendRequest(req)
+	return body, err
+}
+
+func (net *Network) SendPostResourceRequest(restUrl string, resourceUrl string, contentType string) ([]byte, error) {
+	resource, err := openResource(resourceUrl)
+	defer resource.Close()
+	req := net.NewPostRequest(restUrl, resource)
+	req.Header.Set("Content-Type", contentType)
+	body, err := net.SendRequest(req)
+	return body, err
+}
+
+func openResource(resourceUrl string) (io.ReadCloser, error) {
+	u, err := url.Parse(resourceUrl)
+	if err != nil {
+		return nil, err
+	}
+	if "" == u.Scheme || "file" == u.Scheme {
+		return openFileResource(u)
+
+	} else if "http" == u.Scheme || "https" == u.Scheme {
+		return openHttpResource(resourceUrl)
+
+	} else {
+		return nil, errors.New("Unrecognised protocol scheme: " + u.Scheme)
+	}
+}
+
+func openFileResource(url *url.URL) (io.ReadCloser, error) {
+	filePath := url.Path;
+	file, err := os.Open(filepath.Clean(filePath))
+	if err != nil {
+		return nil, err
+	}
+	return file, nil
+}
+
+func openHttpResource(resourceUrl string) (io.ReadCloser, error) {
+	resp, err := http.Get(resourceUrl)
+	if err != nil {
+		return nil, err
+	}
+	return resp.Body, nil
+}
+
+
+func VerifyLoginURL(network *Network) error {
+	url, err := url.Parse(network.BrooklynUrl)
+	if err != nil {
+		return err
+	}
+	if url.Scheme != "http" && url.Scheme != "https" {
+		return errors.New("Use login command to set Brooklyn URL with a scheme of \"http\" or \"https\"")
+	}
+	if url.Host == "" {
+		return errors.New("Use login command to set Brooklyn URL with a valid host[:port]")
+	}
+	return nil
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/pom.xml
----------------------------------------------------------------------
diff --git a/cli/pom.xml b/cli/pom.xml
new file mode 100644
index 0000000..7cfb782
--- /dev/null
+++ b/cli/pom.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<project
+        xmlns="http://maven.apache.org/POM/4.0.0"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.brooklyn</groupId>
+        <artifactId>brooklyn-client</artifactId>
+        <version>0.10.0-SNAPSHOT</version>  <!-- BROOKLYN_VERSION -->
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    
+    <packaging>pom</packaging>
+
+    <artifactId>brooklyn-client-cli</artifactId>
+    <name>Brooklyn Client Command Line Interface</name>
+    <description>
+        A command line client for Apache Brooklyn
+    </description>
+
+
+    <!--
+
+    Run as one of:
+
+    mvn -Dtarget=native clean install                      build for local platform
+    mvn -Dtarget=all clean install                         build for all supported platforms
+    mvn -Dtarget=cross -Dos=OS -Darch=ARCH clean install   build for platform with operating system OS and architecture ARCH
+
+    -->
+
+    <properties>
+        <maven.antrun.plugin.version>1.8</maven.antrun.plugin.version>
+        <maven.assembly.plugin.version>2.6</maven.assembly.plugin.version>
+        <target>all</target>
+    </properties>
+
+    <repositories>
+        <!--
+            Same as in the parent apache pom. Repeated here in case
+            direct parent's pom not found at relativePath. Can't fetch
+            the parent from remote repos for snapshot versions - no
+            snapshot repos enabled by default.
+        -->
+        <repository>
+            <id>apache.snapshots</id>
+            <name>Apache Snapshot Repository</name>
+            <url>http://repository.apache.org/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+        </repository>
+    </repositories>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <version>1.8</version>
+                <executions>
+                    <execution>
+                        <id>process-build-all</id>
+                        <phase>compile</phase>
+                        <configuration>
+                            <target>
+                                <ant target="${target}"/>
+                            </target>
+                        </configuration>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+
+                </executions>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <version>${maven.assembly.plugin.version}</version>
+                <configuration>
+                    <descriptors>
+                        <descriptor>release/assembly.xml</descriptor>
+                    </descriptors>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>make-assembly</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.rat</groupId>
+                <artifactId>apache-rat-plugin</artifactId>
+                <version>0.11</version>
+                <configuration>
+                    <excludes combine.children="append">
+                        <exclude>vendor/**</exclude>
+                        <exclude>glide.*</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+        </plugins>
+
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/release/assembly.xml
----------------------------------------------------------------------
diff --git a/cli/release/assembly.xml b/cli/release/assembly.xml
new file mode 100644
index 0000000..8a32f91
--- /dev/null
+++ b/cli/release/assembly.xml
@@ -0,0 +1,43 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
+    <id>bin</id>
+    <formats>
+        <format>zip</format>
+    </formats>
+    <fileSets>
+        <fileSet>
+            <directory>release/files</directory>
+            <outputDirectory><!-- leave blank, meaning 'root of archive' --></outputDirectory>
+        </fileSet>
+        <fileSet>
+            <directory>release/license/files</directory>
+            <outputDirectory><!-- leave blank, meaning 'root of archive' --></outputDirectory>
+        </fileSet>
+        <fileSet>
+            <directory>${project.build.directory}/bin</directory>
+            <outputDirectory><!-- leave blank, meaning 'root of archive' --></outputDirectory>
+            <includes>
+                <include>**/br*</include>
+            </includes>
+        </fileSet>
+    </fileSets>
+</assembly>

http://git-wip-us.apache.org/repos/asf/brooklyn-client/blob/4122cfe1/cli/release/build.bat
----------------------------------------------------------------------
diff --git a/cli/release/build.bat b/cli/release/build.bat
new file mode 100644
index 0000000..cbef33a
--- /dev/null
+++ b/cli/release/build.bat
@@ -0,0 +1,24 @@
+@echo off
+REM Licensed to the Apache Software Foundation (ASF) under one
+REM or more contributor license agreements.  See the NOTICE file
+REM distributed with this work for additional information
+REM regarding copyright ownership.  The ASF licenses this file
+REM to you under the Apache License, Version 2.0 (the
+REM "License"); you may not use this file except in compliance
+REM with the License.  You may obtain a copy of the License at
+REM
+REM   http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM Unless required by applicable law or agreed to in writing,
+REM software distributed under the License is distributed on an
+REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+REM KIND, either express or implied.  See the License for the
+REM specific language governing permissions and limitations
+REM under the License.
+
+REM TODO
+echo.
+echo brooklyn-client CLI build not supported on Windows platforms, run maven with '-Dno-go-client' to skip.
+echo.
+
+exit 1


Mime
View raw message