/* Returns a sorted list of all the versions of this cookbook */ func (c *Cookbook) sortedVersions() []*CookbookVersion { if config.UsingDB() { return c.sortedCookbookVersionsSQL() } sorted := make([]*CookbookVersion, len(c.Versions)) keys := make(VersionStrings, len(c.Versions)) u := 0 for k, cbv := range c.Versions { keys[u] = k u++ datastore.ChkNilArray(cbv) } sort.Sort(sort.Reverse(keys)) /* populate sorted now */ for i, s := range keys { /* This shouldn't be able to happen, but somehow it... does? */ if i >= len(sorted) { break } sorted[i] = c.Versions[s] } return sorted }
// Fill an environment in from a row returned from the SQL server. See the // equivalent function in node/node.go for more details. // // As there, the SQL query that made the row needs to have the same number & // order of columns as the one in Get(), even if the WHERE clause is different // or omitted. func (e *ChefEnvironment) fillEnvFromSQL(row datastore.ResRow) error { var ( da []byte oa []byte cv []byte ) err := row.Scan(&e.Name, &e.Description, &da, &oa, &cv) if err != nil { return err } e.ChefType = "environment" e.JSONClass = "Chef::Environment" if e.Name == "_default" { e.Default = make(map[string]interface{}) e.Override = make(map[string]interface{}) e.CookbookVersions = make(map[string]string) return nil } err = datastore.DecodeBlob(da, &e.Default) if err != nil { return err } err = datastore.DecodeBlob(oa, &e.Override) if err != nil { return err } err = datastore.DecodeBlob(cv, &e.CookbookVersions) if err != nil { return err } datastore.ChkNilArray(e) return nil }
func (r *Role) fillRoleFromSQL(row datastore.ResRow) error { var ( rl []byte er []byte da []byte oa []byte ) err := row.Scan(&r.Name, &r.Description, &rl, &er, &da, &oa) if err != nil { return err } r.ChefType = "role" r.JSONClass = "Chef::Role" err = datastore.DecodeBlob(rl, &r.RunList) if err != nil { return err } err = datastore.DecodeBlob(er, &r.EnvRunLists) if err != nil { return err } err = datastore.DecodeBlob(da, &r.Default) if err != nil { return err } err = datastore.DecodeBlob(oa, &r.Override) if err != nil { return err } datastore.ChkNilArray(r) return nil }
// LatestVersion gets the latest version of this cookbook. func (c *Cookbook) LatestVersion() *CookbookVersion { if c.latest == nil { sorted := c.sortedVersions() c.latest = sorted[0] if c.latest != nil { datastore.ChkNilArray(c.latest) } } return c.latest }
func (dbi *DataBagItem) fillDBItemFromSQL(row datastore.ResRow) error { var rawb []byte err := row.Scan(&dbi.id, &dbi.dataBagID, &dbi.Name, &dbi.origName, &dbi.DataBagName, &rawb) if err != nil { return err } dbi.ChefType = "data_bag_item" dbi.JSONClass = "Chef::DataBagItem" err = datastore.DecodeBlob(rawb, &dbi.RawData) if err != nil { return err } datastore.ChkNilArray(dbi) return nil }
// GetVersion gets a particular version of the cookbook. func (c *Cookbook) GetVersion(cbVersion string) (*CookbookVersion, util.Gerror) { if cbVersion == "_latest" { return c.LatestVersion(), nil } var cbv *CookbookVersion var found bool if config.UsingDB() { // Ridiculously cacheable, but let's get it working first. This // applies all over the place w/ the SQL bits. if cbv, found = c.Versions[cbVersion]; !found { var err error cbv, err = c.getCookbookVersionSQL(cbVersion) if err != nil { if err == sql.ErrNoRows { found = false } else { gerr := util.Errorf(err.Error()) gerr.SetStatus(http.StatusInternalServerError) return nil, gerr } } else { found = true c.Versions[cbVersion] = cbv } } } else { cbv, found = c.Versions[cbVersion] if cbv != nil { datastore.ChkNilArray(cbv) if cbv.Recipes == nil { cbv.Recipes = make([]map[string]interface{}, 0) } } } if !found { err := util.Errorf("Cannot find a cookbook named %s with version %s", c.Name, cbVersion) err.SetStatus(http.StatusNotFound) return nil, err } return cbv, nil }
// Get a cookbook. func Get(name string) (*Cookbook, util.Gerror) { var cookbook *Cookbook var found bool if config.UsingDB() { var err error cookbook, err = getCookbookSQL(name) if err != nil { if err == sql.ErrNoRows { found = false } else { gerr := util.CastErr(err) gerr.SetStatus(http.StatusInternalServerError) return nil, gerr } } else { found = true } } else { ds := datastore.New() var c interface{} c, found = ds.Get("cookbook", name) if c != nil { cookbook = c.(*Cookbook) } /* hrm. */ if cookbook != nil && config.Config.UseUnsafeMemStore { for _, v := range cookbook.Versions { datastore.ChkNilArray(v) } } } if !found { err := util.Errorf("Cannot find a cookbook named %s", name) err.SetStatus(http.StatusNotFound) return nil, err } return cookbook, nil }
// Fill in a node from a row returned from the SQL server. Useful for the case // down the road where an array of objects is needed, but building it with // a call to GetList(), then repeated calls to Get() sucks with a real db even // if it's marginally acceptable in in-memory mode. // // NB: This does require the query to look like the one in Get(). func (n *Node) fillNodeFromSQL(row datastore.ResRow) error { var ( rl []byte aa []byte na []byte da []byte oa []byte ) err := row.Scan(&n.Name, &n.ChefEnvironment, &rl, &aa, &na, &da, &oa) if err != nil { return err } n.ChefType = "node" n.JSONClass = "Chef::Node" err = datastore.DecodeBlob(rl, &n.RunList) if err != nil { return err } err = datastore.DecodeBlob(aa, &n.Automatic) if err != nil { return err } err = datastore.DecodeBlob(na, &n.Normal) if err != nil { return err } err = datastore.DecodeBlob(da, &n.Default) if err != nil { return err } err = datastore.DecodeBlob(oa, &n.Override) if err != nil { return err } datastore.ChkNilArray(n) return nil }
func (cbv *CookbookVersion) fillCookbookVersionFromSQL(row datastore.ResRow) error { var ( defb []byte libb []byte attb []byte recb []byte prob []byte resb []byte temb []byte roob []byte filb []byte metb []byte major int64 minor int64 patch int64 ) err := row.Scan(&cbv.id, &cbv.cookbookID, &defb, &libb, &attb, &recb, &prob, &resb, &temb, &roob, &filb, &metb, &major, &minor, &patch, &cbv.IsFrozen, &cbv.CookbookName) if err != nil { return err } /* Now... populate it. :-/ */ // These may need to accept x.y versions with only two elements // instead of x.y.0 with the added default 0 patch number. cbv.Version = fmt.Sprintf("%d.%d.%d", major, minor, patch) cbv.Name = fmt.Sprintf("%s-%s", cbv.CookbookName, cbv.Version) cbv.ChefType = "cookbook_version" cbv.JSONClass = "Chef::CookbookVersion" /* TODO: experiment some more with getting this done with * pointers. */ err = datastore.DecodeBlob(metb, &cbv.Metadata) if err != nil { return err } err = datastore.DecodeBlob(defb, &cbv.Definitions) if err != nil { return err } err = datastore.DecodeBlob(libb, &cbv.Libraries) if err != nil { return err } err = datastore.DecodeBlob(attb, &cbv.Attributes) if err != nil { return err } err = datastore.DecodeBlob(recb, &cbv.Recipes) if err != nil { return err } err = datastore.DecodeBlob(prob, &cbv.Providers) if err != nil { return err } err = datastore.DecodeBlob(temb, &cbv.Templates) if err != nil { return err } err = datastore.DecodeBlob(resb, &cbv.Resources) if err != nil { return err } err = datastore.DecodeBlob(roob, &cbv.RootFiles) if err != nil { return err } err = datastore.DecodeBlob(filb, &cbv.Files) if err != nil { return err } datastore.ChkNilArray(cbv) return nil }