func (cc *Controller) CommitFeatures(ft *models.Feature, deleted bool) int { if cc.Config.GitEnabled() { printer.Say("committing changes") err := cc.Client.Commit(ft, deleted) if err != nil { printer.SayErr("%v", err) return 1 } sha, err := cc.Client.UpdateCurrentSHA() printer.Say("set info/current_sha: %s", sha) if err != nil { printer.SayErr("%v", err) return 1 } if cc.Config.PushEnabled() { printer.Say("pushing commit to origin") err = cc.Client.Push() if err != nil { printer.SayErr("%v", err) return 1 } } } return 0 }
func (cc *Controller) Delete(ctx climax.Context) int { name, _ := ctx.Get("name") scope, _ := ctx.Get("scope") if name == "" { printer.Say("name is required") return 1 } if scope == "" { scope = models.DefaultScope } err := cc.Client.Delete(name, scope) if err != nil { printer.SayErr("%v", err) return 1 } printer.Say("deleted flag %s/%s/%s", cc.Config.Namespace, scope, name) ft := &models.Feature{ Key: name, Scope: scope, UpdatedBy: cc.Config.Username, } return cc.CommitFeatures(ft, true) }
func (cc *Controller) List(ctx climax.Context) int { pf, _ := ctx.Get("prefix") scope, _ := ctx.Get("scope") if pf != "" && scope == "" { scope = models.DefaultScope } features, err := cc.Client.List(pf, scope) if err != nil { printer.SayErr("%v", err) return 1 } if len(features) == 0 { printer.Say("no feature flags found in namespace: %s", cc.Client.Namespace()) return 1 } ui.New().DrawFeatures(features) return 0 }
// KVsToFeatures helper for unmarshalling `KVBytes` to a `FeatureMap` func (c *Client) KVsToFeatureMap(kvb stores.KVBytes) (*models.FeatureMap, error) { fm := models.EmptyFeatureMap() for _, v := range kvb { var key string var value interface{} if v.Key == config.DefaultInfoNamespace { var info models.Info err := json.Unmarshal(v.Bytes, &info) if err != nil { return fm, err } fm.Dcdr.Info = &info } else { var ft models.Feature err := json.Unmarshal(v.Bytes, &ft) if err != nil { printer.SayErr("%s: %s", v.Key, v.Bytes) return fm, err } key = strings.Replace(v.Key, fmt.Sprintf("%s/features/", c.Namespace()), "", 1) value = ft.Value } explode(fm.Dcdr.FeatureScopes, key, value) } return fm, nil }
func (cc *Controller) Init(ctx climax.Context) int { if _, err := os.Stat(config.Path()); os.IsNotExist(err) { err = os.MkdirAll(path.Dir(config.Path()), filePerms) printer.Say("creating %s", path.Dir(config.Path())) if err != nil { printer.SayErr("could not create config directory: %v", err) return 1 } err = ioutil.WriteFile(config.Path(), config.ExampleConfig, filePerms) printer.Say("%s not found. creating example config", config.Path()) if err != nil { printer.SayErr("could not write config.hcl %v", err) return 1 } } if !cc.Config.GitEnabled() { printer.Say("no repository configured. skipping") return 0 } create := ctx.Is("create") err := cc.Client.InitRepo(create) if err != nil { printer.SayErr("%v", err) return 1 } if create { printer.Say("initialized new repo in %s and pushed to %s", cc.Config.Git.RepoPath, cc.Config.Git.RepoURL) } else { printer.Say("cloned %s into %s", cc.Config.Git.RepoURL, cc.Config.Git.RepoPath) } return 0 }
func readConfig() *Config { bts, err := ioutil.ReadFile(Path()) if err != nil { printer.SayErr("Could not read %s", Path()) os.Exit(1) } var cfg *Config defaults := DefaultConfig() err = hcl.Decode(&cfg, string(bts[:])) if err != nil { printer.SayErr("[dcdr] config parse error %+v", err) os.Exit(1) } if cfg.Namespace == "" { cfg.Namespace = defaults.Namespace } if cfg.Username == "" { cfg.Username = defaults.Username } if cfg.Watcher.OutputPath == "" { cfg.Watcher.OutputPath = defaults.Watcher.OutputPath } if cfg.Server.Host == "" { cfg.Server.Host = defaults.Server.Host } if cfg.Server.Endpoint == "" { cfg.Server.Endpoint = defaults.Server.Endpoint } if cfg.Server.JSONRoot == "" { cfg.Server.JSONRoot = defaults.Server.JSONRoot } return cfg }
func (cc *Controller) Set(ctx climax.Context) int { ft, err := cc.ParseContext(ctx) if err != nil { printer.SayErr("parse error: %v", err) return 1 } err = cc.Client.Set(ft) if err != nil { printer.SayErr("set error: %v", err) return 1 } printer.Say("set flag '%s'", ft.ScopedKey()) return cc.CommitFeatures(ft, false) }
// UpdateFeatures creates and assigns a new `FeatureMap` from a // Marshalled JSON byte array func (c *Client) UpdateFeatures(bts []byte) { fm, err := models.NewFeatureMap(bts) if err != nil { printer.SayErr("parse error: %v", err) return } c.SetFeatureMap(fm) }
func (cc *Controller) Import(ctx climax.Context) int { bts, err := ioutil.ReadAll(os.Stdin) if err != nil { printer.SayErr("%v", err) return 1 } var kvs map[string]interface{} err = json.Unmarshal(bts, &kvs) if err != nil { printer.SayErr("%v", err) return 1 } scope, _ := ctx.Get("scope") if scope == "" { scope = models.DefaultScope } for k, v := range kvs { f := models.NewFeature(k, v, "", "", scope, cc.Config.Namespace) err = cc.Client.Set(f) if err != nil { printer.SayErr("%v", err) return 1 } printer.Say("set %s to %+v", k, v) } return 1 }
func GitExec() string { if gitExec != "" { return gitExec } output, err := exec.Command("which", "git").Output() if err != nil { printer.SayErr("git not found: %v", err) os.Exit(1) } gitExec = strings.TrimSpace(string(output[:])) return gitExec }
func main() { cfg := config.LoadConfig() store := resolver.LoadStore(cfg) rp := repo.New(cfg) var gs *godspeed.Godspeed var err error if cfg.StatsEnabled() { gs, err = godspeed.New(cfg.Stats.Host, cfg.Stats.Port, false) if err != nil { printer.SayErr("%v", err) os.Exit(1) } } kv := api.New(store, rp, cfg, gs) ctrl := controller.New(cfg, kv) dcdr := cli.New(ctrl) dcdr.Run() }