github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/environs/configstore/mem.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package configstore 5 6 import ( 7 "fmt" 8 "sync" 9 10 "github.com/juju/errors" 11 ) 12 13 type memStore struct { 14 mu sync.Mutex 15 envs map[string]*memInfo 16 } 17 18 type memInfo struct { 19 store *memStore 20 name string 21 environInfo 22 } 23 24 // clone returns a copy of the given environment info, isolated 25 // from the store itself. 26 func (info *memInfo) clone() *memInfo { 27 // Note that none of the Set* methods ever set fields inside 28 // references, which makes this OK to do. 29 info1 := *info 30 newAttrs := make(map[string]interface{}) 31 for name, attr := range info.bootstrapConfig { 32 newAttrs[name] = attr 33 } 34 info1.bootstrapConfig = newAttrs 35 info1.source = sourceMem 36 return &info1 37 } 38 39 // NewMem returns a ConfigStorage implementation that 40 // stores configuration in memory. 41 func NewMem() Storage { 42 return &memStore{ 43 envs: make(map[string]*memInfo), 44 } 45 } 46 47 // CreateInfo implements Storage.CreateInfo. 48 func (m *memStore) CreateInfo(envName string) EnvironInfo { 49 m.mu.Lock() 50 defer m.mu.Unlock() 51 info := &memInfo{ 52 store: m, 53 name: envName, 54 } 55 info.source = sourceCreated 56 return info 57 } 58 59 // List implements Storage.List 60 func (m *memStore) List() ([]string, error) { 61 var envs []string 62 m.mu.Lock() 63 defer m.mu.Unlock() 64 for name, env := range m.envs { 65 api := env.APIEndpoint() 66 if api.ServerUUID == "" || api.EnvironUUID != "" { 67 envs = append(envs, name) 68 } 69 } 70 return envs, nil 71 } 72 73 // ListSystems implements Storage.ListSystems 74 func (m *memStore) ListSystems() ([]string, error) { 75 var servers []string 76 m.mu.Lock() 77 defer m.mu.Unlock() 78 for name, env := range m.envs { 79 api := env.APIEndpoint() 80 if api.ServerUUID == "" || 81 api.ServerUUID == api.EnvironUUID || 82 api.EnvironUUID == "" { 83 servers = append(servers, name) 84 } 85 } 86 return servers, nil 87 } 88 89 // ReadInfo implements Storage.ReadInfo. 90 func (m *memStore) ReadInfo(envName string) (EnvironInfo, error) { 91 m.mu.Lock() 92 defer m.mu.Unlock() 93 info := m.envs[envName] 94 if info != nil { 95 return info.clone(), nil 96 } 97 return nil, errors.NotFoundf("environment %q", envName) 98 } 99 100 // Location implements EnvironInfo.Location. 101 func (info *memInfo) Location() string { 102 return "memory" 103 } 104 105 // Write implements EnvironInfo.Write. 106 func (info *memInfo) Write() error { 107 m := info.store 108 m.mu.Lock() 109 defer m.mu.Unlock() 110 111 if !info.initialized() && m.envs[info.name] != nil { 112 return ErrEnvironInfoAlreadyExists 113 } 114 115 info.source = sourceMem 116 m.envs[info.name] = info.clone() 117 return nil 118 } 119 120 // Destroy implements EnvironInfo.Destroy. 121 func (info *memInfo) Destroy() error { 122 m := info.store 123 m.mu.Lock() 124 defer m.mu.Unlock() 125 if info.initialized() { 126 if m.envs[info.name] == nil { 127 return fmt.Errorf("environment info has already been removed") 128 } 129 delete(m.envs, info.name) 130 } 131 return nil 132 }