func (r *syncCommand) applyBackends(backends []*api.Backend) error {
	log.Infof("%s", color.GreenString("-> synchronizing the backends, backend: %d", len(backends)))
	var list []string
	for _, backend := range backends {
		if err := backend.IsValid(); err != nil {
			return err
		}
		list = append(list, backend.GetPath())
		path := backend.GetPath()
		mounted, err := r.client.Mounts()
		if err != nil {
			return err
		}
		_, found := mounted[backend.GetPath()+"/"]
		if !found {
			log.Infof("[backend: %s] creating backend", path)
			if err := r.client.Client().Sys().Mount(path, &v.MountInput{
				Type:        backend.Type,
				Description: backend.Description,
				Config: v.MountConfigInput{
					DefaultLeaseTTL: backend.DefaultLeaseTTL.String(),
					MaxLeaseTTL:     backend.MaxLeaseTTL.String(),
				},
			}); err != nil {
				return err
			}
		} else {
			log.Infof("[backend: %s]: already exist, moving to configuration", path)
		}
		for _, c := range backend.Attrs {
			uri := c.GetPath(path)
			if found && c.IsOneshot() {
				log.Infof("[backend:%s] skipping the config, as it's a oneshot setting", uri)
				continue
			}
			log.Infof("[backend->config: %s] applying configuration for backend", uri)
			resp, err := r.client.Request("PUT", uri, &c)
			if err != nil {
				return err
			}
			if resp.StatusCode != http.StatusNoContent {
				return err
			}
		}
	}
	if r.fullsync {
		mounted, err := r.client.Client().Sys().ListMounts()
		if err != nil {
			return err
		}
		for name, _ := range mounted {
			if utils.ContainedIn(name, []string{"secret/", "cubbyhole/", "sys/"}) {
				continue
			}
			if !utils.ContainedIn(strings.TrimSuffix(name, "/"), list) {
				log.Warnf("[backend: %s] no longer referenced, delete: %t", name, r.delete)
				if !r.delete {
					continue
				}
				if err := r.client.Client().Sys().Unmount(name); err != nil {
					return fmt.Errorf("failed to unmount the backend: %s, error: %s", name, err)
				}
			}
		}
	}
	return nil
}
syncBackends synchronizes the backend's with vault
package cmd
import (
	"fmt"
	"io/ioutil"
	"net/http"
	"path/filepath"
	"strings"
	"time"
	"github.com/cloudwatt/vault-sync/pkg/api"
	"github.com/cloudwatt/vault-sync/pkg/utils"
	"github.com/cloudwatt/vault-sync/pkg/vault"
	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/fatih/color"
	v "github.com/hashicorp/vault/api"
)
type syncCommand struct {
	auths []*api.Auth
	users []*api.User
	backends []*api.Backend
	secrets []*api.Secret
	policyFiles []string
	configFiles []string
	fullsync bool
	client *vault.Client
	skipAuths bool
	skipUsers bool
	skipBackends bool
	skipPolicies bool
	skipSecrets bool
	delete bool
	policyExtension string
	configExtension string
}
func newSyncCommand() cli.Command {
	return new(syncCommand).getCommand()
}
func (r *syncCommand) action(cx *cli.Context) error {
	startTime := time.Now()
	if err := r.validateAction(cx); err != nil {
		return err
	}
	client, err := getVaultClient(cx)
	if err != nil {
		return err
	}
	r.client = client
	if err := r.parseConfigFiles(); err != nil {
		return err
	}
	if err := r.synchronize(); err != nil {
		return err
	}
	log.Infof("synchronization complete, time took: %s", time.Now().Sub(startTime).String())
	return nil
}
func (r *syncCommand) synchronize() error {
	if !r.skipAuths {
		if err := r.applyAuths(r.auths); err != nil {
			return err
		}
	}
	if !r.skipPolicies {
		if err := r.applyPolicies(r.policyFiles); err != nil {
			return err
		}
	}
	if !r.skipUsers {
		if err := r.applyUsers(r.users); err != nil {
			return err
		}
	}
	if !r.skipBackends {
		if err := r.applyBackends(r.backends); err != nil {
			return err
		}
	}
	if !r.skipSecrets {
		if err := r.applySecrets(r.secrets); err != nil {
			return err
		}
	}
	return nil
}
func (r *syncCommand) applyAuths(auths []*api.Auth) error {
	log.Infof("%s", color.GreenString("-> synchronizing the auth backends, %d backends", len(auths)))
	var list []string
	for _, x := range auths {
		if err := x.IsValid(); err != nil {
			return err
		}
		list = append(list, x.Path)
		mounted, err := r.client.Client().Sys().ListAuth()
		if err != nil {
			return err
		}
		if _, found := mounted[x.Path+"/"]; !found {
			log.Infof("[auth: %s] type: %s is not mounted, attempting to mount now", x.Path, x.Type)
			if err := r.client.Client().Sys().EnableAuth(x.Path, x.Type, x.Description); err != nil {
				return err
			}
		} else {
			log.Infof("[auth: %s] already create, skipping to configuration", x.Path)
		}
		r.client.Client().Sys().TuneMount(fmt.Sprintf("auth/%s/tune", x.Path), v.MountConfigInput{
			DefaultLeaseTTL: x.GetDefaultTTL(),
			MaxLeaseTTL:     x.GetMaxTTL(),
		})
		for _, c := range x.Attrs {
			uri := fmt.Sprintf("/auth/%s", c.GetPath(x.Path))
			if err := c.IsValid(); err != nil {
				return fmt.Errorf("the attribute for auth backend: %s invalid, error: %s", x.Path, err)
			}
			log.Infof("[auth->config: %s] applying configuration to auth", uri)
			resp, err := r.client.Request("PUT", uri, &c)
			if err != nil {
				return err
			}
			if resp.StatusCode != http.StatusNoContent {
				return err
			}
		}
	}
	if r.fullsync {
		mounted, err := r.client.Client().Sys().ListAuth()
		if err != nil {
			return err
		}
		for name, _ := range mounted {
			if utils.ContainedIn(name, []string{"token/"}) {
				continue
			}
			if !utils.ContainedIn(strings.TrimSuffix(name, "/"), list) {
				log.Warnf("[auth: %s] is no longer referenced, delete: %t", name, r.delete)
				if !r.delete {
					continue
				}
				if err := r.client.Client().Sys().DisableAuth(name); err != nil {
					return fmt.Errorf("failed to disable the auth: %s, error: %s", name, err)
				}
			}
		}
	}
	return nil
}
func (r *syncCommand) applyPolicies(policies []string) error {
	log.Infof("%s", color.GreenString("-> synchronizing the vault policies, %d files", len(policies)))
	var list []string
	for _, p := range policies {
		name := strings.TrimSuffix(filepath.Base(p), filepath.Ext(filepath.Base(p)))
		list = append(list, name)
		content, err := ioutil.ReadFile(p)
		if err != nil {
			return err
		}
		if err := r.client.SetPolicy(name, string(content)); err != nil {
			return err
		}
		log.Infof("[policy: %s] successfully applied the policy, filename: %s", name, p)
	}
	if r.fullsync {
		p, err := r.client.Client().Sys().ListPolicies()
		if err != nil {
			return err
		}
		for _, x := range p {
			if utils.ContainedIn(x, []string{"default", "root"}) {
				continue
			}
			if !utils.ContainedIn(x, list) {
				log.Warningf("[policy: %s] no longer referenced in config, delete: %t", x, r.delete)
				if !r.delete {
					continue
				}
				if err := r.client.Client().Sys().DeletePolicy(x); err != nil {
					return err
				}
			}
		}
	}
	return nil
}
func (r *syncCommand) applyUsers(users []*api.User) error {
	log.Infof("%s", color.GreenString("-> synchronizing the vault users, users: %d", len(users)))
	for _, x := range users {
		if err := x.IsValid(); err != nil {
			return err
		}
		path := x.Path
		if path == "" {
			path = "default"
		}
		log.Infof("[user: %s/%s] ensuring user, policies: %s", path, x.Username(), x.GetPolicies())
		if err := r.client.AddUser(x); err != nil {
			return err
		}
	}
	return nil
}