Skip to content
This repository was archived by the owner on Oct 11, 2023. It is now read-only.

Commit bfa2592

Browse files
bensallenniusmallnan
authored andcommitted
Support More Complex Cmdline Configuration
Fixes #2755. Allows for quoted arguments with spaces in the kernel cmdline to be parsed properly. An example command line: ``` $ cat /proc/cmdline earlyprintk=serial console=ttyS0 rancher.autologin=ttyS0 rancher.defaults.hostname=ros-vm1 rancher.defaults.network.dns.nameservers=[192.168.64.1] rancher.network.interfaces.eth0.dhcp=true rancher.network.interfaces.eth1.dhcp=false rancher.network.interfaces.eth1.address=192.168.99.11/24 rancher.state.dev=LABEL=RANCHER_STATE rancher.state.autoformat=[/dev/vda] rancher.state.formatzero cc.ssh_authorized_keys=['ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOz8mD0tRrNsHBLHD5jVgmXO26JA7eKFZrj4Ic9KR2y3qXlxU9JCYYn/qDyTCmExt8Rw6SaU/BvgU7WT3Bjsi6c=','ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJj5mkpBHBBAW5XClcB5aFTWph+VCL7I0W8gm93AT5w4','ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKfb0O2qXgIgrtD5Mj7fBYdg4jMrT7wetBbkG2e4maDsRR3AtSYjEB3NeEifM8gdvIf0gYs1BNB/Ar76agaQGeqW+Ewb2LWdypr4Ipw09yWCrC9ttVbCnHuzVLYjML0CNgpjIRC+FC5r1X1gm2LufRN4orZ1NQvNhRRWJVT37vRtHo79TecK0DKQmy87Zpj3cNiI/5iObnTk56pZWpIAEiC5hEVkcVxmdkLJs3YonWVZzmK/Y8uvFtF+GhA6Jcpc38zDQHKsOjFWvj3qbWtVEQteNDxsM2pNeXY5wdrhRn4YSdKme9Cm7CdAogIdAdPtqPIfq/jY0QczS12qFZH7zt'] ``` Results in: ``` $ sudo ros config export rancher: defaults: hostname: ros-vm1 network: dns: nameservers: - 192.168.64.1 environment: EXTRA_CMDLINE: /init AAAAC3NzaC1lZDI1NTE5AAAAIJj5mkpBHBBAW5XClcB5aFTWph+VCL7I0W8gm93AT5w4','ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKfb0O2qXgIgrtD5Mj7fBYdg4jMrT7wetBbkG2e4maDsRR3AtSYjEB3NeEifM8gdvIf0gYs1BNB/Ar76agaQGeqW+Ewb2LWdypr4Ipw09yWCrC9ttVbCnHuzVLYjML0CNgpjIRC+FC5r1X1gm2LufRN4orZ1NQvNhRRWJVT37vRtHo79TecK0DKQmy87Zpj3cNiI/5iObnTk56pZWpIAEiC5hEVkcVxmdkLJs3YonWVZzmK/Y8uvFtF+GhA6Jcpc38zDQHKsOjFWvj3qbWtVEQteNDxsM2pNeXY5wdrhRn4YSdKme9Cm7CdAogIdAdPtqPIfq/jY0QczS12qFZH7zt'] network: interfaces: eth0: dhcp: true eth1: address: 192.168.99.11/24 dhcp: false state: autoformat: - /dev/vda dev: LABEL=RANCHER_STATE formatzero: true ssh_authorized_keys: - ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOz8mD0tRrNsHBLHD5jVgmXO26JA7eKFZrj4Ic9KR2y3qXlxU9JCYYn/qDyTCmExt8Rw6SaU/BvgU7WT3Bjsi6c= - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJj5mkpBHBBAW5XClcB5aFTWph+VCL7I0W8gm93AT5w4 - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKfb0O2qXgIgrtD5Mj7fBYdg4jMrT7wetBbkG2e4maDsRR3AtSYjEB3NeEifM8gdvIf0gYs1BNB/Ar76agaQGeqW+Ewb2LWdypr4Ipw09yWCrC9ttVbCnHuzVLYjML0CNgpjIRC+FC5r1X1gm2LufRN4orZ1NQvNhRRWJVT37vRtHo79TecK0DKQmy87Zpj3cNiI/5iObnTk56pZWpIAEiC5hEVkcVxmdkLJs3YonWVZzmK/Y8uvFtF+GhA6Jcpc38zDQHKsOjFWvj3qbWtVEQteNDxsM2pNeXY5wdrhRn4YSdKme9Cm7CdAogIdAdPtqPIfq/jY0QczS12qFZH7zt ```
1 parent 8edb916 commit bfa2592

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

