Skip to content

Commit 5052b79

Browse files
committed
Copy over everything from pvc
1 parent 715637f commit 5052b79

File tree

6 files changed

+767
-0
lines changed

6 files changed

+767
-0
lines changed

Godeps/.gitignore

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Godeps/Godeps.json

+59
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Godeps/Readme

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

env.go

+285
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"bytes"
6+
"encoding/json"
7+
"fmt"
8+
"io"
9+
"io/ioutil"
10+
"log"
11+
"net"
12+
"net/http"
13+
"os"
14+
"runtime"
15+
"strconv"
16+
"time"
17+
18+
"github.com/pipeviz/pvc/Godeps/_workspace/src/github.com/pipeviz/pipeviz/schema"
19+
"github.com/pipeviz/pvc/Godeps/_workspace/src/github.com/pipeviz/pipeviz/types/semantic"
20+
"github.com/pipeviz/pvc/Godeps/_workspace/src/github.com/spf13/cobra"
21+
gjs "github.com/pipeviz/pvc/Godeps/_workspace/src/github.com/xeipuuv/gojsonschema"
22+
)
23+
24+
var schemaMaster *gjs.Schema
25+
26+
// TODO we just use this as a way to namespace common names
27+
type envCmd struct{}
28+
29+
func envCommand() *cobra.Command {
30+
ec := envCmd{}
31+
cmd := &cobra.Command{
32+
Use: "env [-n|--no-detect]",
33+
Short: "Generates a pipeviz message describing an environment.",
34+
Long: "Generates a valid message describing an environment from user input, then sends the message to a target pipeviz server.",
35+
Run: ec.runGenEnv,
36+
}
37+
38+
var nodetect bool
39+
cmd.Flags().BoolVarP(&nodetect, "no-detect", "n", false, "Skip automated detection of suggested values.")
40+
41+
return cmd
42+
}
43+
44+
// runGenEnv is the main entry point for running the environment-generating
45+
// env subcommand.
46+
func (ec envCmd) runGenEnv(cmd *cobra.Command, args []string) {
47+
e := &semantic.Environment{}
48+
49+
if !cmd.Flags().Lookup("no-detect").Changed {
50+
*e = detectEnvDefaults()
51+
}
52+
53+
// Write directly to stdout, at least for now
54+
w := os.Stdout
55+
56+
// Prep schema to validate the messages as we go
57+
raw, err := schema.Master()
58+
if err != nil {
59+
fmt.Fprintln(w, "WARNING: Failed to open master schema file; pvc cannot validate outgoing messages.")
60+
}
61+
62+
schemaMaster, err = gjs.NewSchema(gjs.NewStringLoader(string(raw)))
63+
if err != nil {
64+
panic("bad schema...?")
65+
}
66+
67+
client := http.Client{Timeout: 5 * time.Second}
68+
69+
fmt.Fprintln(w, "Generating an environment message...")
70+
reader := bufio.NewReader(os.Stdin)
71+
MenuLoop:
72+
for {
73+
fmt.Fprintf(w, "\n")
74+
ec.printCurrentState(w, *e)
75+
76+
var input string
77+
for {
78+
fmt.Fprintf(w, "\nSelect a value to edit by number, (p)rint current JSON message, (s)end, or (q)uit: ")
79+
l, err := fmt.Fscanln(reader, &input)
80+
if l > 1 || err != nil {
81+
continue
82+
}
83+
84+
switch input {
85+
case "q", "quit":
86+
fmt.Fprintf(w, "\nQuitting; message was not sent\n")
87+
os.Exit(1)
88+
case "s", "send":
89+
msg, err := toJSONBytes(*e)
90+
if err != nil {
91+
log.Fatalf("\nFailed to marshal JSON of environment object, no message sent\n")
92+
}
93+
94+
resp, err := client.Post(cmd.Flags().Lookup("target").Value.String(), "application/json", bytes.NewReader(msg))
95+
if err != nil {
96+
log.Fatalf(err.Error())
97+
}
98+
99+
bod, err := ioutil.ReadAll(resp.Body)
100+
resp.Body.Close()
101+
if err != nil {
102+
log.Fatalf(err.Error())
103+
}
104+
105+
if resp.StatusCode >= 200 && resp.StatusCode <= 300 {
106+
fmt.Printf("Message accepted (HTTP code %v), msgid %v\n", resp.StatusCode, string(bod))
107+
} else {
108+
fmt.Printf("Message was rejected with HTTP code %v and message %v\n", resp.StatusCode, string(bod))
109+
}
110+
break MenuLoop
111+
112+
case "p", "print":
113+
byts, err := toJSONBytes(*e)
114+
if err != nil {
115+
fmt.Fprintf(w, "Error while generating JSON for printing: %q", err.Error())
116+
continue MenuLoop
117+
}
118+
119+
var prettied bytes.Buffer
120+
err = json.Indent(&prettied, byts, "", " ")
121+
if err != nil {
122+
fmt.Fprintf(w, "Error while generating JSON for printing: %q", err.Error())
123+
continue MenuLoop
124+
}
125+
126+
fmt.Fprintf(w, "\nMessage that will be sent to %s:\n", cmd.Flags().Lookup("target").Value)
127+
prettied.WriteTo(w)
128+
w.WriteString("\n")
129+
130+
default:
131+
num, interr := strconv.Atoi(input)
132+
if interr != nil {
133+
continue
134+
} else if 0 < num && num < 7 {
135+
switch num {
136+
case 1:
137+
collectFQDN(w, reader, e)
138+
case 2:
139+
collectIpv4(w, reader, e)
140+
case 3:
141+
collectIpv6(w, reader, e)
142+
case 4:
143+
collectOS(w, reader, e)
144+
case 5:
145+
collectNick(w, reader, e)
146+
case 6:
147+
collectProvider(w, reader, e)
148+
}
149+
continue MenuLoop
150+
} else {
151+
continue
152+
}
153+
}
154+
}
155+
}
156+
}
157+
158+
func collectFQDN(w io.Writer, r io.Reader, e *semantic.Environment) {
159+
fmt.Fprintf(w, "\n\nEditing FQDN\nCurrent Value: %q\n", e.Address.Hostname)
160+
fmt.Fprint(w, "New value: ")
161+
162+
scn := bufio.NewScanner(r)
163+
scn.Scan()
164+
e.Address.Hostname = scn.Text()
165+
}
166+
167+
func collectIpv4(w io.Writer, r io.Reader, e *semantic.Environment) {
168+
fmt.Fprintf(w, "\n\nEditing IPv4\nCurrent Value: %q\n", e.Address.Ipv4)
169+
fmt.Fprint(w, "New value: ")
170+
171+
for {
172+
var input string
173+
_, err := fmt.Fscanln(r, &input)
174+
if err == nil {
175+
addr := net.ParseIP(input)
176+
if addr == nil {
177+
// failed to parse IP, invalid input
178+
fmt.Fprintf(w, "\nNot a valid IP address.\nNew value: ")
179+
} else if addr.To4() == nil {
180+
// not a valid IPv4
181+
fmt.Fprintf(w, "\nNot a valid IPv4 address.\nNew value: ")
182+
} else {
183+
e.Address.Ipv4 = addr.String()
184+
break
185+
}
186+
} else {
187+
fmt.Fprintf(w, "\nInvalid input.\nNew value: ")
188+
}
189+
}
190+
}
191+
192+
func collectIpv6(w io.Writer, r io.Reader, e *semantic.Environment) {
193+
fmt.Fprintf(w, "\n\nEditing IPv6\nCurrent Value: %q\n", e.Address.Ipv6)
194+
fmt.Fprint(w, "New value: ")
195+
196+
for {
197+
var input string
198+
_, err := fmt.Fscanln(r, &input)
199+
if err == nil {
200+
addr := net.ParseIP(input)
201+
if addr == nil {
202+
// failed to parse IP, invalid input
203+
fmt.Fprintf(w, "\nNot a valid IP address.\nNew value: ")
204+
} else if addr.To16() == nil {
205+
// not a valid IPv6
206+
fmt.Fprintf(w, "\nNot a valid IPv6 address.\nNew value: ")
207+
} else {
208+
e.Address.Ipv6 = addr.To16().String()
209+
break
210+
}
211+
} else {
212+
fmt.Fprintf(w, "\nInvalid input.\nNew value: ")
213+
}
214+
}
215+
}
216+
217+
func collectOS(w io.Writer, r io.Reader, e *semantic.Environment) {
218+
fmt.Fprintf(w, "\n\nEditing OS\nCurrent Value: %q\n", e.OS)
219+
fmt.Fprint(w, "New value: ")
220+
221+
scn := bufio.NewScanner(r)
222+
scn.Scan()
223+
e.OS = scn.Text()
224+
}
225+
226+
func collectNick(w io.Writer, r io.Reader, e *semantic.Environment) {
227+
fmt.Fprintf(w, "\n\nEditing Nick\nCurrent Value: %q\n", e.Nick)
228+
fmt.Fprint(w, "New value: ")
229+
230+
scn := bufio.NewScanner(r)
231+
scn.Scan()
232+
e.Nick = scn.Text()
233+
}
234+
235+
func collectProvider(w io.Writer, r io.Reader, e *semantic.Environment) {
236+
fmt.Fprintf(w, "\n\nEditing Provider\nCurrent Value: %q\n", e.Provider)
237+
fmt.Fprint(w, "New value: ")
238+
239+
scn := bufio.NewScanner(r)
240+
scn.Scan()
241+
e.Provider = scn.Text()
242+
}
243+
244+
// Inspects the currently running system to fill in some default values.
245+
func detectEnvDefaults() (e semantic.Environment) {
246+
var err error
247+
e.Address.Hostname, err = os.Hostname()
248+
if err != nil {
249+
e.Address.Hostname = ""
250+
}
251+
252+
e.OS = runtime.GOOS
253+
254+
return e
255+
}
256+
257+
// printMenu prints to stdout a menu showing the current data in the
258+
// message to be generated.
259+
func (ec envCmd) printCurrentState(w io.Writer, e semantic.Environment) {
260+
fmt.Fprintln(w, "Environment data:")
261+
var n int
262+
263+
n++
264+
//if e.Address.Hostname == "" {
265+
//fmt.Fprintf(w, " %v. *FQDN: [empty]\n", n)
266+
//} else {
267+
fmt.Fprintf(w, " %v. FQDN: %q\n", n, e.Address.Hostname)
268+
//}
269+
270+
n++
271+
fmt.Fprintf(w, " %v. Ipv4: %q\n", n, e.Address.Ipv4)
272+
n++
273+
fmt.Fprintf(w, " %v. Ipv6: %q\n", n, e.Address.Ipv6)
274+
275+
n++
276+
fmt.Fprintf(w, " %v. OS: %q\n", n, e.OS)
277+
278+
n++
279+
fmt.Fprintf(w, " %v. Nick: %q\n", n, e.Nick)
280+
281+
n++
282+
fmt.Fprintf(w, " %v. Provider: %q\n", n, e.Provider)
283+
284+
validateAndPrint(w, e)
285+
}

0 commit comments

Comments
 (0)