1package releasedir
2
3import (
4	bosherr "github.com/cloudfoundry/bosh-utils/errors"
5	boshsys "github.com/cloudfoundry/bosh-utils/system"
6	"gopkg.in/yaml.v2"
7)
8
9/*
10# final.yml
11---
12name: cf
13blobstore:
14  provider: s3
15  options:
16    bucket_name: cf-release-blobs
17
18# private.yml
19---
20blobstore:
21  options: { ... }
22*/
23
24type FSConfig struct {
25	publicPath  string
26	privatePath string
27	fs          boshsys.FileSystem
28}
29
30type fsConfigPublicSchema struct {
31	Name      string                   `yaml:"name"`
32	FinalName string                   `yaml:"final_name,omitempty"`
33	Blobstore fsConfigSchema_Blobstore `yaml:"blobstore,omitempty"`
34}
35
36type fsConfigPrivateSchema struct {
37	Blobstore fsConfigSchema_Blobstore `yaml:"blobstore"`
38}
39
40type fsConfigSchema_Blobstore struct {
41	Provider string                 `yaml:"provider"`
42	Options  map[string]interface{} `yaml:"options,omitempty"`
43}
44
45func NewFSConfig(publicPath, privatePath string, fs boshsys.FileSystem) FSConfig {
46	return FSConfig{publicPath: publicPath, privatePath: privatePath, fs: fs}
47}
48
49func (c FSConfig) Name() (string, error) {
50	publicSchema, _, err := c.read()
51	if err != nil {
52		return "", err
53	}
54
55	if len(publicSchema.Name) == 0 {
56		if len(publicSchema.FinalName) == 0 {
57			return "", bosherr.Errorf(
58				"Expected non-empty 'name' in config '%s'", c.publicPath)
59		}
60
61		return publicSchema.FinalName, nil
62	} else if len(publicSchema.FinalName) > 0 {
63		return "", bosherr.Errorf(
64			"Expected 'name' or 'final_name' but not both in config '%s'", c.publicPath)
65	}
66
67	return publicSchema.Name, nil
68}
69
70func (c FSConfig) SaveName(name string) error {
71	publicSchema, _, err := c.read()
72	if err != nil {
73		return err
74	}
75
76	publicSchema.FinalName = ""
77	publicSchema.Name = name
78
79	bytes, err := yaml.Marshal(publicSchema)
80	if err != nil {
81		return bosherr.WrapError(err, "Marshalling config")
82	}
83
84	err = c.fs.WriteFile(c.publicPath, bytes)
85	if err != nil {
86		return bosherr.WrapErrorf(err, "Writing config '%s'", c.publicPath)
87	}
88
89	return nil
90}
91
92func (c FSConfig) Blobstore() (string, map[string]interface{}, error) {
93	publicSchema, privateSchema, err := c.read()
94	if err != nil {
95		return "", nil, err
96	}
97
98	if len(publicSchema.Blobstore.Provider) == 0 {
99		return "", nil, bosherr.Errorf(
100			"Expected non-empty 'blobstore.provider' in config '%s'", c.publicPath)
101	}
102
103	opts := map[string]interface{}{}
104
105	for k, v := range publicSchema.Blobstore.Options {
106		opts[k] = v
107	}
108
109	for k, v := range privateSchema.Blobstore.Options {
110		opts[k] = v
111	}
112
113	return publicSchema.Blobstore.Provider, opts, nil
114}
115
116func (c FSConfig) read() (fsConfigPublicSchema, fsConfigPrivateSchema, error) {
117	var publicSchema fsConfigPublicSchema
118	var privateSchema fsConfigPrivateSchema
119
120	if c.fs.FileExists(c.publicPath) {
121		bytes, err := c.fs.ReadFile(c.publicPath)
122		if err != nil {
123			return publicSchema, privateSchema,
124				bosherr.WrapErrorf(err, "Reading config '%s'", c.publicPath)
125		}
126
127		err = yaml.Unmarshal(bytes, &publicSchema)
128		if err != nil {
129			return publicSchema, privateSchema,
130				bosherr.WrapErrorf(err, "Unmarshalling config '%s'", c.publicPath)
131		}
132	}
133
134	if c.fs.FileExists(c.privatePath) {
135		bytes, err := c.fs.ReadFile(c.privatePath)
136		if err != nil {
137			return publicSchema, privateSchema,
138				bosherr.WrapErrorf(err, "Reading config '%s'", c.privatePath)
139		}
140
141		err = yaml.Unmarshal(bytes, &privateSchema)
142		if err != nil {
143			return publicSchema, privateSchema,
144				bosherr.WrapErrorf(err, "Unmarshalling config '%s'", c.privatePath)
145		}
146	}
147
148	return publicSchema, privateSchema, nil
149}
150