Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(44)

Delta Between Two Patch Sets: environs/configstore/disk.go

Issue 13969043: environs/configstore: change file extension
Left Patch Set: Created 11 years, 6 months ago
Right Patch Set: environs/configstore: change file extension Created 11 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « [revision details] ('k') | environs/configstore/disk_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 "io/ioutil"
9 "os"
10 "path/filepath"
11
12 "launchpad.net/goyaml"
13
14 "launchpad.net/juju-core/environs/config"
15 "launchpad.net/juju-core/errors"
16 )
17
18 // Default returns disk-based environment config storage
19 // rooted at JujuHome.
20 func Default() (Storage, error) {
21 return NewDisk(config.JujuHome())
22 }
23
24 type diskStore struct {
25 dir string
26 }
27
28 type environInfo struct {
29 path string
30 // initialized signifies whether the info has been written.
31 initialized bool
32
33 // created signifies whether the info was returned from
34 // a CreateInfo call.
35 created bool
36 User string
37 Password string
38 StateServers []string `yaml:"state-servers"`
39 CACert string `yaml:"ca-cert"`
40 Config map[string]interface{} `yaml:"bootstrap-config,omitempty"`
41 }
42
43 // NewDisk returns a ConfigStorage implementation that stores
44 // configuration in the given directory. The parent of the directory
45 // must already exist; the directory itself is created on demand.
46 func NewDisk(dir string) (Storage, error) {
47 if _, err := os.Stat(dir); err != nil {
48 return nil, err
49 }
50 return &diskStore{dir}, nil
1 } 51 }
2 52
3 func (d *diskStore) envPath(envName string) string { 53 func (d *diskStore) envPath(envName string) string {
4 » return filepath.Join(d.dir, "environments", envName+".yaml") 54 » return filepath.Join(d.dir, "environments", envName+".jenv")
mue 2013/09/26 13:52:51 Good choice. I prefer names/extensions telling wha
5 } 55 }
6 56
7 func (d *diskStore) mkEnvironmentsDir() error { 57 func (d *diskStore) mkEnvironmentsDir() error {
58 err := os.Mkdir(filepath.Join(d.dir, "environments"), 0700)
59 if err == nil || os.IsExist(err) {
60 return nil
61 }
62 return err
63 }
64
65 // CreateInfo implements Storage.CreateInfo.
66 func (d *diskStore) CreateInfo(envName string) (EnvironInfo, error) {
67 if err := d.mkEnvironmentsDir(); err != nil {
68 return nil, err
69 }
70 // We create an empty file so that any subsequent CreateInfos
71 // will fail.
72 path := d.envPath(envName)
73 file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
74 if os.IsExist(err) {
75 return nil, ErrEnvironInfoAlreadyExists
76 }
77 if err != nil {
78 return nil, err
79 }
80 file.Close()
81 return &environInfo{
82 created: true,
83 path: path,
84 }, nil
85 }
86
87 // ReadInfo implements Storage.ReadInfo.
88 func (d *diskStore) ReadInfo(envName string) (EnvironInfo, error) {
89 path := d.envPath(envName)
90 data, err := ioutil.ReadFile(path)
91 if err != nil {
92 if os.IsNotExist(err) {
93 return nil, errors.NotFoundf("environment %q", envName)
94 }
95 return nil, err
96 }
97 var info environInfo
98 info.path = path
99 if len(data) == 0 {
100 return &info, nil
101 }
102 if err := goyaml.Unmarshal(data, &info); err != nil {
103 return nil, fmt.Errorf("error unmarshalling %q: %v", path, err)
104 }
105 info.initialized = true
106 return &info, nil
107 }
108
109 // Initialized implements EnvironInfo.Initialized.
110 func (info *environInfo) Initialized() bool {
111 return info.initialized
112 }
113
114 // BootstrapConfig implements EnvironInfo.BootstrapConfig.
115 func (info *environInfo) BootstrapConfig() map[string]interface{} {
116 return info.Config
117 }
118
119 // APICredentials implements EnvironInfo.APICredentials.
120 func (info *environInfo) APICredentials() APICredentials {
121 return APICredentials{
122 User: info.User,
123 Password: info.Password,
124 }
125 }
126
127 // APIEndpoint implements EnvironInfo.APIEndpoint.
128 func (info *environInfo) APIEndpoint() APIEndpoint {
129 return APIEndpoint{
130 Addresses: info.StateServers,
131 CACert: info.CACert,
132 }
133 }
134
135 // SetExtraConfig implements EnvironInfo.SetBootstrapConfig.
136 func (info *environInfo) SetBootstrapConfig(attrs map[string]interface{}) {
137 if !info.created {
138 panic("bootstrap config set on environment info that has not jus t been created")
139 }
140 info.Config = attrs
141 }
142
143 // SetAPIEndpoint implements EnvironInfo.SetAPIEndpoint.
144 func (info *environInfo) SetAPIEndpoint(endpoint APIEndpoint) {
145 info.StateServers = endpoint.Addresses
146 info.CACert = endpoint.CACert
147 }
148
149 // SetAPICredentials implements EnvironInfo.SetAPICredentials.
150 func (info *environInfo) SetAPICredentials(creds APICredentials) {
151 info.User = creds.User
152 info.Password = creds.Password
153 }
154
155 // Write implements EnvironInfo.Write.
156 func (info *environInfo) Write() error {
157 data, err := goyaml.Marshal(info)
158 if err != nil {
159 return fmt.Errorf("cannot marshal environment info: %v", err)
160 }
161 // Create a temporary file and rename it, so that the data
162 // changes atomically.
163 parent, _ := filepath.Split(info.path)
164 tmpFile, err := ioutil.TempFile(parent, "")
165 if err != nil {
166 return fmt.Errorf("cannot create temporary file: %v", err)
167 }
168 defer tmpFile.Close()
169 _, err = tmpFile.Write(data)
170 if err != nil {
171 return fmt.Errorf("cannot write temporary file: %v", err)
172 }
173 if err := os.Rename(tmpFile.Name(), info.path); err != nil {
174 os.Remove(tmpFile.Name())
175 return fmt.Errorf("cannot rename new environment info file: %v", err)
176 }
177 info.initialized = true
178 return nil
179 }
180
181 // Destroy implements EnvironInfo.Destroy.
182 func (info *environInfo) Destroy() error {
183 err := os.Remove(info.path)
184 if os.IsNotExist(err) {
185 return fmt.Errorf("environment info has already been removed")
186 }
187 return err
188 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b