-
Notifications
You must be signed in to change notification settings - Fork 89
/
main.go
213 lines (179 loc) · 5.55 KB
/
main.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// Nanobox automates the creation of isolated, repeatable environments for local
// and production applications. When developing locally, Nanobox provisions your
// app's infrastructure inside of a virtual machine (VM) and mounts your local
// codebase into the VM. Any changes made to your codebase are reflected inside
// the virtual environment.
//
// Once code is built and tested locally, Nanobox provisions and deploys an
// identical infrastructure on a production platform.
package main
import (
"bufio"
"fmt"
"os"
"path/filepath"
"runtime"
"runtime/debug"
"strings"
"github.com/jcelliott/lumber"
"github.com/nanobox-io/nanobox/commands"
"github.com/nanobox-io/nanobox/models"
"github.com/nanobox-io/nanobox/processors"
proc_provider "github.com/nanobox-io/nanobox/processors/provider"
"github.com/nanobox-io/nanobox/util"
"github.com/nanobox-io/nanobox/util/config"
"github.com/nanobox-io/nanobox/util/display"
"github.com/nanobox-io/nanobox/util/provider"
)
// main
func main() {
// setup a file logger, this will be replaced in verbose mode.
fileLogger, err := lumber.NewTruncateLogger(filepath.ToSlash(filepath.Join(config.GlobalDir(), "nanobox.log")))
if err != nil {
fmt.Println("logging error:", err)
}
//
lumber.SetLogger(fileLogger)
lumber.Level(lumber.INFO)
defer lumber.Close()
// if it is running the server just run it
// skip the tratiotional messaging
if len(os.Args) >= 2 && (os.Args[1] == "server" ||
os.Args[1] == "version" ||
os.Args[1] == "tunnel" ||
os.Args[1] == "console" ||
os.Args[1] == "log" ||
os.Args[1] == "login" ||
os.Args[1] == "logout") {
err := commands.NanoboxCmd.Execute()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
return
}
// verify that we support the prompt they are using
if badTerminal() {
display.BadTerminal()
os.Exit(1)
}
// do the commands configure check here
command := strings.Join(os.Args, " ")
if _, err := models.LoadConfig(); err != nil && !strings.Contains(command, " config") && !strings.Contains(command, "env server") {
err = processors.Configure()
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
}
migrationCheck()
fixRunArgs()
configModel, _ := models.LoadConfig()
// build the viper config because viper cannot handle concurrency
// so it has to be done at the beginning even if we dont need it
providerName := configModel.Provider
// make sure nanobox has all the necessry parts
if !strings.Contains(command, " config") && !strings.Contains(command, " server") {
err, missingParts := provider.Valid()
if err != nil {
fmt.Printf("Failed to validate provider - %s\n", err.Error())
if len(missingParts) > 0 {
display.MissingDependencies(providerName, missingParts)
}
os.Exit(1)
}
}
// global panic handler; this is done to avoid showing any panic output if
// something happens to fail. The output is logged and "pretty" message is
// shown
defer func() {
if r := recover(); r != nil {
// put r into your log ( it contains the panic message)
// Then log debug.Stack (from the runtime/debug package)
stack := debug.Stack()
// in a panic state we dont want to try loading or using any non standard libraries.
// so we will just use the ones we already have
lumber.Fatal(fmt.Sprintf("Cause of failure: %v", r))
lumber.Fatal(fmt.Sprintf("Error output:\n%v\n", string(stack)))
lumber.Close()
fmt.Println("Nanobox encountered an unexpected error. Please see ~/.nanobox/nanobox.log and submit the issue to us.")
os.Exit(1)
}
}()
//
commands.NanoboxCmd.Execute()
}
func badTerminal() bool {
return runtime.GOOS == "windows" && strings.Contains(os.Getenv("shell"), "bash")
}
func fixRunArgs() {
found := false
lastLocation := 0
LOOP:
for i, arg := range os.Args {
switch arg {
case "run":
found = true
lastLocation = i
case "--debug", "--trace", "--verbose", "-t", "-v":
// if we hit a argument of ours after 'found'
// we will reset the last location
if found == true {
lastLocation = i
}
default:
// if we hit this after we have found run
// we are done
if found == true {
break LOOP
}
}
}
if found {
os.Args = append(os.Args[:lastLocation+1], strings.Join(os.Args[lastLocation+1:], " "))
}
}
// check to see if we need to wipe the old
func migrationCheck() {
config, _ := models.LoadConfig()
providerName := config.Provider
providerModel, err := models.LoadProvider()
// if the provider hasnt changed or its a new provider
// no migration required
if util.IsPrivileged() || err != nil || providerModel.Name == providerName {
return
}
// remember the new provider
newProviderName := providerName
// when migrating from the old system
// the provider.Name may be blank
if providerModel.Name == "" {
display.MigrateOldRequired()
providerModel.Name = newProviderName
} else {
display.MigrateProviderRequired()
}
// adjust cached config to be the old provider
config.Provider = providerModel.Name
config.Save()
// alert the user of our actions
fmt.Println("press enter to continue")
reader := bufio.NewReader(os.Stdin)
reader.ReadString('\n')
// implode the old system
processors.Implode()
// on implode success
// adjust the provider to the new one and save the provider model
config.Provider = newProviderName
config.Save()
providerModel.Name = newProviderName
providerModel.Save()
// unset all the docer variables and re init the docker client
os.Unsetenv("DOCKER_TLS_VERIFY")
os.Unsetenv("DOCKER_MACHINE_NAME")
os.Unsetenv("DOCKER_HOST")
os.Unsetenv("DOCKER_CERT_PATH")
if err := proc_provider.Init(); err != nil {
os.Exit(0)
}
}