Skip to content

Commit 21cd48b

Browse files
authored
Merge pull request juju#10330 from ycliuhw/fix/podspec-cmd-args-parsing
juju#10330 ## Description of change Added helper funcs to go template for better podspec parsing and also fixing a bug related podspec parsing errors for container commands include shell scripts; ## QA steps - prepare caas model; - deploy containers commands like these (https://paste.ubuntu.com/p/P2sQTKxpq7/); ## Documentation changes None ## Bug reference https://bugs.launchpad.net/juju/+bug/1832783
2 parents 9f57a63 + 9cb0220 commit 21cd48b

File tree

5 files changed

+171
-56
lines changed

5 files changed

+171
-56
lines changed

caas/kubernetes/provider/export_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ var (
3434
AttemptMicroK8sCloud = attemptMicroK8sCloud
3535
EnsureMicroK8sSuitable = ensureMicroK8sSuitable
3636
NewK8sBroker = newK8sBroker
37+
ToYaml = toYaml
38+
Indent = indent
3739
)
3840

3941
type (

caas/kubernetes/provider/k8s.go

Lines changed: 4 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"strconv"
1616
"strings"
1717
"sync"
18-
"text/template"
1918
"time"
2019

2120
jujuclock "github.com/juju/clock"
@@ -34,7 +33,7 @@ import (
3433
"k8s.io/apimachinery/pkg/api/resource"
3534
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3635
"k8s.io/apimachinery/pkg/util/intstr"
37-
"k8s.io/apimachinery/pkg/util/yaml"
36+
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
3837
apimachineryversion "k8s.io/apimachinery/pkg/version"
3938
"k8s.io/apimachinery/pkg/watch"
4039
"k8s.io/client-go/kubernetes"
@@ -2464,61 +2463,18 @@ type unitSpec struct {
24642463
Service *K8sServiceSpec
24652464
}
24662465

2467-
var containerTemplate = `
2468-
- name: {{.Name}}
2469-
{{if .Ports}}
2470-
ports:
2471-
{{- range .Ports }}
2472-
- containerPort: {{.ContainerPort}}
2473-
{{if .Name}}name: {{.Name}}{{end}}
2474-
{{if .Protocol}}protocol: {{.Protocol}}{{end}}
2475-
{{- end}}
2476-
{{end}}
2477-
{{if .Command}}
2478-
command: [{{- range $idx, $c := .Command -}}{{if ne $idx 0}},{{end}}"{{$c}}"{{- end -}}]
2479-
{{end}}
2480-
{{if .Args}}
2481-
args: [{{- range $idx, $a := .Args -}}{{if ne $idx 0}},{{end}}"{{$a}}"{{- end -}}]
2482-
{{end}}
2483-
{{if .WorkingDir}}
2484-
workingDir: {{.WorkingDir}}
2485-
{{end}}
2486-
{{if .Config}}
2487-
env:
2488-
{{- range $k, $v := .Config }}
2489-
- name: {{$k}}
2490-
value: {{$v}}
2491-
{{- end}}
2492-
{{end}}
2493-
`
2494-
2495-
var defaultPodTemplate = fmt.Sprintf(`
2496-
pod:
2497-
containers:
2498-
{{- range .Containers }}
2499-
%s
2500-
{{- end}}
2501-
{{if .InitContainers}}
2502-
initContainers:
2503-
{{- range .InitContainers }}
2504-
%s
2505-
{{- end}}
2506-
{{end}}
2507-
`[1:], containerTemplate, containerTemplate)
2508-
25092466
func makeUnitSpec(appName, deploymentName string, podSpec *caas.PodSpec) (*unitSpec, error) {
25102467
// Fill out the easy bits using a template.
2511-
tmpl := template.Must(template.New("").Parse(defaultPodTemplate))
25122468
var buf bytes.Buffer
2513-
if err := tmpl.Execute(&buf, podSpec); err != nil {
2469+
if err := defaultPodTemplate.Execute(&buf, podSpec); err != nil {
25142470
return nil, errors.Trace(err)
25152471
}
25162472
unitSpecString := buf.String()
25172473

25182474
var unitSpec unitSpec
2519-
decoder := yaml.NewYAMLOrJSONDecoder(strings.NewReader(unitSpecString), len(unitSpecString))
2475+
decoder := k8syaml.NewYAMLOrJSONDecoder(strings.NewReader(unitSpecString), len(unitSpecString))
25202476
if err := decoder.Decode(&unitSpec); err != nil {
2521-
logger.Errorf("unable to parse %q pod spec: %+v\n%v", appName, *podSpec, unitSpecString)
2477+
logger.Errorf("unable to parse %q pod spec: \n%+v\nunit spec: \n%v", appName, *podSpec, unitSpecString)
25222478
return nil, errors.Trace(err)
25232479
}
25242480

caas/kubernetes/provider/k8stypes_test.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,12 @@ containers:
4646
- name: gitlab
4747
image: gitlab/latest
4848
imagePullPolicy: Always
49-
command: ["sh", "-c"]
49+
command:
50+
- sh
51+
- -c
52+
- |
53+
set -ex
54+
echo "do some stuff here for gitlab container"
5055
args: ["doIt", "--debug"]
5156
workingDir: "/path/to/here"
5257
ports:
@@ -97,7 +102,12 @@ initContainers:
97102
- name: gitlab-init
98103
image: gitlab-init/latest
99104
imagePullPolicy: Always
100-
command: ["sh", "-c"]
105+
command:
106+
- sh
107+
- -c
108+
- |
109+
set -ex
110+
echo "do some stuff here for gitlab-init container"
101111
args: ["doIt", "--debug"]
102112
workingDir: "/path/to/here"
103113
ports:
@@ -180,9 +190,12 @@ foo: bar
180190
},
181191
},
182192
Containers: []caas.ContainerSpec{{
183-
Name: "gitlab",
184-
Image: "gitlab/latest",
185-
Command: []string{"sh", "-c"},
193+
Name: "gitlab",
194+
Image: "gitlab/latest",
195+
Command: []string{"sh", "-c", `
196+
set -ex
197+
echo "do some stuff here for gitlab container"
198+
`[1:]},
186199
Args: []string{"doIt", "--debug"},
187200
WorkingDir: "/path/to/here",
188201
Ports: []caas.ContainerPort{
@@ -249,9 +262,12 @@ foo: bar
249262
},
250263
}},
251264
InitContainers: []caas.ContainerSpec{{
252-
Name: "gitlab-init",
253-
Image: "gitlab-init/latest",
254-
Command: []string{"sh", "-c"},
265+
Name: "gitlab-init",
266+
Image: "gitlab-init/latest",
267+
Command: []string{"sh", "-c", `
268+
set -ex
269+
echo "do some stuff here for gitlab-init container"
270+
`[1:]},
255271
Args: []string{"doIt", "--debug"},
256272
WorkingDir: "/path/to/here",
257273
Ports: []caas.ContainerPort{
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright 2019 Canonical Ltd.
2+
// Licensed under the AGPLv3, see LICENCE file for details.
3+
4+
package provider
5+
6+
import (
7+
"fmt"
8+
"strings"
9+
"text/template"
10+
11+
"github.com/juju/errors"
12+
"gopkg.in/yaml.v2"
13+
)
14+
15+
var containerTemplate = `
16+
- name: {{.Name}}
17+
{{if .Ports}}
18+
ports:
19+
{{- range .Ports }}
20+
- containerPort: {{.ContainerPort}}
21+
{{if .Name}}name: {{.Name}}{{end}}
22+
{{if .Protocol}}protocol: {{.Protocol}}{{end}}
23+
{{- end}}
24+
{{end}}
25+
{{if .Command}}
26+
command:
27+
{{ toYaml .Command | indent 6 }}
28+
{{end}}
29+
{{if .Args}}
30+
args:
31+
{{ toYaml .Args | indent 6 }}
32+
{{end}}
33+
{{if .WorkingDir}}
34+
workingDir: {{.WorkingDir}}
35+
{{end}}
36+
{{if .Config}}
37+
env:
38+
{{- range $k, $v := .Config }}
39+
- name: {{$k}}
40+
value: {{$v}}
41+
{{- end}}
42+
{{end}}`[1:]
43+
44+
var defaultPodTemplateStr = fmt.Sprintf(`
45+
pod:
46+
containers:
47+
{{- range .Containers }}
48+
%s
49+
{{- end}}
50+
{{if .InitContainers}}
51+
initContainers:
52+
{{- range .InitContainers }}
53+
%s
54+
{{- end}}
55+
{{end}}
56+
`[1:], containerTemplate, containerTemplate)
57+
58+
var defaultPodTemplate = template.Must(template.New("").Funcs(templateAddons).Parse(defaultPodTemplateStr))
59+
60+
func toYaml(val interface{}) (string, error) {
61+
data, err := yaml.Marshal(val)
62+
if err != nil {
63+
return "", errors.Annotatef(err, "marshalling to yaml for %v", val)
64+
}
65+
return string(data), nil
66+
}
67+
68+
func indent(n int, str string) string {
69+
out := ""
70+
prefix := strings.Repeat(" ", n)
71+
for _, line := range strings.Split(str, "\n") {
72+
out += prefix + line + "\n"
73+
}
74+
return out
75+
}
76+
77+
var templateAddons = template.FuncMap{
78+
"toYaml": toYaml,
79+
"indent": indent,
80+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2019 Canonical Ltd.
2+
// Licensed under the AGPLv3, see LICENCE file for details.
3+
4+
package provider_test
5+
6+
import (
7+
jc "github.com/juju/testing/checkers"
8+
gc "gopkg.in/check.v1"
9+
10+
"github.com/juju/juju/caas/kubernetes/provider"
11+
"github.com/juju/juju/testing"
12+
)
13+
14+
type templateSuite struct {
15+
testing.BaseSuite
16+
}
17+
18+
var _ = gc.Suite(&templateSuite{})
19+
20+
func (t *templateSuite) TestToYaml(c *gc.C) {
21+
in := struct {
22+
Command []string `yaml:"command,omitempty"`
23+
}{
24+
Command: []string{"sh", "-c", `
25+
set -ex
26+
echo "do some stuff here for gitlab container"
27+
`[1:]},
28+
}
29+
out, err := provider.ToYaml(in)
30+
c.Assert(err, jc.ErrorIsNil)
31+
c.Assert(out, jc.DeepEquals, `
32+
command:
33+
- sh
34+
- -c
35+
- |
36+
set -ex
37+
echo "do some stuff here for gitlab container"
38+
`[1:])
39+
}
40+
41+
func (t *templateSuite) TestIndent(c *gc.C) {
42+
out := provider.Indent(6, `
43+
line 1
44+
line 2
45+
line 3`[1:])
46+
c.Assert(out, jc.DeepEquals, `
47+
line 1
48+
line 2
49+
line 3
50+
`[1:])
51+
52+
out = provider.Indent(8, `
53+
line 1
54+
line 2
55+
line 3`[1:])
56+
c.Assert(out, jc.DeepEquals, `
57+
line 1
58+
line 2
59+
line 3
60+
`[1:])
61+
}

0 commit comments

Comments
 (0)