// MakePatch generates a JSON Patch that describes the difference between the last time // an object was fetched from the server and its current state. func MakePatch(o Crudder) ([]byte, error) { if len(o.lastJSON()) == 0 { return nil, fmt.Errorf("Cannot update an object that has never been fetched") } buf, err := json.Marshal(o) if err != nil { return nil, err } return jsonpatch.GenerateJSON(o.lastJSON(), buf, true) }
// UpdateJSON tries to update Crudder with toMerge, which should be a // JSON blob with keys that correspond to the Crudder's struct fields // when serialzed to JSON. func UpdateJSON(o Crudder, toMerge []byte) error { buf := o.lastJSON() if len(buf) == 0 { return fmt.Errorf("Cannot update an object that has never been fetched") } merged, err := safeMergeJSON(buf, toMerge) if err != nil { return err } patch, err := jsonpatch.GenerateJSON(buf, merged, true) if err != nil { return err } return Patch(o, patch) }
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 }