forked from Azure/draft-classic
/
create.go
137 lines (120 loc) · 3.69 KB
/
create.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package main
import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"github.com/BurntSushi/toml"
log "github.com/Sirupsen/logrus"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/proto/hapi/chart"
"github.com/Azure/draft/pkg/draft/draftpath"
"github.com/Azure/draft/pkg/draft/manifest"
"github.com/Azure/draft/pkg/draft/pack"
"github.com/Azure/draft/pkg/osutil"
)
const (
createDesc = `This command transforms the local directory to be deployable via 'draft up'.
`
)
type createCmd struct {
appName string
out io.Writer
pack string
home draftpath.Home
}
func newCreateCmd(out io.Writer) *cobra.Command {
cc := &createCmd{
out: out,
}
cmd := &cobra.Command{
Use: "create",
Short: "transform the local directory to be deployable to Kubernetes",
Long: createDesc,
RunE: func(cmd *cobra.Command, args []string) error {
return cc.run()
},
}
cc.home = draftpath.Home(homePath())
f := cmd.Flags()
f.StringVarP(&cc.appName, "app", "a", "", "name of the Helm release. By default this is the basename of the current working directory")
f.StringVarP(&cc.pack, "pack", "p", "", "the named Draft starter pack to scaffold the app with")
return cmd
}
func (c *createCmd) run() error {
var err error
mfest := manifest.New()
cfile := &chart.Metadata{
Name: mfest.Environments[manifest.DefaultEnvironmentName].Name,
Description: "A Helm chart for Kubernetes",
Version: "0.1.0",
ApiVersion: chartutil.ApiVersionV1,
}
chartExists, err := osutil.Exists("chart")
if err != nil {
return fmt.Errorf("there was an error checking if a chart exists: %v", err)
}
if chartExists {
// chart dir already exists, so we just tell the user that we are happily skipping the
// process.
fmt.Fprintln(c.out, "--> chart/ already exists. Ready to sail!")
return nil
}
if c.pack != "" {
// --pack was explicitly defined, so we can just lazily use that here. No detection required.
lpack := filepath.Join(c.home.Packs(), c.pack)
err = pack.CreateFrom(cfile, "", lpack)
if err != nil {
return err
}
} else {
// pack detection time
packPath, output, err := doPackDetection(c.home.Packs(), c.out)
log.Debugf("doPackDetection result: %s, %s, %v", packPath, output, err)
if err != nil {
return err
}
fmt.Fprintf(c.out, "--> %s app detected\n", output)
err = pack.CreateFrom(cfile, "", packPath)
if err != nil {
return err
}
}
draftToml, err := os.OpenFile("draft.toml", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
return err
}
defer draftToml.Close()
if err := toml.NewEncoder(draftToml).Encode(mfest); err != nil {
return fmt.Errorf("could not write metadata to draft.toml: %v", err)
}
fmt.Fprintln(c.out, "--> Ready to sail")
return nil
}
// doPackDetection performs pack detection across all the packs available in $(draft home)/packs in
// alphabetical order, returning the pack dirpath, the "formal name" returned from the detect
// script's output and any errors that occurred during the pack detection.
func doPackDetection(packHomeDir string, out io.Writer) (string, string, error) {
files, err := ioutil.ReadDir(packHomeDir)
if err != nil {
return "", "", fmt.Errorf("there was an error reading %s: %v", packHomeDir, err)
}
for _, file := range files {
if file.IsDir() {
packPath := filepath.Join(packHomeDir, file.Name())
log.Debugf("pack path: %s", packPath)
p, err := pack.FromDir(packPath)
if err != nil {
return "", "", fmt.Errorf("could not load pack %s: %v", packPath, err)
}
output, err := p.Detect("")
log.Debugf("pack.Detect() result: %s, %v", output, err)
if err == nil {
return packPath, output, err
}
}
}
return "", "", fmt.Errorf("Unable to select a starter pack Q_Q")
}