// New creates a new environment, returning an error if the environment already // exists or you try to create an environment named "_default". func New(name string) (*ChefEnvironment, util.Gerror) { if !util.ValidateEnvName(name) { err := util.Errorf("Field 'name' invalid") err.SetStatus(http.StatusBadRequest) return nil, err } var found bool if config.UsingDB() { var eerr error found, eerr = checkForEnvironmentSQL(datastore.Dbh, name) if eerr != nil { err := util.CastErr(eerr) err.SetStatus(http.StatusInternalServerError) return nil, err } } else { ds := datastore.New() _, found = ds.Get("env", name) } if found || name == "_default" { err := util.Errorf("Environment already exists") return nil, err } env := &ChefEnvironment{ Name: name, ChefType: "environment", JSONClass: "Chef::Environment", Default: map[string]interface{}{}, Override: map[string]interface{}{}, CookbookVersions: map[string]string{}, } return env, nil }
// UpdateFromJSON updates an existing environment from JSON uploaded to the // server. func (e *ChefEnvironment) UpdateFromJSON(jsonEnv map[string]interface{}) util.Gerror { if e.Name != jsonEnv["name"].(string) { err := util.Errorf("Environment name %s and %s from JSON do not match", e.Name, jsonEnv["name"].(string)) return err } else if e.Name == "_default" { err := util.Errorf("The '_default' environment cannot be modified.") err.SetStatus(http.StatusMethodNotAllowed) return err } /* Validations */ validElements := []string{"name", "chef_type", "json_class", "description", "default_attributes", "override_attributes", "cookbook_versions"} ValidElem: for k := range jsonEnv { for _, i := range validElements { if k == i { continue ValidElem } } err := util.Errorf("Invalid key %s in request body", k) return err } var verr util.Gerror attrs := []string{"default_attributes", "override_attributes"} for _, a := range attrs { jsonEnv[a], verr = util.ValidateAttributes(a, jsonEnv[a]) if verr != nil { return verr } } jsonEnv["json_class"], verr = util.ValidateAsFieldString(jsonEnv["json_class"]) if verr != nil { if verr.Error() == "Field 'name' nil" { jsonEnv["json_class"] = e.JSONClass } else { return verr } } else { if jsonEnv["json_class"].(string) != "Chef::Environment" { verr = util.Errorf("Field 'json_class' invalid") return verr } } jsonEnv["chef_type"], verr = util.ValidateAsFieldString(jsonEnv["chef_type"]) if verr != nil { if verr.Error() == "Field 'name' nil" { jsonEnv["chef_type"] = e.ChefType } else { return verr } } else { if jsonEnv["chef_type"].(string) != "environment" { verr = util.Errorf("Field 'chef_type' invalid") return verr } } jsonEnv["cookbook_versions"], verr = util.ValidateAttributes("cookbook_versions", jsonEnv["cookbook_versions"]) if verr != nil { return verr } for k, v := range jsonEnv["cookbook_versions"].(map[string]interface{}) { if !util.ValidateEnvName(k) || k == "" { merr := util.Errorf("Cookbook name %s invalid", k) merr.SetStatus(http.StatusBadRequest) return merr } if v == nil { verr = util.Errorf("Invalid version number") return verr } _, verr = util.ValidateAsConstraint(v) if verr != nil { /* try validating as a version */ v, verr = util.ValidateAsVersion(v) if verr != nil { return verr } } } jsonEnv["description"], verr = util.ValidateAsString(jsonEnv["description"]) if verr != nil { if verr.Error() == "Field 'name' missing" { jsonEnv["description"] = "" } else { return verr } } e.ChefType = jsonEnv["chef_type"].(string) e.JSONClass = jsonEnv["json_class"].(string) e.Description = jsonEnv["description"].(string) e.Default = jsonEnv["default_attributes"].(map[string]interface{}) e.Override = jsonEnv["override_attributes"].(map[string]interface{}) /* clear out, then loop over the cookbook versions */ e.CookbookVersions = make(map[string]string, len(jsonEnv["cookbook_versions"].(map[string]interface{}))) for c, v := range jsonEnv["cookbook_versions"].(map[string]interface{}) { e.CookbookVersions[c] = v.(string) } return nil }
// UpdateFromJSON updates an existing node with the uploaded JSON. func (n *Node) UpdateFromJSON(jsonNode map[string]interface{}) util.Gerror { /* It's actually totally legitimate to save a node with a different * name than you started with, but we need to get/create a new node for * it is all. */ nodeName, nerr := util.ValidateAsString(jsonNode["name"]) if nerr != nil { return nerr } if n.Name != nodeName { err := util.Errorf("Node name %s and %s from JSON do not match.", n.Name, nodeName) return err } /* Validations */ /* Look for invalid top level elements. *We* don't have to worry about * them, but chef-pedant cares (probably because Chef <=10 stores * json objects directly, dunno about Chef 11). */ validElements := []string{"name", "json_class", "chef_type", "chef_environment", "run_list", "override", "normal", "default", "automatic"} ValidElem: for k := range jsonNode { for _, i := range validElements { if k == i { continue ValidElem } } err := util.Errorf("Invalid key %s in request body", k) return err } var verr util.Gerror jsonNode["run_list"], verr = util.ValidateRunList(jsonNode["run_list"]) if verr != nil { return verr } attrs := []string{"normal", "automatic", "default", "override"} for _, a := range attrs { jsonNode[a], verr = util.ValidateAttributes(a, jsonNode[a]) if verr != nil { return verr } } jsonNode["chef_environment"], verr = util.ValidateAsFieldString(jsonNode["chef_environment"]) if verr != nil { if verr.Error() == "Field 'name' nil" { jsonNode["chef_environment"] = n.ChefEnvironment } else { return verr } } else { if !util.ValidateEnvName(jsonNode["chef_environment"].(string)) { verr = util.Errorf("Field 'chef_environment' invalid") return verr } } jsonNode["json_class"], verr = util.ValidateAsFieldString(jsonNode["json_class"]) if verr != nil { if verr.Error() == "Field 'name' nil" { jsonNode["json_class"] = n.JSONClass } else { return verr } } else { if jsonNode["json_class"].(string) != "Chef::Node" { verr = util.Errorf("Field 'json_class' invalid") return verr } } jsonNode["chef_type"], verr = util.ValidateAsFieldString(jsonNode["chef_type"]) if verr != nil { if verr.Error() == "Field 'name' nil" { jsonNode["chef_type"] = n.ChefType } else { return verr } } else { if jsonNode["chef_type"].(string) != "node" { verr = util.Errorf("Field 'chef_type' invalid") return verr } } /* and setting */ n.ChefEnvironment = jsonNode["chef_environment"].(string) n.ChefType = jsonNode["chef_type"].(string) n.JSONClass = jsonNode["json_class"].(string) n.RunList = jsonNode["run_list"].([]string) n.Normal = jsonNode["normal"].(map[string]interface{}) n.Automatic = jsonNode["automatic"].(map[string]interface{}) n.Default = jsonNode["default"].(map[string]interface{}) n.Override = jsonNode["override"].(map[string]interface{}) return nil }