コード例 #1
0
ファイル: node.go プロジェクト: VictorLowther/crowbar-api
func addNoderCommands(singularName string,
	maker func() client.Crudder,
	res *cobra.Command) {
	if _, ok := maker().(client.Noder); !ok {
		return
	}
	cmd := &cobra.Command{
		Use:   "nodes [id]",
		Short: fmt.Sprintf("List all nodes for a specifc %v", singularName),
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				log.Fatalf("%v requires 1 argument\n", c.UseLine())
			}
			obj := maker().(client.Noder)
			if client.SetId(obj, args[0]) != nil {
				log.Fatalf("Failed to parse ID %v for an %v\n", args[0], singularName)
			}
			objs, err := client.Nodes(obj)
			if err != nil {
				log.Fatalf("Failed to get nodes for %v(%v)\n", singularName, args[0])
			}
			fmt.Println(prettyJSON(objs))
		},
	}
	res.AddCommand(cmd)
}
コード例 #2
0
ファイル: node.go プロジェクト: VictorLowther/crowbar-api
func init() {
	maker := func() client.Crudder { return &client.Node{} }
	singularName := "node"
	nodes := makeCommandTree(singularName, maker)
	nodes.AddCommand(&cobra.Command{
		Use:   "addresses [id] on [networkId]",
		Short: "Fetch all addresses allocated to node [id] on a given network",
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 3 {
				log.Fatalf("%v requires 2 arguments", c.UseLine())
			}
			node := &client.Node{}
			net := &client.Network{}
			if err := client.Fetch(node, args[0]); err != nil {
				log.Fatalln("Failed to fetch node:", err)
			}
			if err := client.Fetch(net, args[2]); err != nil {
				log.Fatalln("Failed to fetch network:", err)
			}
			allocations := []*client.NetworkAllocation{}
			matcher := make(map[string]interface{})
			matcher["network_id"] = net.ID
			matcher["node_id"] = node.ID
			if err := client.Match("network_allocations", matcher, &allocations); err != nil {
				log.Fatalln("Failed to fetch allocations:", err)
			}
			addresses := make([]string, len(allocations))
			for i := range allocations {
				addresses[i] = allocations[i].Address
			}
			type result struct {
				Node      string   `json:"node"`
				Network   string   `json:"network"`
				Category  string   `json:"category"`
				Addresses []string `json:"addresses"`
			}
			res := result{Node: node.Name, Network: net.Name, Category: net.Category, Addresses: addresses}
			fmt.Println(prettyJSON(res))
		},
	})
	nodes.AddCommand(&cobra.Command{
		Use:   "bind [id] to [roleId]",
		Short: "Bind a node to a role",
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 3 || args[1] != "to" {
				log.Fatalf("%v requires 2 arguments seperated by \"to\"", c.UseLine())
			}
			obj := &client.Node{}

			role := &client.Role{}
			if err := client.Fetch(obj, args[0]); err != nil {
				log.Fatalf("Failed to fetch Node: %v\n", err.Error())
			}
			if err := client.Fetch(role, args[2]); err != nil {
				log.Fatalf("Failed to fetch Role: %v\n", err.Error())
			}
			nr := &client.NodeRole{}
			if err := client.Init(nr); err != nil {
				log.Fatalf("Failed to initialize NodeRole with defaults\n%v\n", err)
			}
			nr.RoleID = role.ID
			nr.NodeID = obj.ID
			nr.DeploymentID = obj.DeploymentID
			if err := client.BaseCreate(nr); err != nil {
				log.Fatalf("Failed to create noderole for node:%v role:%v\n", args[0], args[2])
			}
			fmt.Println(prettyJSON(nr))
		},
	})
	nodes.AddCommand(&cobra.Command{
		Use:   "import [json]",
		Short: "Import a node definition as a JSON blob.  May include a mac and an IP hint.",
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				log.Fatalf("%v requires 1 argument\n", c.UseLine())
			}
			obj := &client.Node{}
			if err := client.Import(obj, []byte(args[0])); err != nil {
				log.Fatalf("Failed to create node\n%v\n", err)
			}
			fmt.Println(prettyJSON(obj))
		},
	})
	nodes.AddCommand(&cobra.Command{
		Use:   "move [id] to [deployment]",
		Short: "Atomically move a node from one deployment to another",
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 3 {
				log.Fatalf("%v requires 2 argument\n", c.UseLine())
			}
			obj := &client.Node{}
			if client.Fetch(obj, args[0]) != nil {
				log.Fatalf("Failed to fetch %v\n", singularName)
			}
			depl := &client.Deployment{}
			if client.Fetch(depl, args[2]) != nil {
				log.Fatalf("Failed fetch deployment")
			}
			if obj.Move(depl) != nil {
				log.Fatalf("Failed to move node %v to deployment %v\n", args[0], args[2])
			}
			fmt.Println(prettyJSON(obj))
		},
	})
	nodes.AddCommand(&cobra.Command{
		Use:   "poweractions [id]",
		Short: "Get the power actions for this node",
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				log.Fatalf("%v requires 1 argument\n", c.UseLine())
			}
			obj := &client.Node{}
			if client.SetId(obj, args[0]) != nil {
				log.Fatalf("Failed to parse ID %v for an %v\n", args[0], singularName)
			}
			res, err := obj.PowerActions()
			if err != nil {
				log.Fatalf("Failed to get power actions for node %v\n", args[0])
			}
			fmt.Println(prettyJSON(res))
		},
	})
	nodes.AddCommand(&cobra.Command{
		Use:   "power [id] [action]",
		Short: "Perform a power control action for this node",
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 2 {
				log.Fatalf("%v requires 2 arguments\n", c.UseLine())
			}
			obj := &client.Node{}
			if client.SetId(obj, args[0]) != nil {
				log.Fatalf("Failed to parse ID %v for an %v\n", args[0], singularName)
			}
			err := obj.Power(args[1])
			if err != nil {
				log.Fatalf("Failed perform power action %v\n", args[1])
			}
		},
	})
	nodes.AddCommand(&cobra.Command{
		Use:   "activebootenv [id]",
		Short: "Get the boot environment that the provisioner has configured for the node.",
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				log.Fatalf("%v requires 1 argument\n", c.UseLine())
			}
			obj := &client.Node{}
			if client.SetId(obj, args[0]) != nil {
				log.Fatalf("Failed to parse ID %v for an %v\n", args[0], singularName)
			}
			fmt.Println(obj.ActiveBootstate())
		},
	})
	app.AddCommand(nodes)
}
コード例 #3
0
ファイル: main.go プロジェクト: VictorLowther/crowbar-api
func makeCommandTree(singularName string,
	maker func() client.Crudder) (res *cobra.Command) {
	name := singularName + "s"
	d("Making command tree for %v\n", name)
	res = &cobra.Command{
		Use:   name,
		Short: fmt.Sprintf("Access CLI commands relating to %v", name),
	}
	commands := make([]*cobra.Command, 8)
	commands[0] = &cobra.Command{
		Use:   "list",
		Short: fmt.Sprintf("List all %v", name),
		Run: func(c *cobra.Command, args []string) {
			objs := []interface{}{}
			if err := client.List(maker().ApiName(), &objs); err != nil {
				log.Fatalf("Error listing %v: %v", name, err.Error())
			}
			fmt.Println(prettyJSON(objs))
		},
	}
	commands[1] = &cobra.Command{
		Use:   "match [json]",
		Short: fmt.Sprintf("List all %v that match the template in [json]", name),
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				log.Fatalf("%v requires 1 argument\n", c.UseLine())
			}
			objs := []interface{}{}
			vals := map[string]interface{}{}
			if err := json.Unmarshal([]byte(args[0]), &vals); err != nil {
				log.Fatalf("Matches not valid JSON\n%v", err)
			}
			if err := client.Match(maker().ApiName(), vals, &objs); err != nil {
				log.Fatalf("Error getting matches for %v\nError:%v\n", singularName, err.Error())
			}
			fmt.Println(prettyJSON(objs))
		},
	}
	commands[2] = &cobra.Command{
		Use:   "show [id]",
		Short: fmt.Sprintf("Show a single %v by id", singularName),
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				log.Fatalf("%v requires 1 argument\n", c.UseLine())
			}
			obj := maker()
			if client.Fetch(obj, args[0]) != nil {
				log.Fatalf("Failed to fetch %v\n", singularName, args[0])
			}
			fmt.Println(prettyJSON(obj))
		},
	}
	commands[3] = &cobra.Command{
		Use:   "sample",
		Short: fmt.Sprintf("Get the default values for a %v", singularName),
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 0 {
				log.Fatalf("%v takes no arguments", c.UseLine())
			}
			obj := maker()
			if err := client.Init(obj); err != nil {
				log.Fatalf("Unable to fetch defaults for %v: %v\n", singularName, err.Error())
			}
			fmt.Println(prettyJSON(obj))
		},
	}
	commands[4] = &cobra.Command{
		Use:   "create [json]",
		Short: fmt.Sprintf("Create a new %v with the passed-in JSON", singularName),
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				log.Fatalf("%v requires 1 argument\n", c.UseLine())
			}
			obj := maker()
			if err := client.Import(obj, []byte(args[0])); err != nil {
				log.Fatalf("Unable to create new %v: %v\n", singularName, err.Error())
			}
			fmt.Println(prettyJSON(obj))
		},
	}
	commands[5] = &cobra.Command{
		Use:   "update [id] [json]",
		Short: fmt.Sprintf("Unsafely update %v by id with the passed-in JSON", singularName),
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 2 {
				log.Fatalf("%v requires 2 arguments\n", c.UseLine())
			}
			obj := maker()
			if err := client.Fetch(obj, args[0]); err != nil {
				log.Fatalf("Failed to fetch %v\n%v\n", singularName, err)
			}
			if err := client.UpdateJSON(obj, []byte(args[1])); err != nil {
				log.Fatalf("Unable to patch %v\n%v\n", args[0], err)
			}

			fmt.Println(prettyJSON(obj))
		},
	}
	commands[6] = &cobra.Command{
		Use:   "patch [objectJson] [changesJson]",
		Short: fmt.Sprintf("Patch %v with the passed-in JSON", singularName),
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 2 {
				log.Fatalf("%v requires 2 arguments\n", c.UseLine())
			}
			obj := maker()
			if err := json.Unmarshal([]byte(args[0]), obj); err != nil {
				log.Fatalf("Unable to parse %v JSON %v\nError: %v\n", args[0], err)
			}
			newObj := maker()
			json.Unmarshal([]byte(args[0]), newObj)
			if err := json.Unmarshal([]byte(args[1]), newObj); err != nil {
				log.Fatalf("Unable to parse %v JSON %v\nError: %v\n", args[1], err)
			}
			newBuf, _ := json.Marshal(newObj)
			patch, err := jsonpatch.GenerateJSON([]byte(args[0]), newBuf, true)
			if err != nil {
				log.Fatalf("Cannot generate JSON Patch\n%v\n", err)
			}

			if err := client.Patch(obj, patch); err != nil {
				log.Fatalf("Unable to patch %v\n%v\n", args[0], err)
			}

			fmt.Println(prettyJSON(obj))
		},
	}
	commands[7] = &cobra.Command{
		Use:   "destroy [id]",
		Short: fmt.Sprintf("Destroy %v by id", singularName),
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				log.Fatalf("%v requires 1 argument\n", c.UseLine())
			}
			obj := maker()
			if client.SetId(obj, args[0]) != nil {
				log.Fatalf("Failed to parse ID %v for an %v\n", args[0], singularName)
			}
			if err := client.Destroy(obj); err != nil {
				log.Fatalf("Unable to destroy %v %v\nError: %v\n", singularName, args[0], err.Error())
			}
			fmt.Printf("Deleted %v %v\n", singularName, args[0])
		},
	}

	res.AddCommand(commands...)
	// Add relavent subcommands as needed.
	addAttriberCommands(singularName, maker, res)
	addDeploymenterCommands(singularName, maker, res)
	addDeploymentRolerCommands(singularName, maker, res)
	addNetworkerCommands(singularName, maker, res)
	addNetworkRangerCommands(singularName, maker, res)
	addNetworkAllocaterCommands(singularName, maker, res)
	addNoderCommands(singularName, maker, res)
	addRolerCommands(singularName, maker, res)
	addHammererCommands(singularName, maker, res)
	addJiggerCommands(singularName, maker, res)
	return res
}
コード例 #4
0
ファイル: attrib.go プロジェクト: VictorLowther/crowbar-api
func addAttriberCommands(singularName string,
	maker func() client.Crudder,
	res *cobra.Command) {
	if _, ok := maker().(client.Attriber); !ok {
		return
	}
	commands := make([]*cobra.Command, 5)
	commands[0] = &cobra.Command{
		Use:   "attribs [id]",
		Short: fmt.Sprintf("List all attribs for a specifc %v", singularName),
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				log.Fatalf("%v requires 1 argument\n", c.UseLine())
			}
			obj := maker().(client.Attriber)
			if client.SetId(obj, args[0]) != nil {
				log.Fatalf("Failed to parse ID %v for an %v\n", args[0], singularName)
			}
			objs, err := client.Attribs(obj)
			if err != nil {
				log.Fatalf("Failed to get attribs for %v(%v)\n", singularName, args[0])
			}
			fmt.Println(prettyJSON(objs))
		},
	}
	commands[1] = &cobra.Command{
		Use:   "get [id] attrib [attrib] bucket [bucket=all]",
		Short: fmt.Sprintf("Get an attrib for a specific %v in a specific bucket.", singularName),
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 3 && len(args) != 5 {
				log.Fatalf("%v requires 2 or 3 arguments.\n", c.UseLine())
			}
			obj := maker().(client.Attriber)
			attr := &client.Attrib{}
			if client.SetId(obj, args[0]) != nil {
				log.Fatalf("Failed to parse ID %v for an %v\n", args[0], singularName)
			}
			if client.SetId(attr, args[2]) != nil {
				log.Fatalf("Failed to parse ID %v for an attrib\n", args[1])
			}
			bucket := "all"
			if len(args) == 5 {
				bucket = args[4]
			}
			attr, err := client.GetAttrib(obj, attr, bucket)
			if err != nil {
				log.Fatalf("Error fetching attrib %v for %v(%v): %v\n", args[1], singularName, args[0], err.Error())
			}
			fmt.Println(prettyJSON(attr))
		},
	}
	commands[2] = &cobra.Command{
		Use:   "set [id] attrib [attrib] to [json] bucket [bucket=user]",
		Short: fmt.Sprintf("Set an attrib value for a specific %v", singularName),
		Run: func(c *cobra.Command, args []string) {
			bucket := "user"
			if len(args) != 5 && len(args) != 7 {
				log.Fatalf("%v requires 3 or 4 arguments.\n", c.UseLine())
			}
			obj := maker().(client.Attriber)
			attr := &client.Attrib{}
			if len(args) == 7 {
				bucket = args[6]
			}
			if client.SetId(obj, args[0]) != nil {
				log.Fatalf("Failed to parse ID %v for an %v\n", args[0], singularName)
			}
			if client.SetId(attr, args[2]) != nil {
				log.Fatalf("Failed to parse ID %v for an attrib\n", args[1])
			}
			attr, err := client.GetAttrib(obj, attr, "")
			if err != nil {
				log.Fatalf("Failed to fetch Attrib from server\n%v", err)
			}
			val := &struct {
				Value interface{} `json:"value"`
			}{}
			err = json.Unmarshal([]byte(args[4]), val)
			if err != nil {
				log.Fatalf("Failed to parse %v as JSON!\nError: %v\n", args[2], err.Error())
			}
			attr.Value = val.Value
			if err := client.SetAttrib(obj, attr, bucket); err != nil {
				log.Fatalf("Unable to set attrib! Error: %v\n", err.Error())
			}
			fmt.Println(prettyJSON(attr))
		},
	}
	commands[3] = &cobra.Command{
		Use:   "propose [id]",
		Short: fmt.Sprintf("Tell a specific %v to prepare to accept new attrib values", singularName),
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				log.Fatalf("%v requires 1 argument\n", c.UseLine())
			}
			obj := maker().(client.Attriber)
			if client.SetId(obj, args[0]) != nil {
				log.Fatalf("Failed to parse ID %v for an %v\n", args[0], singularName)
			}
			if err := client.Propose(obj); err != nil {
				log.Fatalf("Failed to propose: %v\n", err.Error())
			}
			fmt.Println(prettyJSON(obj))
		},
	}
	commands[4] = &cobra.Command{
		Use:   "commit [id]",
		Short: fmt.Sprintf("Have %v commit any new attrib values", singularName),
		Run: func(c *cobra.Command, args []string) {
			if len(args) != 1 {
				log.Fatalf("%v requires 1 argument\n", c.UseLine())
			}
			obj := maker().(client.Attriber)
			if client.SetId(obj, args[0]) != nil {
				log.Fatalf("Failed to parse ID %v for an %v\n", args[0], singularName)
			}
			if err := client.Commit(obj); err != nil {
				log.Fatalf("Failed to commit: %v\n", err.Error())
			}
			fmt.Println(prettyJSON(obj))
		},
	}
	res.AddCommand(commands...)
}
コード例 #5
0
ファイル: network.go プロジェクト: VictorLowther/crowbar-api
func init() {
	maker := func() client.Crudder { return &client.Network{} }
	network := makeCommandTree("network", maker)
	cmds := []*cobra.Command{
		&cobra.Command{
			Use:   "import [json]",
			Short: "Import a network + optional ranges and routers into Crowbar",
			Run: func(c *cobra.Command, args []string) {
				if len(args) != 1 {
					log.Fatalf("%v requires 1 argument\n", c.UseLine())
				}
				obj := &client.Network{}
				if err := client.Import(obj, []byte(args[0])); err != nil {
					log.Fatalf("Unable to import network: %v\n", err)
				}
				fmt.Println(prettyJSON(obj))
			},
		},
		&cobra.Command{
			Use:   "add [id] to [nodeId]",
			Short: "Add a Network to a Node.  This will implicitly allocate an address from the default host ranges in the network.",
			Run: func(c *cobra.Command, args []string) {
				if len(args) != 3 {
					log.Fatalf("%v requires 2 arguments\n", c.UseLine())
				}
				node := &client.Node{}
				network := &client.Network{}
				if err := client.Fetch(node, args[2]); err != nil {
					log.Fatalf("Unable to fetch node\n%v\n", err)
				}
				if err := client.Fetch(network, args[0]); err != nil {
					log.Fatalf("Unable to fetch network\n%v\n", err)
				}
				ranges, err := network.AutoRanges(node)
				if err != nil {
					log.Fatalln("Failed to get auto ranges for network", err)
				}
				res := make([]*client.NetworkAllocation, len(ranges))
				unwind := true
				defer func() {
					if unwind {
						for _, allocation := range res {
							if allocation != nil {
								client.Destroy(allocation)
							}
						}
					}
				}()

				for i, netRange := range ranges {
					alloc := &client.NetworkAllocation{}
					alloc.NodeID = null.IntFrom(node.ID)
					alloc.NetworkID = null.IntFrom(network.ID)
					alloc.NetworkRangeID = null.IntFrom(netRange.ID)

					if err := client.BaseCreate(alloc); err != nil {
						log.Fatalf("Unable to create new NetworkAllocation: %v", err)
					}
					res[i] = alloc
				}
				unwind = false
				fmt.Println(prettyJSON(res))
			},
		},
		&cobra.Command{
			Use:   "alloc [id] on [nodeId] from [rangeId] hint [address]",
			Short: "Add a Network to a Node with an address allocated from a specific Range.",
			Run: func(c *cobra.Command, args []string) {
				if len(args) != 5 && len(args) != 7 {
					log.Fatalf("%v requires 3 or 4 arguments", c.UseLine())
				}
				node := &client.Node{}
				if err := client.Fetch(node, args[0]); err != nil {
					log.Fatalln("Unable to fetch node from Crowbar\n%v\n", err)
				}
				netRange := &client.NetworkRange{}
				if err := client.SetId(netRange, args[4]); err != nil {
					vals := map[string]interface{}{}
					vals["name"] = args[4]
					network := &client.Network{}
					if err := client.Fetch(network, args[2]); err != nil {
						log.Fatalln("Unable to fetch network from Crowbar\n%v\n", err)
					}
					vals["network_id"] = network.ID
					netRanges := []*client.NetworkRange{}
					if err := client.Match(netRange.ApiName(), vals, &netRanges); err != nil {
						log.Fatalf("Unable to fetch ranges matching %#v\n%v\n", netRange, err)
					}
					if len(netRanges) != 1 {
						log.Fatalln("Supplied network range information is ambiguous")
					}
					netRange = netRanges[0]
				} else {
					if err := client.Read(netRange); err != nil {
						log.Fatalln("Unable to fetch network range\n%v\n", err)
					}
				}
				alloc := &client.NetworkAllocation{}
				alloc.NetworkID = null.IntFrom(netRange.NetworkID)
				alloc.NetworkRangeID = null.IntFrom(netRange.ID)
				alloc.NodeID = null.IntFrom(node.ID)
				if len(args) == 7 {
					alloc.Address = args[6]
				}
				if err := client.BaseCreate(alloc); err != nil {
					log.Fatalf("Unable to add node to network\n%v\n", err)
				}
				fmt.Println(prettyJSON(alloc))
			},
		},
	}
	network.AddCommand(cmds...)
	app.AddCommand(network)
	maker = func() client.Crudder { return &client.NetworkRange{} }
	networkrange := makeCommandTree("networkrange", maker)
	app.AddCommand(networkrange)
	maker = func() client.Crudder { return &client.NetworkAllocation{} }
	app.AddCommand(makeCommandTree("networkallocation", maker))
	maker = func() client.Crudder { return &client.NetworkRouter{} }
	app.AddCommand(makeCommandTree("networkrouter", maker))
}