/
writers.go
122 lines (102 loc) · 2.98 KB
/
writers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package aws_config_client
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"sync"
"github.com/pkg/errors"
"gopkg.in/ini.v1"
)
type AWSConfigWriter interface {
MergeAWSConfigs(*ini.File, *ini.File) (*ini.File, error)
Write([]byte) (int, error)
}
type AWSConfigFile struct {
awsConfigPath string
buffer *bytes.Buffer
}
func NewAWSConfigFileWriter(awsConfigPath string) *AWSConfigFile {
return &AWSConfigFile{
buffer: bytes.NewBuffer(nil),
awsConfigPath: awsConfigPath,
}
}
func (a *AWSConfigFile) Finalize() error {
tmpfile, err := ioutil.TempFile("", "")
if err != nil {
return errors.Wrap(err, "could not create temporary file for aws config")
}
defer func() {
// if we have an error, attempt cleanup best we can
if err != nil {
tmpfile.Close()
os.Remove(tmpfile.Name())
}
}()
_, err = io.Copy(tmpfile, a.buffer)
if err != nil {
return errors.Wrap(err, "could not write contents to temporary aws config")
}
err = tmpfile.Sync()
if err != nil {
return errors.Wrap(err, "could not Sync temporary aws credentials file")
}
err = tmpfile.Close()
if err != nil {
return errors.Wrap(err, "could not close temporary aws credentials file")
}
err = os.Rename(tmpfile.Name(), a.awsConfigPath)
return errors.Wrapf(err, "could not move aws config to %s", err)
}
func (a *AWSConfigFile) Write(p []byte) (int, error) {
return a.buffer.Write(p)
}
// mergeConfig will merge the new config with the existing aws config
// giving precedence to the new aws config blocks
func (a *AWSConfigFile) MergeAWSConfigs(new *ini.File, old *ini.File) (*ini.File, error) {
return mergeAWSConfigs(new, old)
}
type AWSConfigSTDOUTWriter struct {
preamble sync.Once
}
// stdout writer only returns the new config
// up to users to figure out how to merge
func (a *AWSConfigSTDOUTWriter) MergeAWSConfigs(new *ini.File, old *ini.File) (*ini.File, error) {
return new, nil
}
func (a *AWSConfigSTDOUTWriter) Write(p []byte) (int, error) {
w := os.Stdout
// we only write the preamble once
// a bit Hacky, but ok since just stdout
a.preamble.Do(func() {
fmt.Fprintf(w, "Please add the following to your AWS Config:\n")
})
return w.Write(p)
}
func mergeAWSConfigs(new *ini.File, old *ini.File) (*ini.File, error) {
// first, delete all overlapping sections
for _, section := range new.Sections() {
// skip over the default section
if section.Name() == "DEFAULT" {
continue
}
old.DeleteSection(section.Name())
}
baseBytes := bytes.NewBuffer(nil)
newAWSProfileBytes := bytes.NewBuffer(nil)
_, err := new.WriteTo(newAWSProfileBytes)
if err != nil {
return nil, errors.Wrap(err, "Unable to write AWS Profiles")
}
_, err = old.WriteTo(baseBytes)
if err != nil {
return nil, errors.Wrap(err, "Unable to incorporate original AWS config file with new config changes")
}
mergedConfig, err := ini.Load(baseBytes, newAWSProfileBytes)
if err != nil {
return nil, errors.Wrap(err, "Unable to merge old and new config files")
}
return mergedConfig, nil
}