Example #1
0
// TrackFile will track an individual file, meaning, it will move the original
// file to either the files or backup folder. It will the create a symlink of
// the file in the original location. `name` will be used as the name of the
// folder and key in the config file. `fullPath` has to be the absolute path
// to the file to be tracked.
//
// TrackFile can be called from two contexes:
// 1. From SyncFiles, it will read all the tracked files from the config and
//    make track files if necessary.
// 2. From CommandAdd, this will add a new file for tracking
//
// TrackFile will make a distinction between a new file and a file that is
// already been tracked:
// 1. TrackFile can't find the symlink, but the file is present in the
//    dot_path (the folder that holds all the original files). Then we need to
//    relink it, thus creating a symlink at the correct location. This happens
//    we you run dot on a new 'additional machine'.
// 2. TrackFile can't find the symlink, and the file is also not present in
//    the dot_path folder. This will mean that it is a new file were are going
//    to track. So we copy the file to the files folder, create a symlink, and
//    add an entry to the config file.
func TrackFile(name string, fullPath string, push bool) {

	// Base
	base := path.Base(fullPath)

	// get relative path
	relPath, err := GetRelativePath(fullPath)
	if err != nil {
		PrintBodyError(err.Error())
		return
	}

	// check if path is present
	_, err = os.Stat(fullPath)
	if err != nil {
		message := fmt.Sprintf("not able to find: %s", fullPath)
		PrintBodyError(message)
		return
	}

	// check if path is already symlinked
	s, err := os.Lstat(fullPath)
	if s.Mode()&os.ModeSymlink == os.ModeSymlink {
		message := fmt.Sprintf("%s is already symlinked, skipping ...", name)
		PrintBody(message)
		return
	}

	// load config
	c, err := NewConfig(PathDotConfig)
	if err != nil {
		PrintBodyError("not able to find .dotconfig")
		return
	}

	repoPath := fmt.Sprintf("%s%s/files/%s/", HomeDir(), c.DotPath, name)

	if _, err := os.Stat(repoPath); err == nil {
		// no symlink found, already in repo => additional machine
		message := fmt.Sprintf("Symlinking: %s", name)
		PrintBody(message)

		// put in backup folder, set named folder based on `name`, e.g.:
		// `/home/erroneousboat/dotfiles/backup/[name]/[base]`
		dst := fmt.Sprintf("%s%s/backup/%s/%s", HomeDir(), c.DotPath, name, base)
		err = MakeAndMoveToDir(fullPath, dst)
		if err != nil {
			log.Fatal(err)
		}

		// create symlink (os.Symlink(oldname, newname))
		dst = fmt.Sprintf("%s%s/files/%s/%s", HomeDir(), c.DotPath, name, base)
		err = os.Symlink(dst, fullPath)
		if err != nil {
			log.Fatal(err)
		}

	} else {
		// no symlink found, not in repo => new entry
		message := fmt.Sprintf("Symlinking: %s", name)
		PrintBody(message)

		// put in files folder, set named folder based on `name`, e.g.:
		// `/home/erroneousboat/dotfiles/files/[name]/[base]`
		dst := fmt.Sprintf("%s%s/files/%s/%s", HomeDir(), c.DotPath, name, base)
		err = MakeAndMoveToDir(fullPath, dst)
		if err != nil {
			log.Fatal(err)
		}

		// create symlink (os.Symlink(oldname, newname))
		err = os.Symlink(dst, fullPath)
		if err != nil {
			log.Fatal(err)
		}

		// create entry in .dotconfig file
		c.Files[name] = relPath
		c.Save()

		// push changes to repository
		if push {
			GitCommitPush(name, "add")
		}
	}
}
Example #2
0
func Main() {
	userset := flag.NewFlagSet("fleet", flag.ExitOnError)
	printVersion := userset.Bool("version", false, "Print the version and exit")
	cfgPath := userset.String("config", "", fmt.Sprintf("Path to config file. Fleet will look for a config at %s by default.", DefaultConfigFile))

	userset.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s\nUsage of %s:\n", FleetdDescription, os.Args[0])
		userset.PrintDefaults()
	}

	err := userset.Parse(os.Args[1:])
	if err != nil {
		userset.Usage()
		os.Exit(1)
	}

	args := userset.Args()
	if len(args) > 0 {
		// support `fleetd version` the same as `fleetd --version`
		if args[0] == "version" {
			*printVersion = true
		} else {
			fmt.Fprintf(os.Stderr, "%s takes no arguments. Did you mean to invoke fleetctl instead?\n", os.Args[0])
			userset.Usage()
			os.Exit(1)
		}
	}

	if *printVersion {
		fmt.Println("fleetd version", version.Version)
		os.Exit(0)
	}

	log.Infof("Starting fleetd version %v", version.Version)

	cfgset := flag.NewFlagSet("fleet", flag.ExitOnError)
	cfgset.Int("verbosity", 0, "Logging level")
	cfgset.Var(&pkg.StringSlice{"http://127.0.0.1:2379", "http://127.0.0.1:4001"}, "etcd_servers", "List of etcd endpoints")
	cfgset.String("etcd_username", "", "username for secure etcd communication")
	cfgset.String("etcd_password", "", "password for secure etcd communication")
	cfgset.String("etcd_keyfile", "", "SSL key file used to secure etcd communication")
	cfgset.String("etcd_certfile", "", "SSL certification file used to secure etcd communication")
	cfgset.String("etcd_cafile", "", "SSL Certificate Authority file used to secure etcd communication")
	cfgset.String("etcd_key_prefix", registry.DefaultKeyPrefix, "Keyspace for fleet data in etcd")
	cfgset.Float64("etcd_request_timeout", 1.0, "Amount of time in seconds to allow a single etcd request before considering it failed.")
	cfgset.Float64("engine_reconcile_interval", 2.0, "Interval at which the engine should reconcile the cluster schedule in etcd.")
	cfgset.String("public_ip", "", "IP address that fleet machine should publish")
	cfgset.String("metadata", "", "List of key-value metadata to assign to the fleet machine")
	cfgset.String("agent_ttl", agent.DefaultTTL, "TTL in seconds of fleet machine state in etcd")
	cfgset.String("units_directory", "/run/fleet/units/", "Path to the fleet units directory")
	cfgset.Bool("systemd_user", false, "When true use systemd --user)")
	cfgset.Int("token_limit", 100, "Maximum number of entries per page returned from API requests")
	cfgset.Bool("enable_grpc", false, "When possible, uses grpc to communicate between engine and agent")
	cfgset.Bool("disable_engine", false, "Disable the engine entirely, use with care")
	cfgset.Bool("disable_watches", false, "Disable the use of etcd watches. Increases scheduling latency")
	cfgset.Bool("verify_units", false, "DEPRECATED - This option is ignored")
	cfgset.String("authorized_keys_file", "", "DEPRECATED - This option is ignored")

	globalconf.Register("", cfgset)
	cfg, err := getConfig(cfgset, *cfgPath)
	if err != nil {
		log.Fatal(err)
	}

	log.Debugf("Creating Server")
	srv, err := server.New(*cfg, nil)
	if err != nil {
		log.Fatalf("Failed creating Server: %v", err)
	}
	srv.Run()

	srvMutex := sync.Mutex{}

	reconfigure := func() {
		log.Infof("Reloading configuration from %s", *cfgPath)

		srvMutex.Lock()
		defer srvMutex.Unlock()

		cfg, err := getConfig(cfgset, *cfgPath)
		if err != nil {
			log.Fatal(err)
		}

		log.Infof("Restarting server components")
		srv.SetReconfigServer(true)

		// Get Server.listeners[] to keep it for a new server,
		// before killing the old server.
		oldListeners := srv.GetApiServerListeners()

		srv.Kill()

		// The new server takes the original listeners.
		srv, err = server.New(*cfg, oldListeners)
		if err != nil {
			log.Fatal(err)
		}

		srv.Run()
		srv.SetReconfigServer(false)
	}

	shutdown := func() {
		log.Infof("Gracefully shutting down")

		srvMutex.Lock()
		defer srvMutex.Unlock()

		srv.Kill()
		srv.Purge()
		os.Exit(0)
	}

	writeState := func() {
		log.Infof("Dumping server state")

		srvMutex.Lock()
		defer srvMutex.Unlock()

		encoded, err := json.Marshal(srv)
		if err != nil {
			log.Errorf("Failed to dump server state: %v", err)
			return
		}

		if _, err := os.Stdout.Write(encoded); err != nil {
			log.Errorf("Failed to dump server state: %v", err)
			return
		}

		os.Stdout.Write([]byte("\n"))

		log.Debugf("Finished dumping server state")
	}

	signals := map[os.Signal]func(){
		syscall.SIGHUP:  reconfigure,
		syscall.SIGTERM: shutdown,
		syscall.SIGINT:  shutdown,
		syscall.SIGUSR1: writeState,
	}

	listenForSignals(signals)
}
Example #3
0
// UntrackFile will remove a file from tracking. `name` will be the key
// in the config file that points to the initial location of the file
func UntrackFile(name string, push bool) {
	// open config file
	c, err := NewConfig(HomeDir() + "/" + ConfigFileName)
	if err != nil {
		PrintBodyError("not able to find .dotconfig")
		return
	}

	// check if `name` is present in c.Files
	path := c.Files[name]
	if path == "" {
		message := fmt.Sprintf("'%s' is not being tracked. Get the list of "+
			"tracked files with `dot list`", name)
		PrintBodyError(message)
		return
	}

	// check if path (the symlink) is present
	pathSymlink := fmt.Sprintf("%s%s", HomeDir(), path)
	f, err := os.Lstat(pathSymlink)
	if err != nil {
		message := fmt.Sprintf("not able to find: %s", path)
		PrintBodyError(message)
		return
	}

	// check if path is symlink
	if f.Mode()&os.ModeSymlink != os.ModeSymlink {
		message := fmt.Sprintf("%s is not a symlink", path)
		PrintBodyError(message)
		return
	}

	// check if src is present
	src := fmt.Sprintf("%s%s/files/%s", HomeDir(), c.DotPath, name)
	if _, err = os.Stat(src); err != nil {
		message := fmt.Sprintf("not able to find %s", src)
		PrintBodyError(message)
		return
	}

	// remove symlink
	err = os.Remove(pathSymlink)
	if err != nil {
		message := fmt.Sprintf("not able to remove %s", pathSymlink)
		PrintBodyError(message)
		return
	}

	// move the file or directory
	dst := fmt.Sprintf("%s%s", HomeDir(), path)

	message := fmt.Sprintf("Moving %s back to %s", name, dst)
	PrintBody(message)

	err = MakeAndMoveToDir(src, dst)
	if err != nil {
		log.Fatal(err)
	}

	// remove entry from config and save config
	delete(c.Files, name)
	c.Save()

	// push changes to repository
	if push {
		GitCommitPush(name, "rm")
	}
}