package libmachine import ( "encoding/json" "io/ioutil" "os" "path/filepath" "strings" log "github.com/Sirupsen/logrus" "github.com/docker/machine/utils" ) type Filestore struct { path string caCertPath string privateKeyPath string } func NewFilestore(rootPath string, caCert string, privateKey string) *Filestore { return &Filestore{path: rootPath, caCertPath: caCert, privateKeyPath: privateKey} } func (s Filestore) loadHost(name string) (*Host, error) { hostPath := filepath.Join(utils.GetMachineDir(), name) if _, err := os.Stat(hostPath); os.IsNotExist(err) { return nil, ErrHostDoesNotExist } host := &Host{Name: name, StorePath: hostPath} if err := host.LoadConfig(); err != nil { return nil, err } h := FillNestedHost(host) return h, nil } func (s Filestore) GetPath() string { return s.path } func (s Filestore) GetCACertificatePath() (string, error) { return s.caCertPath, nil } func (s Filestore) GetPrivateKeyPath() (string, error) { return s.privateKeyPath, nil } func (s Filestore) Save(host *Host) error { data, err := json.Marshal(host) if err != nil { return err } hostPath := filepath.Join(utils.GetMachineDir(), host.Name) if err := os.MkdirAll(hostPath, 0700); err != nil { return err } if err := ioutil.WriteFile(filepath.Join(hostPath, "config.json"), data, 0600); err != nil { return err } return nil } func (s Filestore) Remove(name string, force bool) error { hostPath := filepath.Join(utils.GetMachineDir(), name) return os.RemoveAll(hostPath) } func (s Filestore) List() ([]*Host, error) { dir, err := ioutil.ReadDir(utils.GetMachineDir()) if err != nil && !os.IsNotExist(err) { return nil, err } hosts := []*Host{} for _, file := range dir { // don't load hidden dirs; used for configs if file.IsDir() && strings.Index(file.Name(), ".") != 0 { host, err := s.Get(file.Name()) if err != nil { log.Errorf("error loading host %q: %s", file.Name(), err) continue } hosts = append(hosts, host) } } return hosts, nil } func (s Filestore) Exists(name string) (bool, error) { _, err := os.Stat(filepath.Join(utils.GetMachineDir(), name)) if os.IsNotExist(err) { return false, nil } else if err == nil { return true, nil } return false, err } func (s Filestore) Get(name string) (*Host, error) { return s.loadHost(name) } func (s Filestore) GetActive() (*Host, error) { hostName, err := ioutil.ReadFile(s.activePath()) if os.IsNotExist(err) { return nil, nil } else if err != nil { return nil, err } return s.Get(string(hostName)) } func (s Filestore) IsActive(host *Host) (bool, error) { active, err := s.GetActive() if err != nil { return false, err } if active == nil { return false, nil } return active.Name == host.Name, nil } func (s Filestore) SetActive(host *Host) error { if err := os.MkdirAll(filepath.Dir(s.activePath()), 0700); err != nil { return err } return ioutil.WriteFile(s.activePath(), []byte(host.Name), 0600) } func (s Filestore) RemoveActive() error { return os.Remove(s.activePath()) } // activePath returns the path to the file that stores the name of the // active host func (s Filestore) activePath() string { return filepath.Join(utils.GetMachineDir(), ".active") }