config/cmdline/cmdline.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cmdline
33
import (
44
"io/ioutil"
55
"strings"
6+
"unicode"
67

78
"github.com/rancher/os/pkg/util"
89

@@ -125,11 +126,34 @@ func UnmarshalOrReturnString(value string) (result interface{}) {
125126
return
126127
}
127128

129+
//splitCmdLine splits on spaces except when a space is within a quoted or bracketed string.
130+
func splitCmdLine(cmdLine string) []string {
131+
lastRune := rune(0)
132+
f := func(c rune) bool {
133+
switch {
134+
case c == lastRune:
135+
lastRune = rune(0)
136+
return false
137+
case lastRune != rune(0):
138+
return false
139+
case unicode.In(c, unicode.Quotation_Mark):
140+
lastRune = c
141+
return false
142+
case c == '[':
143+
lastRune = ']'
144+
return false
145+
default:
146+
return c == ' '
147+
}
148+
}
149+
return strings.FieldsFunc(cmdLine, f)
150+
}
151+
128152
func Parse(cmdLine string, parseAll bool) map[interface{}]interface{} {
129153
result := map[interface{}]interface{}{}
130154

131155
outer:
132-
for _, part := range strings.Split(cmdLine, " ") {
156+
for _, part := range splitCmdLine(cmdLine) {
133157
if strings.HasPrefix(part, "cc.") {
134158
part = part[3:]
135159
} else if !strings.HasPrefix(part, "rancher.") {

config/config_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ func TestCmdlineParse(t *testing.T) {
123123
},
124124
}, cmdline.Parse("rancher.key=a\nb", false), false)
125125

126+
assert.Equal(map[interface{}]interface{}{
127+
"rancher": map[interface{}]interface{}{
128+
"key": "a b",
129+
},
130+
}, cmdline.Parse("rancher.key='a b'", false), false)
131+
126132
assert.Equal(map[interface{}]interface{}{
127133
"rancher": map[interface{}]interface{}{
128134
"key": "a:b",
@@ -158,6 +164,24 @@ func TestCmdlineParse(t *testing.T) {
158164
"strArray": []interface{}{"url:http://192.168.1.100/cloud-config?a=b"},
159165
},
160166
}, cmdline.Parse("rancher.strArray=[url:http://192.168.1.100/cloud-config?a=b]", false), false)
167+
168+
assert.Equal(map[interface{}]interface{}{
169+
"rancher": map[interface{}]interface{}{
170+
"strArray": []interface{}{"part1 part2", "part3"},
171+
},
172+
}, cmdline.Parse("rancher.strArray=['part1 part2',part3]", false), false)
173+
174+
assert.Equal(map[interface{}]interface{}{
175+
"rancher": map[interface{}]interface{}{
176+
"strArray": []interface{}{"part1 part2", "part3"},
177+
},
178+
}, cmdline.Parse("rancher.strArray=[\"part1 part2\",part3]", false), false)
179+
180+
assert.Equal(map[interface{}]interface{}{
181+
"rancher": map[interface{}]interface{}{
182+
"strArray": []interface{}{"part1 part2", "part3"},
183+
},
184+
}, cmdline.Parse("rancher.strArray=[ \"part1 part2\", part3 ]", false), false)
161185
}
162186

163187
func TestGet(t *testing.T) {

0 commit comments

Comments
 (0)