func (r Reader) ReadMessage() ([]byte, error) { c, err := r.b.ReadByte() if err != nil { return nil, stackerr.Wrap(err) } if c != byte(0x0b) { return nil, ErrInvalidHeader(stackerr.Newf("invalid header found; expected 0x0b but got %02x", c)) } d, err := r.b.ReadBytes(byte(0x1c)) if err != nil { return nil, stackerr.Wrap(err) } if len(d) < 2 { return nil, ErrInvalidContent(stackerr.Newf("content including boundary should be at least two bytes long; instead was %d", len(d))) } if d[len(d)-2] != 0x0d { return nil, ErrInvalidBoundary(stackerr.Newf("content should end with 0x0d; instead was %02x", d[len(d)-2])) } t, err := r.b.ReadByte() if err != nil { return nil, stackerr.Wrap(err) } if t != byte(0x0d) { return nil, ErrInvalidTrailer(stackerr.Newf("invalid trailer found; expected 0x0d but got %02x", t)) } return d[0 : len(d)-2], nil }
func (u *updateCmd) updateCLI(e *env) (bool, error) { downloadURL, err := u.getDownloadURL(e) if err != nil { return false, err } if downloadURL == "" { return false, nil } exec, err := osext.Executable() if err != nil { return false, stackerr.Wrap(err) } fmt.Fprintf(e.Out, "Downloading binary from %s.\n", downloadURL) resp, err := http.Get(downloadURL) if err != nil { return false, stackerr.Newf("Update failed with error: %v", err) } defer resp.Body.Close() err = update.Apply(resp.Body, update.Options{TargetPath: exec}) if err != nil { return false, stackerr.Newf("Update failed with error: %v", err) } fmt.Fprintf(e.Out, "Successfully updated binary at: %s\n", exec) return true, nil }
func (l *Login) AuthToken(e *Env, token string) (string, error) { req := &http.Request{ Method: "POST", URL: &url.URL{Path: "accountkey"}, Body: ioutil.NopCloser( jsonpipe.Encode( map[string]string{ "accountKey": token, }, ), ), } res := &struct { Email string `json:"email"` }{} if response, err := e.ParseAPIClient.Do(req, nil, res); err != nil { if response != nil && response.StatusCode == http.StatusUnauthorized { return "", stackerr.Newf(tokenErrMsgf, Last4(token), keysURL) } return "", stackerr.Wrap(err) } if e.ParserEmail != "" && res.Email != e.ParserEmail { return "", stackerr.Newf("Account key %q does not belong to %q", Last4(token), e.ParserEmail) } return res.Email, nil }
func (g *Generator) genRootCA() error { certFileName := g.certFileName() keyFileName := g.keyFileName() if _, err := os.Stat(certFileName); !os.IsNotExist(err) { return stackerr.Newf("%s must not exist", certFileName) } if _, err := os.Stat(keyFileName); !os.IsNotExist(err) { return stackerr.Newf("%s must not exist", keyFileName) } priv, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return stackerr.Wrap(err) } now := time.Now() template := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(0), Subject: pkix.Name{ CommonName: g.RootName, }, NotBefore: now.Add(-5 * time.Minute).UTC(), NotAfter: now.Add(g.MaxAge), IsCA: true, SubjectKeyId: []byte{1, 2, 3, 4}, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageCRLSign, BasicConstraintsValid: true, } derBytes, err := x509.CreateCertificate( rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return stackerr.Wrap(err) } certOut, err := os.Create(certFileName) if err != nil { return stackerr.Wrap(err) } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() log.Print("Written " + certFileName + "\n") keyOut, err := os.OpenFile(keyFileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return stackerr.Wrap(err) } pem.Encode(keyOut, &pem.Block{ Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv), }) keyOut.Close() log.Print("Written " + keyFileName + "\n") return nil }
func (c *ParseConfig) AddAlias(name, link string) error { if _, found := c.Applications[name]; found { return stackerr.Newf("App %q has already been added.", name) } if _, found := c.Applications[link]; !found { return stackerr.Newf("App %q wasn't found.", link) } c.Applications[name] = &ParseAppConfig{Link: link} return nil }
func (c *ParseConfig) App(name string) (AppConfig, error) { ac, found := c.Applications[name] if !found { if name == DefaultKey { return nil, stackerr.Newf("No default app configured.") } return nil, stackerr.Newf("App %q wasn't found.", name) } if ac.Link != "" { return c.App(ac.Link) } return ac, nil }
func (l *Login) GetTokenCredentials(e *Env, email string) (bool, *Credentials, error) { reader, err := l.getTokensReader() if err != nil { return false, nil, stackerr.Wrap(err) } tokens, err := netrc.Parse(reader) if err != nil { return false, nil, stackerr.Wrap(err) } server, err := getHostFromURL(e.Server, email) if err != nil { return false, nil, err } machine := tokens.FindMachine(server) if machine != nil { return true, &Credentials{ Token: machine.Password, }, nil } if email == "" { return false, nil, stackerr.Newf("Could not find account key for %q", server) } // check for system default account key for the given server // since we could not find account key for the given account (email) server, err = getHostFromURL(e.Server, "") if err != nil { return false, nil, err } machine = tokens.FindMachine(server) if machine != nil { return false, &Credentials{ Token: machine.Password, }, nil } return false, nil, stackerr.Newf( `Could not find account key for email: %q, and default access key not configured for %q `, email, e.Server, ) }
func (manager *StateManager) Start() error { corelog.LogInfoMessage("starting manager") manager.Lock() defer manager.Unlock() var err error manager.currentReplicaSetState, err = manager.generateReplicaSetState() if err != nil { return err return errors.New(fmt.Sprintf("error starting statemanager, replicaset in flux: %v", err)) } healthyAddrs := manager.currentReplicaSetState.Addrs() // Ensure we have at least one health address. if len(healthyAddrs) == 0 { return stackerr.Newf("no healthy primaries or secondaries: %s", manager.replicaSet.Addrs) } manager.addProxies(healthyAddrs...) for _, proxy := range manager.proxies { go manager.startProxy(proxy) } manager.refreshTime = time.Now() return nil }
func (g *gitInfo) isGitRepo(e *parsecli.Env) error { _, err := os.Lstat(filepath.Join(e.Root, ".git")) if os.IsNotExist(err) { return stackerr.Newf("%s is not a git repository. Please run 'git init'", e.Root) } return nil }
func selectHerokuApp(apps nameIDs, e *parsecli.Env) (*nameID, error) { fmt.Fprintf(e.Out, "Please select from the following Heroku apps: (Enter a number between 1 and %d)\n", len(apps)) for i, app := range apps { w := new(tabwriter.Writer) w.Init(e.Out, 0, 8, 0, '\t', 0) fmt.Fprintf(w, "%d: %s\t\t(%s)\n", i+1, app.name, app.id) if err := w.Flush(); err != nil { return nil, stackerr.Wrap(err) } } fmt.Fprintf(e.Out, "Selection: ") var selection string fmt.Fscanf(e.In, "%s\n", &selection) n, err := strconv.Atoi(selection) if err != nil { return nil, err } lapps := len(apps) if n <= 0 || n > lapps { return nil, stackerr.Newf("Invalid selection: can only be in range 1..%d", lapps) } return &apps[n-1], nil }
func (s *symbolsCmd) run(e *env, c *context) error { android := &androidSymbolUploader{ Path: s.path, Apk: s.apk, Manifest: s.manifest, AAPT: s.aapt} ios := &iosSymbolUploader{ Path: s.path, SkipOsCheck: s.skipOsCheck} switch { case android.acceptsPath(): if err := android.validate(); err != nil { return err } fmt.Fprintln(e.Out, "Uploading Android symbol files...") return android.uploadSymbols(e) case ios.acceptsPath(): if err := ios.validate(); err != nil { return err } fmt.Fprintln(e.Out, "Uploading iOS symbol files...") return ios.uploadSymbols(e) default: if s.path == "" { return stackerr.New("Please specify path to symbol files") } return stackerr.Newf("Do not understand symbol files at : %s", s.path) } }
func (r *releasesCmd) printFiles(version string, releases []releasesResponse, e *env) error { var files string for _, release := range releases { if release.Version == version { files = release.UserFiles break } } if files == "" { return stackerr.Newf(`Unable to fetch files for release version: %s Note that you can list files for all releases shown in "parse releases"`, version) } var versionFileNames userFiles if err := json.NewDecoder( strings.NewReader(files), ).Decode(&versionFileNames); err != nil { return stackerr.Wrap(err) } if len(versionFileNames.Cloud) != 0 { fmt.Fprintf(e.Out, "Deployed cloud code files:\n") r.printFileNames(versionFileNames.Cloud, e) } if len(versionFileNames.Cloud) != 0 && len(versionFileNames.Public) != 0 { fmt.Fprintln(e.Out) } if len(versionFileNames.Public) != 0 { fmt.Fprintf(e.Out, "Deployed public hosting files:\n") r.printFileNames(versionFileNames.Public, e) } return nil }
func (i *iosSymbolUploader) convertSymbols(e *env) ([]string, error) { homedir, err := homedir.Dir() if err != nil { return nil, stackerr.Wrap(err) } folderPath := filepath.Join(homedir, ".parse", "CrashReportingSymbols") if err := i.prepareSymbolsFolder(folderPath, e); err != nil { return nil, stackerr.Wrap(err) } conversionTool, err := i.symbolConversionTool(homedir, nil, e) if err != nil { return nil, stackerr.Wrap(err) } cmd := exec.Command(conversionTool, i.Path, folderPath) if out, err := cmd.CombinedOutput(); err != nil { return nil, stackerr.Newf("Symbol conversion failed with:\n%s", string(out)) } filenames, err := readDirNames(folderPath) if err != nil { return nil, stackerr.Wrap(err) } return filenames, nil }
func (l *logsCmd) run(e *env, c *context) error { level := strings.ToUpper(l.level) if level != "INFO" && level != "ERROR" { return stackerr.Newf("invalid level: %q", l.level) } l.level = level numIsSet := true if l.num == 0 { numIsSet = false l.num = 10 } lastTime, err := l.round(e, c, nil) if err != nil { return err } if !l.follow { return nil } if !numIsSet { l.num = 100 // force num to 100 for follow } ticker := e.Clock.Ticker(logFollowSleepDuration) defer ticker.Stop() for range ticker.C { lastTime, err = l.round(e, c, lastTime) if err != nil { return err } } return nil }
func (u *updateCmd) updateCLI(e *env) (bool, error) { downloadURL := unixCliDownloadURL switch runtime.GOOS { case "windows": downloadURL = windowsCliDownloadURL case "darwin": downloadURL = macCliDownloadURL } latestVersion, err := u.latestVersion(e, downloadURL) if err != nil { return false, stackerr.Wrap(err) } if latestVersion == "" || latestVersion == version { return false, nil } exec, err := osext.Executable() if err != nil { return false, stackerr.Wrap(err) } fmt.Fprintf(e.Out, "Downloading binary from %s.\n", downloadURL) if err, _ := update.New().Target(exec).FromUrl(downloadURL); err != nil { return false, stackerr.Newf("Update failed: %v", err) } fmt.Fprintf(e.Out, "Successfully updated binary at: %s\n", exec) return true, nil }
func (d *defaultCmd) run(e *env, args []string) error { var newDefault string if len(args) > 1 { return stackerr.Newf("unexpected arguments, only an optional app name is expected: %v", args) } if len(args) == 1 { newDefault = args[0] } config, err := configFromDir(e.Root) if err != nil { return err } if config.getNumApps() == 0 { return stackerr.New("No apps are associated with this project. You can add some with parse add") } defaultApp := config.getDefaultApp() switch newDefault { case "": return d.printDefault(e, defaultApp) default: return d.setDefault(e, newDefault, defaultApp, config) } }
func fetchAppKeys(e *env, appID string) (*app, error) { l := &login{} err := l.authUser(e) if err != nil { return nil, err } credentials := &l.credentials req := &http.Request{ Method: "GET", URL: &url.URL{Path: path.Join("apps", appID)}, Header: getAuthHeaders(credentials, nil), } res := &app{} if response, err := e.ParseAPIClient.Do(req, nil, res); err != nil { if response.StatusCode == http.StatusUnauthorized { return nil, errAuth } return nil, err } if res == nil { return nil, stackerr.Newf("Unable to fetch keys for %s.", appID) } return res, nil }
func (a *apps) selectApp(apps []*app, msg string, e *env) (*app, error) { appNames := allApps(apps) appCount := len(apps) pos := -1 var err error for { fmt.Fprintf(e.Out, "%s%s", selectionString(appNames), msg) var selected string fmt.Fscanf(e.In, "%s", &selected) if pos, err = strconv.Atoi(strings.TrimSpace(selected)); err != nil { pos = -1 break } if pos > 0 && pos <= appCount { break } else { fmt.Fprintf(e.Out, "Invalid selection %d: must be between 1 and %d\n", pos, appCount) pos = -1 } } if pos != -1 { appName := appNames[pos-1] for _, app := range apps { if app.Name == appName { return app, nil } } } return nil, stackerr.Newf("Please try again. Please select from among the listed apps.") }
func (d *daemon) validateFile() error { if d.fileName == "" { return stackerr.Newf("Invalid config file. File path cannot be empty.") } if !filepath.IsAbs(d.fileName) { return stackerr.Newf("Invalid config file: [%s]. File path must be absolute path.", d.fileName) } dir := filepath.Dir(d.fileName) if _, err := os.Stat(dir); os.IsNotExist(err) { return stackerr.Newf("Invalid config file: [%s]. The enclosing directory [%s] does not exit.", d.fileName, dir) } if _, err := os.Stat(d.fileName); os.IsNotExist(err) { d.log.Printf("[INFO]: [%s] doesn't exist. Going to create a new one.", d.fileName) } return nil }
func (u *updateCmd) updateCLI(e *env) (bool, error) { ostype := runtime.GOOS arch := runtime.GOARCH latestVersion, err := u.latestVersion(e) if err != nil { return false, err } if latestVersion == "" || latestVersion == version { return false, nil } var downloadURL string switch ostype { case "darwin": downloadURL = fmt.Sprintf(downloadURLFormat, latestVersion, macDownload) case "windows": downloadURL = fmt.Sprintf(downloadURLFormat, latestVersion, windowsDownload) case "linux": if arch == "arm" { downloadURL = fmt.Sprintf(downloadURLFormat, latestVersion, linuxArmDownload) } else { downloadURL = fmt.Sprintf(downloadURLFormat, latestVersion, linuxDownload) } } exec, err := osext.Executable() if err != nil { return false, stackerr.Wrap(err) } fmt.Fprintf(e.Out, "Downloading binary from %s.\n", downloadURL) resp, err := http.Get(downloadURL) if err != nil { return false, stackerr.Newf("Update failed with error: %v", err) } defer resp.Body.Close() err = update.Apply(resp.Body, &update.Options{TargetPath: exec}) if err != nil { return false, stackerr.Newf("Update failed with error: %v", err) } fmt.Fprintf(e.Out, "Successfully updated binary at: %s\n", exec) return true, nil }
func fetchHerokuAppInfo(e *parsecli.Env, appConfig *parsecli.HerokuAppConfig) (*heroku.App, error) { herokuAppInfo, err := e.HerokuAPIClient.AppInfo(appConfig.HerokuAppID) if err != nil { return nil, stackerr.Newf( "Unable to fetch app info for: %q from heroku.", appConfig.HerokuAppID, ) } return herokuAppInfo, nil }
func (d *defaultCmd) setDefault(e *env, newDefault, defaultApp string, c config) error { if c.getProjectConfig().Type == legacy { p, ok := c.(*parseConfig) if !ok { return stackerr.New("Invalid Cloud Code config.") } return d.setParseDefault(e, newDefault, defaultApp, p) } return stackerr.Newf("Project type not configured.") }
func TestNewf(t *testing.T) { const fmtStr = "%s 42" const errStr = "foo bar baz" e := stackerr.Newf(fmtStr, errStr) matches := []string{ fmt.Sprintf(fmtStr, errStr), "stackerr_test.go:26 +TestNewf$", } match(t, e.Error(), matches) }
func storeConfig(e *env, c config) error { projectType := c.getProjectConfig().Type switch projectType { case legacyParseFormat: pc, ok := (c).(*parseConfig) if !ok { return stackerr.Newf("Incorrect project type: 'legacy'.") } lconf := &legacyConfig{Applications: pc.Applications} lconf.Global.ParseVersion = pc.projectConfig.Parse.JSSDK return writeLegacyConfigFile( lconf, filepath.Join(e.Root, legacyConfigFile), ) case parseFormat: return writeConfigFile(c, filepath.Join(e.Root, parseLocal)) } return stackerr.Newf("Unknown project type: %d.", projectType) }
func (g *generateCmd) validateArgs() error { if _, ok := validTypes[g.generateType]; !ok { var buf bytes.Buffer for key := range validTypes { buf.WriteString(key) buf.WriteString(comma) } return stackerr.Newf("type can only be one of {%s}", buf.String()) } return nil }
func (g *Generator) loadPem(filename string) (*pem.Block, error) { in, err := ioutil.ReadFile(filename) if err != nil { return nil, stackerr.Wrap(err) } b, _ := pem.Decode(in) if b == nil { return nil, stackerr.Newf("failed to pem decode %s", filename) } return b, nil }
func getHostFromURL(urlStr string) (string, error) { netURL, err := url.Parse(urlStr) if err != nil { return "", stackerr.Wrap(err) } server := regexp.MustCompile(`(.*):\d+$`).ReplaceAllString(netURL.Host, "$1") if server == "" { return "", stackerr.Newf("%s is not a valid url", urlStr) } return server, nil }
func newParseAPIClient(e *env) (*ParseAPIClient, error) { baseURL, err := url.Parse(e.Server) if err != nil { return nil, stackerr.Newf("invalid server URL %q: %s", e.Server, err) } return &ParseAPIClient{ apiClient: &parse.Client{ BaseURL: baseURL, }, }, nil }
func AddSelectedParseApp( appName string, appConfig *parsecli.ParseAppConfig, args []string, makeDefault, verbose bool, e *parsecli.Env, ) error { config, err := parsecli.ConfigFromDir(e.Root) if err != nil { return err } parseConfig, ok := config.(*parsecli.ParseConfig) if !ok { return stackerr.New("Invalid Cloud Code config.") } // add app to config if _, ok := parseConfig.Applications[appName]; ok { return stackerr.Newf("App %s has already been added", appName) } parseConfig.Applications[appName] = appConfig if len(args) > 0 && args[0] != "" { alias := args[0] aliasConfig, ok := parseConfig.Applications[alias] if !ok { parseConfig.Applications[alias] = &parsecli.ParseAppConfig{Link: appName} } if ok && aliasConfig.GetLink() != "" { fmt.Fprintf(e.Out, "Overwriting alias: %q to point to %q\n", alias, appName) parseConfig.Applications[alias] = &parsecli.ParseAppConfig{Link: appName} } } if makeDefault { if _, ok := parseConfig.Applications[parsecli.DefaultKey]; ok { return stackerr.New(`Default key already set. To override default, use command "parse default"`) } parseConfig.Applications[parsecli.DefaultKey] = &parsecli.ParseAppConfig{Link: appName} } if err := parsecli.StoreConfig(e, parseConfig); err != nil { return err } if verbose { fmt.Fprintf(e.Out, "Written config for %q\n", appName) if makeDefault { fmt.Fprintf(e.Out, "Set %q as default\n", appName) } } return nil }
func configFromDir(dir string) (config, error) { l, err := readLegacyConfigFile(filepath.Join(dir, legacyConfigFile)) if err != nil && !stackerr.HasUnderlying(err, stackerr.MatcherFunc(os.IsNotExist)) { return nil, err } if l != nil { // legacy config format projectConfig := &projectConfig{ Type: legacyParseFormat, Parse: &parseProjectConfig{ JSSDK: l.Global.ParseVersion, }, ParserEmail: l.Global.ParserEmail, } applications := l.Applications if applications == nil { applications = make(map[string]*parseAppConfig) } return &parseConfig{ Applications: applications, projectConfig: projectConfig, }, nil } canonicalize := func(err error) error { if err == nil { return nil } if stackerr.HasUnderlying(err, stackerr.MatcherFunc(os.IsNotExist)) { return stackerr.New("Command must be run inside a Parse project.") } return err } // current config format p, err := readProjectConfigFile(filepath.Join(dir, parseProject)) if err != nil { return nil, canonicalize(err) } configFile := filepath.Join(dir, parseLocal) switch p.Type { case parseFormat: c, err := readParseConfigFile(configFile) if err != nil { return nil, canonicalize(err) } if c.Applications == nil { c.Applications = make(map[string]*parseAppConfig) } c.projectConfig = p return c, nil } return nil, stackerr.Newf("Unknown project type: %d.", p.Type) }