Browse Source

allow reading userdata from file, for inconvenient values

Antoine Grondin 3 years ago
parent
commit
f8f711296e
5 changed files with 83 additions and 8 deletions
  1. 1
    0
      args.go
  2. 6
    2
      cmd/docli/droplet_commands.go
  3. 11
    1
      droplets.go
  4. 46
    5
      droplets_test.go
  5. 19
    0
      testdata/cloud-config.yml

+ 1
- 0
args.go View File

@@ -26,6 +26,7 @@ const (
26 26
 	ArgSizeSlug          = "size"
27 27
 	ArgSSHKeys           = "ssh-keys"
28 28
 	ArgUserData          = "user-data"
29
+	ArgUserDataFile      = "user-data-file"
29 30
 	ArgImageName         = "image-name"
30 31
 	ArgKey               = "key"
31 32
 	ArgKeyName           = "key-name"

+ 6
- 2
cmd/docli/droplet_commands.go View File

@@ -75,8 +75,12 @@ func dropletCreate() cli.Command {
75 75
 				Usage: "enable droplet private networking",
76 76
 			},
77 77
 			cli.StringFlag{
78
-				Name:  docli.ArgUserData,
79
-				Usage: "droplet name",
78
+				Name:  doit.ArgUserData,
79
+				Usage: "droplet user data",
80
+			},
81
+			cli.StringFlag{
82
+				Name:  doit.ArgUserDataFile,
83
+				Usage: "reads droplet user data from a file",
80 84
 			},
81 85
 			jsonFlag(),
82 86
 			textFlag(),

+ 11
- 1
droplets.go View File

@@ -1,6 +1,7 @@
1 1
 package docli
2 2
 
3 3
 import (
4
+	"io/ioutil"
4 5
 	"strconv"
5 6
 
6 7
 	"github.com/Sirupsen/logrus"
@@ -94,6 +95,15 @@ func DropletCreate(c *cli.Context) {
94 95
 		sshKeys = append(sshKeys, godo.DropletCreateSSHKey{Fingerprint: rawKey})
95 96
 	}
96 97
 
98
+	userData := c.String(ArgUserData)
99
+	if userData == "" && c.String(ArgUserDataFile) != "" {
100
+		data, err := ioutil.ReadFile(c.String(ArgUserDataFile))
101
+		if err != nil {
102
+			logrus.WithField("err", err).Fatal("could not read user-data file")
103
+		}
104
+		userData = string(data)
105
+	}
106
+
97 107
 	dcr := &godo.DropletCreateRequest{
98 108
 		Name:              c.String(ArgDropletName),
99 109
 		Region:            c.String(ArgRegionSlug),
@@ -102,7 +112,7 @@ func DropletCreate(c *cli.Context) {
102 112
 		IPv6:              c.Bool(ArgIPv6),
103 113
 		PrivateNetworking: c.Bool(ArgPrivateNetworking),
104 114
 		SSHKeys:           sshKeys,
105
-		UserData:          c.String(ArgUserData),
115
+		UserData:          userData,
106 116
 	}
107 117
 
108 118
 	imageStr := c.String(ArgImage)

+ 46
- 5
droplets_test.go View File

@@ -2,6 +2,7 @@ package docli
2 2
 
3 3
 import (
4 4
 	"flag"
5
+	"io/ioutil"
5 6
 	"testing"
6 7
 
7 8
 	"github.com/codegangsta/cli"
@@ -68,11 +69,12 @@ func TestDropletCreate(t *testing.T) {
68 69
 		Droplets: &DropletsServiceMock{
69 70
 			CreateFn: func(cr *godo.DropletCreateRequest) (*godo.Droplet, *godo.Response, error) {
70 71
 				expected := &godo.DropletCreateRequest{
71
-					Name:    "droplet",
72
-					Image:   godo.DropletCreateImage{Slug: "image"},
73
-					Region:  "dev0",
74
-					Size:    "1gb",
75
-					SSHKeys: []godo.DropletCreateSSHKey{},
72
+					Name:     "droplet",
73
+					Image:    godo.DropletCreateImage{Slug: "image"},
74
+					Region:   "dev0",
75
+					Size:     "1gb",
76
+					UserData: "#cloud-config",
77
+					SSHKeys:  []godo.DropletCreateSSHKey{},
76 78
 				}
77 79
 
78 80
 				assert.Equal(t, cr, expected, "create requests did not match")
@@ -88,6 +90,45 @@ func TestDropletCreate(t *testing.T) {
88 90
 	fs.String(ArgRegionSlug, "dev0", ArgRegionSlug)
89 91
 	fs.String(ArgSizeSlug, "1gb", ArgSizeSlug)
90 92
 	fs.String(ArgImage, "image", ArgImage)
93
+	fs.String(ArgUserData, "#cloud-config", ArgUserData)
94
+
95
+	WithinTest(cs, fs, func(c *cli.Context) {
96
+		DropletCreate(c)
97
+	})
98
+}
99
+
100
+func TestDropletCreateUserDataFile(t *testing.T) {
101
+	userData, err := ioutil.ReadFile("testdata/cloud-config.yml")
102
+	if err != nil {
103
+		t.Fatal(err)
104
+	}
105
+
106
+	client := &godo.Client{
107
+		Droplets: &DropletsServiceMock{
108
+			CreateFn: func(cr *godo.DropletCreateRequest) (*godo.Droplet, *godo.Response, error) {
109
+				expected := &godo.DropletCreateRequest{
110
+					Name:     "droplet",
111
+					Image:    godo.DropletCreateImage{Slug: "image"},
112
+					Region:   "dev0",
113
+					Size:     "1gb",
114
+					UserData: string(userData),
115
+					SSHKeys:  []godo.DropletCreateSSHKey{},
116
+				}
117
+
118
+				assert.Equal(t, cr, expected, "create requests did not match")
119
+
120
+				return &testDroplet, nil, nil
121
+			},
122
+		},
123
+	}
124
+
125
+	cs := NewTestConfig(client)
126
+	fs := flag.NewFlagSet("flag set", 0)
127
+	fs.String(ArgDropletName, "droplet", ArgDropletName)
128
+	fs.String(ArgRegionSlug, "dev0", ArgRegionSlug)
129
+	fs.String(ArgSizeSlug, "1gb", ArgSizeSlug)
130
+	fs.String(ArgImage, "image", ArgImage)
131
+	fs.String(ArgUserDataFile, "testdata/cloud-config.yml", ArgUserDataFile)
91 132
 
92 133
 	WithinTest(cs, fs, func(c *cli.Context) {
93 134
 		DropletCreate(c)

+ 19
- 0
testdata/cloud-config.yml View File

@@ -0,0 +1,19 @@
1
+#cloud-config
2
+
3
+coreos:
4
+  etcd2:
5
+    # generate a new token for each unique cluster from https://discovery.etcd.io/new?size=5
6
+    # specify the initial size of your cluster with ?size=X
7
+    discovery: https://discovery.etcd.io/<token>
8
+    # multi-region and multi-cloud deployments need to use $public_ipv4
9
+    advertise-client-urls: http://$private_ipv4:2379,http://$private_ipv4:4001
10
+    initial-advertise-peer-urls: http://$private_ipv4:2380
11
+    # listen on both the official ports and the legacy ports
12
+    # legacy ports can be omitted if your application doesn't depend on them
13
+    listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
14
+    listen-peer-urls: http://$private_ipv4:2380
15
+  units:
16
+    - name: etcd2.service
17
+      command: start
18
+    - name: fleet.service
19
+      command: start