예제 #1
0
func updateBinary(v semver.Version, downloadBinary, updateLinkPrefix, downloadLinkFormat string) {
	checksum, err := downloadChecksum(v, downloadBinary, downloadLinkFormat)
	if err != nil {
		glog.Errorf("Cannot download checksum: %s", err)
		os.Exit(1)
	}
	binary, err := http.Get(fmt.Sprintf(downloadLinkFormat, v, downloadBinary))
	if err != nil {
		glog.Errorf("Cannot download binary: %s", err)
		os.Exit(1)
	}
	defer binary.Body.Close()
	err = update.Apply(binary.Body, update.Options{
		Hash:     crypto.SHA256,
		Checksum: checksum,
	})
	if err != nil {
		glog.Errorf("Cannot apply binary update: %s", err)
		os.Exit(1)
	}

	env := os.Environ()
	args := os.Args
	currentBinary, err := osext.Executable()
	if err != nil {
		glog.Errorf("Cannot find current binary to exec: %s", err)
		os.Exit(1)
	}
	err = syscall.Exec(currentBinary, args, env)
	if err != nil {
		glog.Errorf("Failed to exec updated binary: %s", err)
		os.Exit(1)
	}
}
예제 #2
0
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
}
예제 #3
0
// Start starts the e2e services in another process, it returns when all e2e
// services are ready.
// We want to statically link e2e services into the test binary, but we don't
// want their glog to pollute the test result. So we run the binary in run-
// services-mode to start e2e services in another process.
func (e *E2EServices) Start() error {
	var err error
	// Create the manifest path for kubelet.
	// TODO(random-liu): Remove related logic when we move kubelet starting logic out of the test.
	framework.TestContext.ManifestPath, err = ioutil.TempDir("", "node-e2e-pod")
	if err != nil {
		return fmt.Errorf("failed to create static pod manifest directory: %v", err)
	}
	testBin, err := osext.Executable()
	if err != nil {
		return fmt.Errorf("can't get current binary: %v", err)
	}
	// TODO(random-liu): Add sudo after we statically link apiserver and etcd, because apiserver needs
	// sudo. We can't add sudo now, because etcd may not be in PATH of root.
	startCmd := exec.Command(testBin,
		"--run-services-mode",
		"--server-start-timeout", serverStartTimeout.String(),
		"--report-dir", framework.TestContext.ReportDir,
		// TODO(random-liu): Remove the following flags after we move kubelet starting logic
		// out of the test.
		"--node-name", framework.TestContext.NodeName,
		"--disable-kubenet="+strconv.FormatBool(framework.TestContext.DisableKubenet),
		// TODO: enable when flag is introduced in 1.5
		// "--cgroups-per-qos="+strconv.FormatBool(framework.TestContext.CgroupsPerQOS),
		"--manifest-path", framework.TestContext.ManifestPath,
		"--eviction-hard", framework.TestContext.EvictionHard,
		"--logtostderr",
		"--vmodule=*=4",
	)
	e.services = newServer("services", startCmd, nil, nil, getHealthCheckURLs(), servicesLogFile, false)
	return e.services.start()
}
예제 #4
0
파일: agent.go 프로젝트: djui/dlite
func CreateAgent() error {
	path, err := osext.Executable()
	if err != nil {
		return err
	}

	fileDir := os.ExpandEnv("$HOME/Library/LaunchAgents")
	err = os.MkdirAll(fileDir, 0755)
	if err != nil {
		return err
	}

	err = changePermissions(fileDir)
	if err != nil {
		return err
	}

	filePath := os.ExpandEnv("$HOME/Library/LaunchAgents/local.dlite.plist")
	file, err := os.Create(filePath)
	if err != nil {
		return err
	}

	plist := fmt.Sprintf(template, path)
	_, err = file.WriteString(plist)
	if err != nil {
		return err
	}

	return changePermissions(filePath)
}
예제 #5
0
func (u *Update) getPath() (string, error) {
	if u.TargetPath == "" {
		return osext.Executable()
	} else {
		return u.TargetPath, nil
	}
}
예제 #6
0
파일: util.go 프로젝트: Oskoss/rexray
func GetThisPathParts() (dirPath, fileName, absPath string) {
	exeFile, err := osext.Executable()
	if err != nil {
		panic(err)
	}
	return GetPathParts(exeFile)
}
예제 #7
0
파일: config.go 프로젝트: ack/terraform
// Discover plugins located on disk, and fall back on plugins baked into the
// Terraform binary.
//
// We look in the following places for plugins:
//
// 1. Terraform configuration path
// 2. Path where Terraform is installed
// 3. Path where Terraform is invoked
//
// Whichever file is discoverd LAST wins.
//
// Finally, we look at the list of plugins compiled into Terraform. If any of
// them has not been found on disk we use the internal version. This allows
// users to add / replace plugins without recompiling the main binary.
func (c *Config) Discover(ui cli.Ui) error {
	// Look in ~/.terraform.d/plugins/
	dir, err := ConfigDir()
	if err != nil {
		log.Printf("[ERR] Error loading config directory: %s", err)
	} else {
		if err := c.discover(filepath.Join(dir, "plugins")); err != nil {
			return err
		}
	}

	// Next, look in the same directory as the Terraform executable, usually
	// /usr/local/bin. If found, this replaces what we found in the config path.
	exePath, err := osext.Executable()
	if err != nil {
		log.Printf("[ERR] Error loading exe directory: %s", err)
	} else {
		if err := c.discover(filepath.Dir(exePath)); err != nil {
			return err
		}
	}

	// Finally look in the cwd (where we are invoke Terraform). If found, this
	// replaces anything we found in the config / install paths.
	if err := c.discover("."); err != nil {
		return err
	}

	// Finally, if we have a plugin compiled into Terraform and we didn't find
	// a replacement on disk, we'll just use the internal version.
	for name, _ := range command.InternalProviders {
		if path, found := c.Providers[name]; found {
			ui.Warn(fmt.Sprintf("[WARN] %s overrides an internal plugin for %s-provider.\n"+
				"  If you did not expect to see this message you will need to remove the old plugin.\n"+
				"  See https://www.terraform.io/docs/internals/internal-plugins.html", path, name))
		} else {

			cmd, err := command.BuildPluginCommandString("provider", name)
			if err != nil {
				return err
			}
			c.Providers[name] = cmd
		}
	}
	for name, _ := range command.InternalProvisioners {
		if path, found := c.Provisioners[name]; found {
			ui.Warn(fmt.Sprintf("[WARN] %s overrides an internal plugin for %s-provisioner.\n"+
				"  If you did not expect to see this message you will need to remove the old plugin.\n"+
				"  See https://www.terraform.io/docs/internals/internal-plugins.html", path, name))
		} else {
			cmd, err := command.BuildPluginCommandString("provisioner", name)
			if err != nil {
				return err
			}
			c.Provisioners[name] = cmd
		}
	}

	return nil
}
예제 #8
0
파일: status.go 프로젝트: thanzen/agostle
func onStart() {
	var err error
	if self, err = osext.Executable(); err != nil {
		logger.Warn("msg", "error getting the path for self", "error", err)
	} else {
		var self2 string
		if self2, err = filepath.Abs(self); err != nil {
			logger.Warn("msg", "error getting the absolute path for "+self, "error", err)
		} else {
			self = self2
		}
	}

	if version != "" {
		self = self + " (" + version + ")"
	}

	var uname string
	if u, e := user.Current(); e != nil {
		logger.Warn("msg", "cannot get current user", "error", e)
		uname = os.Getenv("USER")
	} else {
		uname = u.Username
	}
	i := len(topCmd) - 1
	topCmd[i] = topCmd[i] + uname

	stats.startedat = time.Now().Format(time.RFC3339)
}
예제 #9
0
파일: config.go 프로젝트: c12simple/packer
// Discover discovers plugins.
//
// Search the directory of the executable, then the plugins directory, and
// finally the CWD, in that order. Any conflicts will overwrite previously
// found plugins, in that order.
// Hence, the priority order is the reverse of the search order - i.e., the
// CWD has the highest priority.
func (c *config) Discover() error {
	// First, look in the same directory as the executable.
	exePath, err := osext.Executable()
	if err != nil {
		log.Printf("[ERR] Error loading exe directory: %s", err)
	} else {
		if err := c.discover(filepath.Dir(exePath)); err != nil {
			return err
		}
	}

	// Next, look in the plugins directory.
	dir, err := packer.ConfigDir()
	if err != nil {
		log.Printf("[ERR] Error loading config directory: %s", err)
	} else {
		if err := c.discover(filepath.Join(dir, "plugins")); err != nil {
			return err
		}
	}

	// Next, look in the CWD.
	if err := c.discover("."); err != nil {
		return err
	}

	// Finally, try to use an internal plugin. Note that this will not override
	// any previously-loaded plugins.
	if err := c.discoverInternal(); err != nil {
		return err
	}

	return nil
}
예제 #10
0
func runSelfUpdate(ctx *cli.Context) {
	version := "latest"
	if len(ctx.Args()) > 0 {
		version = ctx.Args()[0]
	}
	release, err := getRelease(version)
	if err != nil {
		util.Fatal("Unable to fetch release data")
	}
	filename := "vagabond_" + runtime.GOOS + "_" + runtime.GOARCH
	asset, found := assetSearch(release.Assets, filename)
	if !found {
		util.Fatal("Unable to find a release asset for this OS and architecture.  Expected to find " + filename)
	}
	srcfile, err := fetchAsset(asset)
	if err != nil {
		util.Fatalf("Failed fetching file: %s", err)
	}
	dstFile, err := osext.Executable()
	if err != nil {
		util.Fatalf("Failed determining current binary: %s", err)
	}
	err = copyFileOver(srcfile, dstFile)
	if err != nil {
		util.Fatalf("Failed replacing current binary.")
	}
	util.Successf("Updated to %s (%s)", *release.TagName, dstFile)
}
예제 #11
0
func CreateLaunchFile(autoLaunch bool) {
	var err error
	var content bytes.Buffer
	fname := appdir.InHomeDir(LaunchdPlistFile)

	lanternPath, err := osext.Executable()
	if err != nil {
		log.Errorf("Could not get Lantern directory path: %q", err)
		return
	}
	log.Debugf("Using lantern path: %v", lanternPath)

	// Create plist template and set RunAtLoad property
	t := template.Must(template.New("LaunchdPlist").Parse(LaunchdPlist))

	err = t.Execute(&content, &Plist{RunAtLoad: autoLaunch, Path: lanternPath})
	if err != nil {
		log.Errorf("Error writing plist template: %q", err)
		return
	}

	if err = ioutil.WriteFile(fname, content.Bytes(), 0755); err != nil {
		log.Errorf("Error writing to launchd plist file: %q", err)
	}
}
예제 #12
0
func exeDir() (string, error) {
	exe, err := osext.Executable()
	if err != nil {
		return "", err
	}
	return path.Dir(exe), nil
}
예제 #13
0
파일: testtask.go 프로젝트: bastiaanb/nomad
// Path returns the path to the currently running executable.
func Path() string {
	path, err := osext.Executable()
	if err != nil {
		panic(err)
	}
	return path
}
예제 #14
0
func loadFullExePath() {
	if exe, err := osext.Executable(); err != nil {
		panic("Cannot find EXE path, error: " + err.Error())
	} else {
		FULL_EXE_PATH = exe
	}
}
예제 #15
0
func (u *Updater) update() error {
	path, err := osext.Executable()
	if err != nil {
		return err
	}
	old, err := os.Open(path)
	if err != nil {
		return err
	}
	defer old.Close()

	err = u.fetchInfo()
	if err != nil {
		return err
	}
	if u.Info.Version == u.CurrentVersion {
		return nil
	}
	bin, err := u.fetchAndVerifyPatch(old)
	if err != nil {
		if err == ErrHashMismatch {
			log.Println("update: hash mismatch from patched binary")
		} else {
			if u.DiffURL != "" {
				log.Println("update: patching binary,", err)
			}
		}

		bin, err = u.fetchAndVerifyFullBin()
		if err != nil {
			if err == ErrHashMismatch {
				log.Println("update: hash mismatch from full binary")
			} else {
				log.Println("update: fetching full binary,", err)
			}
			return err
		}
	}

	// close the old binary before installing because on windows
	// it can't be renamed if a handle to the file is still open
	old.Close()

	err, errRecover := up.FromStream(bytes.NewBuffer(bin))
	if errRecover != nil {
		return fmt.Errorf("update and recovery errors: %q %q", err, errRecover)
	}
	if err != nil {
		return err
	}

	// remove config.ini so at restart the package will extract again
	shutil.CopyFile(*configIni, *configIni+".bak", false)
	os.Remove(*configIni)

	// update done, we should decide if we need to restart ASAP (maybe a field in update json?)
	// BIG issue: the file has been renamed in the meantime

	return nil
}
예제 #16
0
func getMoonLauncher() *MoonLauncher {
	if moonLauncher != nil {
		return moonLauncher
	}

	moonLauncher = &MoonLauncher{
		name: "MoonDeploy",
	}

	moonLauncher.title = fmt.Sprintf("%v %v", moonLauncher.name, moondeploy.Version)

	var err error
	moonLauncher.executable, err = osext.Executable()
	if err != nil {
		panic(err)
	}

	moonLauncher.directory, err = osext.ExecutableFolder()
	if err != nil {
		panic(err)
	}

	moonLauncher.iconPathAsIco = filepath.Join(moonLauncher.directory, "moondeploy.ico")
	moonLauncher.iconPathAsPng = filepath.Join(moonLauncher.directory, "moondeploy.png")

	moonLauncher.settings = getMoonSettings()

	return moonLauncher
}
예제 #17
0
func (ws *windowsService) Install() error {
	exepath, err := osext.Executable()
	if err != nil {
		return err
	}
	// Used if path contains a space.
	exepath = `"` + exepath + `"`
	m, err := mgr.Connect()
	if err != nil {
		return err
	}
	defer m.Disconnect()
	s, err := m.OpenService(ws.name)
	if err == nil {
		s.Close()
		return fmt.Errorf("service %s already exists", ws.name)
	}
	s, err = m.CreateService(ws.name, exepath, mgr.Config{
		DisplayName: ws.displayName,
		Description: ws.description,
		StartType:   mgr.StartAutomatic,
	})
	if err != nil {
		return err
	}
	defer s.Close()
	err = eventlog.InstallAsEventCreate(ws.name, eventlog.Error|eventlog.Warning|eventlog.Info)
	if err != nil {
		s.Delete()
		return fmt.Errorf("InstallAsEventCreate() failed: %s", err)
	}
	return nil
}
예제 #18
0
파일: upgrade.go 프로젝트: calmh/mole
// UpgradeTo upgrades the currently exeuting binary to the specified Build and
// returns an error or nil. The file is downloaded to <destination>.part and
// atomically renamed to the destination after the hash check. The destination
// is taken as the path of the currently executing binary, while following any
// symbolic links to it's destination.
func UpgradeTo(build Build) error {
	path, err := osext.Executable()
	if err != nil {
		return err
	}

	path, err = filepath.EvalSymlinks(path)
	if err != nil {
		return err
	}

	tmp := path + ".part"
	gzUrl := build.URL + ".gz"

	resp, err := http.Get(gzUrl)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	gunzip, err := gzip.NewReader(resp.Body)
	if err != nil {
		return err
	}

	out, err := os.Create(tmp)
	if err != nil {
		return err
	}
	defer os.Remove(tmp)

	err = os.Chmod(tmp, 0755)
	if err != nil {
		return err
	}

	_, err = io.Copy(out, gunzip)
	if err != nil {
		return err
	}

	err = out.Close()
	if err != nil {
		return err
	}

	hash, err := sha1file(tmp)
	if err != nil {
		return err
	}

	if hash != build.Hash {
		return ErrHashMismatch
	}

	ftime := time.Unix(int64(build.BuildStamp), 0)
	_ = os.Chtimes(tmp, ftime, ftime)

	return os.Rename(tmp, path)
}
예제 #19
0
파일: main.go 프로젝트: x5u/goofys
func massageArg0() {
	var err error
	os.Args[0], err = osext.Executable()
	if err != nil {
		panic(fmt.Sprintf("Unable to discover current executable: %v", err))
	}
}
예제 #20
0
파일: info.go 프로젝트: pkgr/scaleway-cli
func runInfo(cmd *types.Command, args []string) {
	if infoHelp {
		cmd.PrintUsage()
	}
	if len(args) != 0 {
		cmd.PrintShortUsage()
	}

	// FIXME: fmt.Printf("Servers: %s\n", "quantity")
	// FIXME: fmt.Printf("Images: %s\n", "quantity")
	fmt.Printf("Debug mode (client): %v\n", os.Getenv("DEBUG") != "")

	fmt.Printf("Organization: %s\n", cmd.API.Organization)
	// FIXME: add partially-masked token
	fmt.Printf("API Endpoint: %s\n", os.Getenv("scaleway_api_endpoint"))
	configPath, _ := utils.GetConfigFilePath()
	fmt.Printf("RC file: %s\n", configPath)
	fmt.Printf("User: %s\n", os.Getenv("USER"))
	fmt.Printf("CPUs: %d\n", runtime.NumCPU())
	hostname, _ := os.Hostname()
	fmt.Printf("Hostname: %s\n", hostname)
	cliPath, _ := osext.Executable()
	fmt.Printf("CLI Path: %s\n", cliPath)

	fmt.Printf("Cache: %s\n", cmd.API.Cache.Path)
	fmt.Printf("  Servers: %d\n", cmd.API.Cache.GetNbServers())
	fmt.Printf("  Images: %d\n", cmd.API.Cache.GetNbImages())
	fmt.Printf("  Snapshots: %d\n", cmd.API.Cache.GetNbSnapshots())
	fmt.Printf("  Volumes: %d\n", cmd.API.Cache.GetNbVolumes())
	fmt.Printf("  Bootscripts: %d\n", cmd.API.Cache.GetNbBootscripts())
}
예제 #21
0
파일: lax.go 프로젝트: enova/tokyo
// ExecPath returns a string containing the full executable path.
func ExecPath() string {
	filename, err := osext.Executable()
	if err != nil {
		return "unknown_exec"
	}
	return filename
}
예제 #22
0
파일: helper.go 프로젝트: worldspawn/vault
func init() {
	var err error
	exePath, err = osext.Executable()
	if err != nil {
		panic("failed to detect self path: " + err.Error())
	}
}
예제 #23
0
func updateHandler(c *gin.Context) {

	path, err := osext.Executable()

	if err != nil {
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}

	var up = &updater.Updater{
		CurrentVersion: version,
		APIURL:         *updateUrl,
		BinURL:         *updateUrl,
		DiffURL:        "",
		Dir:            "update/",
		CmdName:        *appName,
	}

	err = up.BackgroundRun()

	if err != nil {
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}

	c.JSON(200, gin.H{"success": "Please wait a moment while the agent reboots itself"})
	go restart(path)
}
예제 #24
0
func init() {
	var err error
	pluginExePath, err = osext.Executable()
	if err != nil {
		panic(err)
	}
}
예제 #25
0
// NewSchedulerServer creates a new SchedulerServer with default parameters
func NewSchedulerServer() *SchedulerServer {
	s := SchedulerServer{
		Port:                   ports.SchedulerPort,
		Address:                util.IP(net.ParseIP("127.0.0.1")),
		FailoverTimeout:        time.Duration((1 << 62) - 1).Seconds(),
		ExecutorRunProxy:       true,
		ExecutorSuicideTimeout: execcfg.DefaultSuicideTimeout,
		MesosAuthProvider:      sasl.ProviderName,
		MesosMaster:            defaultMesosMaster,
		MesosUser:              defaultMesosUser,
		ReconcileInterval:      defaultReconcileInterval,
		ReconcileCooldown:      defaultReconcileCooldown,
		Checkpoint:             true,
		FrameworkName:          defaultFrameworkName,
		HA:                     false,
		mux:                    http.NewServeMux(),
		KubeletCadvisorPort:    4194, // copied from github.com/GoogleCloudPlatform/kubernetes/blob/release-0.14/cmd/kubelet/app/server.go
		KubeletSyncFrequency:   10 * time.Second,
	}
	// cache this for later use. also useful in case the original binary gets deleted, e.g.
	// during upgrades, development deployments, etc.
	if filename, err := osext.Executable(); err != nil {
		log.Fatalf("failed to determine path to currently running executable: %v", err)
	} else {
		s.executable = filename
		s.KMPath = filename
	}

	return &s
}
예제 #26
0
파일: hopper.go 프로젝트: kamilchm/hopper
// Sets Hopper workspace because it depends on
// run mode - user or project local.
func buildWorkspace() (*workspace, error) {
	var hopsFile, binDir string
	var wsp workspace
	if inLocalMode() {
		log.Debug("Hopper in local mode")
		hopsFile = localHopsFile
		binDir = "./"
	} else {
		log.Debug("Hopper in user mode")
		var err error
		hopsFile, err = homedir.Expand("~/.hopper/hops/hop.yaml")
		if err != nil {
			log.Fatal(err)
		}
		binDir, err = homedir.Expand("~/.hopper/bin")
		if err != nil {
			log.Fatal(err)
		}
	}
	hopperPath, err := osext.Executable()
	if err != nil {
		log.Fatal(err)
	}
	log.Debug("Hopper run from %v", hopperPath)
	wsp = workspace{Hops: nil, BinDir: binDir, HopperPath: hopperPath}
	hs, err := loadHops(hopsFile)
	if err != nil {
		return nil, err
	}
	wsp.Hops = hs
	return &wsp, nil
}
예제 #27
0
func Test_RealReadableFileSystem_ReadFile(t *testing.T) {
	self, _ := osext.Executable()
	fs := Reality()
	bytes, err := fs.ReadFile(self)
	assert.Equal(t, nil, err)
	assert.NotEqual(t, 0, len(bytes))
}
예제 #28
0
func (lsm *LocalServiceManager) call(serviceMethod string, args interface{}, reply interface{}) error {
	lsm.mu.Lock()
	defer lsm.mu.Unlock()

	if lsm.client == nil {
		exe, err := osext.Executable()
		if err != nil {
			return err
		}

		listener, err := net.Listen("tcp", "127.0.0.1:0")
		if err != nil {
			return err
		}
		defer listener.Close()

		runner := exec.Command(exe, "service-runner", "--address", listener.Addr().String(), "--state-file", lsm.stateFile)
		runner.Stdout = os.Stdout
		runner.Stderr = os.Stderr
		go func() {
			runner.Run()
			lsm.mu.Lock()
			lsm.client = nil
			lsm.mu.Unlock()
		}()

		conn, err := listener.Accept()
		if err != nil {
			return err
		}
		lsm.client = rpc.NewClient(conn)
	}

	return lsm.client.Call(serviceMethod, args, reply)
}
예제 #29
0
func (mp *master) checkBinary() error {
	//get path to binary and confirm its writable
	binPath, err := osext.Executable()
	if err != nil {
		return fmt.Errorf("failed to find binary path (%s)", err)
	}
	mp.binPath = binPath
	if info, err := os.Stat(binPath); err != nil {
		return fmt.Errorf("failed to stat binary (%s)", err)
	} else if info.Size() == 0 {
		return fmt.Errorf("binary file is empty")
	} else {
		//copy permissions
		mp.binPerms = info.Mode()
	}
	f, err := os.Open(binPath)
	if err != nil {
		return fmt.Errorf("cannot read binary (%s)", err)
	}
	//initial hash of file
	hash := sha1.New()
	io.Copy(hash, f)
	mp.binHash = hash.Sum(nil)
	f.Close()
	//test bin<->tmpbin moves
	if err := move(tmpBinPath, mp.binPath); err != nil {
		return fmt.Errorf("cannot move binary (%s)", err)
	}
	if err := move(mp.binPath, tmpBinPath); err != nil {
		return fmt.Errorf("cannot move binary back (%s)", err)
	}
	return nil
}
예제 #30
0
// Discover discovers plugins.
//
// This looks in the directory of the executable and the CWD, in that
// order for priority.
func (c *Config) Discover() error {
	// Look in the cwd.
	if err := c.discover("."); err != nil {
		return err
	}

	// Look in the plugins directory. This will override any found
	// in the current directory.
	dir, err := ConfigDir()
	if err != nil {
		log.Printf("[ERR] Error loading config directory: %s", err)
	} else {
		if err := c.discover(filepath.Join(dir, "plugins")); err != nil {
			return err
		}
	}

	// Next, look in the same directory as the executable. Any conflicts
	// will overwrite those found in our current directory.
	exePath, err := osext.Executable()
	if err != nil {
		log.Printf("[ERR] Error loading exe directory: %s", err)
	} else {
		if err := c.discover(filepath.Dir(exePath)); err != nil {
			return err
		}
	}

	return nil
}