Skip to content

Commit

Permalink
Add ability to override pod spec options (#837)
Browse files Browse the repository at this point in the history
This change introduces the ability to override PodSpec options for
plugins. A new flag `--show-default-podspec` has been added to the
`gen` and `gen plugin` commands. When used, Sonobuoy will include the
default PodSpec options for the given plugin driver in the resulting
yaml. This allows users to change these values or they can provide their
own. If one is provided in the plugin definition, Sonobuoy will use that
as is, otherwise it will use the default.

Signed-off-by: Bridget McErlean <[email protected]>
  • Loading branch information
zubron authored Aug 15, 2019
1 parent 1cce037 commit 0fb9865
Show file tree
Hide file tree
Showing 17 changed files with 759 additions and 74 deletions.
9 changes: 9 additions & 0 deletions cmd/sonobuoy/app/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,15 @@ func AddTimeoutFlag(flag *int, flags *pflag.FlagSet) {
)
}

// AddShowDefaultPodSpecFlag adds an bool flag for determining whether or not to include the default pod spec
// used by Sonobuoy in the output
func AddShowDefaultPodSpecFlag(flag *bool, flags *pflag.FlagSet) {
flags.BoolVar(
flag, "show-default-podspec", false,
"If true, include the default pod spec used for plugins in the output",
)
}

// AddWaitOutputFlag adds a flag for spinner when wait flag is set for Sonobuoy operations.
func AddWaitOutputFlag(mode *WaitOutputMode, flags *pflag.FlagSet, defaultMode WaitOutputMode) {
*mode = defaultMode
Expand Down
3 changes: 3 additions & 0 deletions cmd/sonobuoy/app/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type genFlags struct {
imagePullPolicy ImagePullPolicy
e2eRepoList string
timeoutSeconds int
showDefaultPodSpec bool

// plugins will keep a list of the plugins we want. Custom type for
// flag support.
Expand Down Expand Up @@ -74,6 +75,7 @@ func GenFlagSet(cfg *genFlags, rbac RBACMode) *pflag.FlagSet {
AddRBACModeFlags(&cfg.rbacMode, genset, rbac)
AddImagePullPolicyFlag(&cfg.imagePullPolicy, genset)
AddTimeoutFlag(&cfg.timeoutSeconds, genset)
AddShowDefaultPodSpecFlag(&cfg.showDefaultPodSpec, genset)

AddNamespaceFlag(&cfg.namespace, genset)
AddSonobuoyImage(&cfg.sonobuoyImage, genset)
Expand Down Expand Up @@ -149,6 +151,7 @@ func (g *genFlags) Config() (*client.GenConfig, error) {
DynamicPlugins: g.plugins.DynamicPlugins,
StaticPlugins: g.plugins.StaticPlugins,
PluginEnvOverrides: g.pluginEnvs,
ShowDefaultPodSpec: g.showDefaultPodSpec,
}, nil
}

Expand Down
32 changes: 24 additions & 8 deletions cmd/sonobuoy/app/gen_plugin_def.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ import (

"github.com/heptio/sonobuoy/pkg/errlog"
"github.com/heptio/sonobuoy/pkg/plugin"
"github.com/heptio/sonobuoy/pkg/plugin/driver"
"github.com/heptio/sonobuoy/pkg/plugin/manifest"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"

v1 "k8s.io/api/core/v1"
kuberuntime "k8s.io/apimachinery/pkg/runtime"
Expand All @@ -47,6 +49,9 @@ type GenPluginDefConfig struct {
// driver holds the values that will be parsed into the plugin driver.
// Allows validation during flag parsing by having a custom type.
driver pluginDriver

// If set, the default pod spec used by Sonobuoy will be included in the output
showDefaultPodSpec bool
}

// NewCmdGenPluginDef ...
Expand All @@ -64,38 +69,43 @@ func NewCmdGenPluginDef() *cobra.Command {
Args: cobra.NoArgs,
}

cmd.Flags().StringVarP(
genPluginSet := pflag.NewFlagSet("generate plugin", pflag.ExitOnError)

genPluginSet.StringVarP(
&genPluginOpts.def.SonobuoyConfig.PluginName, "name", "n", "",
"Plugin name",
)
cmd.MarkFlagRequired("name")

cmd.Flags().VarP(
genPluginSet.VarP(
&genPluginOpts.driver, "type", "t",
"Plugin Driver (job or daemonset)",
)

cmd.Flags().StringVarP(
genPluginSet.StringVarP(
&genPluginOpts.def.Spec.Image, "image", "i", "",
"Plugin image",
)
cmd.MarkFlagRequired("image")

cmd.Flags().StringArrayVarP(
genPluginSet.StringArrayVarP(
&genPluginOpts.def.Spec.Command, "cmd", "c", []string{"./run.sh"},
`Command to run when starting the plugin's container. Can be set multiple times (e.g. --cmd /bin/sh -c "-c")`,
)

cmd.Flags().VarP(
genPluginSet.VarP(
&genPluginOpts.env, "env", "e",
"Env var values to set on the plugin (e.g. --env FOO=bar)",
)

cmd.Flags().StringArrayVarP(
genPluginSet.StringArrayVarP(
&genPluginOpts.def.Spec.Args, "arg", "a", []string{},
"Arg values to set on the plugin. Can be set multiple times (e.g. --arg 'arg 1' --arg arg2)",
)

AddShowDefaultPodSpecFlag(&genPluginOpts.showDefaultPodSpec, genPluginSet)

cmd.Flags().AddFlagSet(genPluginSet)
cmd.MarkFlagRequired("name")
cmd.MarkFlagRequired("image")
return cmd
}

Expand Down Expand Up @@ -147,6 +157,12 @@ func genPluginDef(cfg *GenPluginDefConfig) ([]byte, error) {
})
}

if cfg.showDefaultPodSpec {
cfg.def.PodSpec = &manifest.PodSpec{
PodSpec: driver.DefaultPodSpec(cfg.def.SonobuoyConfig.Driver),
}
}

yaml, err := kuberuntime.Encode(manifest.Encoder, &cfg.def)
return yaml, errors.Wrap(err, "serializing as YAML")
}
12 changes: 12 additions & 0 deletions cmd/sonobuoy/app/gen_plugin_def_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ func TestPluginGenDef(t *testing.T) {
env: map[string]string{"FOO": "- bar"},
},
expectFile: "testdata/pluginDef-quotes.golden",
}, {
desc: "default PodSpec is included if requested",
cfg: GenPluginDefConfig{
showDefaultPodSpec: true,
def: manifest.Manifest{
SonobuoyConfig: manifest.SonobuoyConfig{
PluginName: "n",
},
Spec: manifest.Container{},
},
},
expectFile: "testdata/pluginDef-default-podspec.golden",
},
}
for _, tC := range testCases {
Expand Down
17 changes: 17 additions & 0 deletions cmd/sonobuoy/app/testdata/pluginDef-default-podspec.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
podSpec:
containers: []
restartPolicy: Never
serviceAccountName: sonobuoy-serviceaccount
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/master
operator: Exists
- key: CriticalAddonsOnly
operator: Exists
sonobuoy-config:
driver: ""
plugin-name: "n"
result-type: "n"
spec:
name: ""
resources: {}
6 changes: 6 additions & 0 deletions pkg/client/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (

"github.com/heptio/sonobuoy/pkg/config"
"github.com/heptio/sonobuoy/pkg/plugin"
"github.com/heptio/sonobuoy/pkg/plugin/driver"
"github.com/heptio/sonobuoy/pkg/plugin/manifest"
"github.com/heptio/sonobuoy/pkg/templates"

Expand Down Expand Up @@ -159,6 +160,11 @@ func (*SonobuoyClient) GenerateManifest(cfg *GenConfig) ([]byte, error) {

pluginYAML := []string{}
for _, v := range plugins {
if cfg.ShowDefaultPodSpec && v.PodSpec == nil {
v.PodSpec = &manifest.PodSpec{
PodSpec: driver.DefaultPodSpec(v.SonobuoyConfig.Driver),
}
}
yaml, err := kuberuntime.Encode(manifest.Encoder, v)
if err != nil {
return nil, errors.Wrapf(err, "serializing plugin %v as YAML", v.SonobuoyConfig.PluginName)
Expand Down
20 changes: 20 additions & 0 deletions pkg/client/gen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,26 @@ func TestGenerateManifestGolden(t *testing.T) {
},
},
expectErr: "failed to override env vars for plugin e2e2, no plugin with that name found; have plugins: [e2e]",
}, {
name: "Default pod spec is included if requested and no other pod spec provided",
inputcm: &client.GenConfig{
E2EConfig: &client.E2EConfig{},
ShowDefaultPodSpec: true,
},
goldenFile: filepath.Join("testdata", "default-pod-spec.golden"),
}, {
name: "Existing pod spec is not modified if default pod spec is requested",
inputcm: &client.GenConfig{
E2EConfig: &client.E2EConfig{},
ShowDefaultPodSpec: true,
StaticPlugins: []*manifest.Manifest{
{
SonobuoyConfig: manifest.SonobuoyConfig{PluginName: "a"},
PodSpec: &manifest.PodSpec{},
},
},
},
goldenFile: filepath.Join("testdata", "use-existing-pod-spec.golden"),
},
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/client/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ type GenConfig struct {
// out of band from the plugins because of how the dynamic plugins are not
// yet able to be manipulated in this way.
PluginEnvOverrides map[string]map[string]string

// ShowDefaultPodSpec determines whether or not the default pod spec for
// the plugin should be incuded in the output.
ShowDefaultPodSpec bool
}

// Validate checks the config to determine if it is valid.
Expand Down
164 changes: 164 additions & 0 deletions pkg/client/testdata/default-pod-spec.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@

---
apiVersion: v1
kind: Namespace
metadata:
name:
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
component: sonobuoy
name: sonobuoy-serviceaccount
namespace:
---
apiVersion: v1
data:
config.json: |
{"Description":"","UUID":"","Version":"","ResultsDir":"","Resources":null,"Filters":{"Namespaces":"","LabelSelector":""},"Limits":{"PodLogs":{"Namespaces":"","SonobuoyNamespace":null,"FieldSelectors":null,"LabelSelector":"","Previous":false,"SinceSeconds":null,"SinceTime":null,"Timestamps":false,"TailLines":null,"LimitBytes":null,"LimitSize":"","LimitTime":""}},"Server":{"bindaddress":"","bindport":0,"advertiseaddress":"","timeoutseconds":0},"Plugins":null,"PluginSearchPath":null,"Namespace":"","WorkerImage":"","ImagePullPolicy":"","ImagePullSecrets":""}
kind: ConfigMap
metadata:
labels:
component: sonobuoy
name: sonobuoy-config-cm
namespace:
---
apiVersion: v1
data:
plugin-0.yaml: |
podSpec:
containers: []
restartPolicy: Never
serviceAccountName: sonobuoy-serviceaccount
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/master
operator: Exists
- key: CriticalAddonsOnly
operator: Exists
sonobuoy-config:
driver: Job
plugin-name: e2e
result-format: junit
result-type: e2e
spec:
command:
- /run_e2e.sh
env:
- name: E2E_FOCUS
- name: E2E_SKIP
- name: E2E_PARALLEL
name: e2e
resources: {}
volumeMounts:
- mountPath: /tmp/results
name: results
plugin-1.yaml: |
podSpec:
containers: []
dnsPolicy: ClusterFirstWithHostNet
hostIPC: true
hostNetwork: true
hostPID: true
serviceAccountName: sonobuoy-serviceaccount
tolerations:
- operator: Exists
volumes:
- hostPath:
path: /
name: root
sonobuoy-config:
driver: DaemonSet
plugin-name: systemd-logs
result-format: raw
result-type: systemd-logs
spec:
command:
- /bin/sh
- -c
- /get_systemd_logs.sh && sleep 3600
env:
- name: CHROOT_DIR
value: /node
- name: RESULTS_DIR
value: /tmp/results
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
image: gcr.io/heptio-images/sonobuoy-plugin-systemd-logs:latest
name: systemd-logs
resources: {}
securityContext:
privileged: true
volumeMounts:
- mountPath: /tmp/results
name: results
- mountPath: /node
name: root
kind: ConfigMap
metadata:
labels:
component: sonobuoy
name: sonobuoy-plugins-cm
namespace:
---
apiVersion: v1
kind: Pod
metadata:
labels:
component: sonobuoy
run: sonobuoy-master
tier: analysis
name: sonobuoy
namespace:
spec:
containers:
- command:
- /bin/bash
- -c
- /sonobuoy master --no-exit=true -v 3 --logtostderr
env:
- name: SONOBUOY_ADVERTISE_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
image:
imagePullPolicy:
name: kube-sonobuoy
volumeMounts:
- mountPath: /etc/sonobuoy
name: sonobuoy-config-volume
- mountPath: /plugins.d
name: sonobuoy-plugins-volume
- mountPath: /tmp/sonobuoy
name: output-volume
restartPolicy: Never
serviceAccountName: sonobuoy-serviceaccount
volumes:
- configMap:
name: sonobuoy-config-cm
name: sonobuoy-config-volume
- configMap:
name: sonobuoy-plugins-cm
name: sonobuoy-plugins-volume
- emptyDir: {}
name: output-volume
---
apiVersion: v1
kind: Service
metadata:
labels:
component: sonobuoy
run: sonobuoy-master
name: sonobuoy-master
namespace:
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
run: sonobuoy-master
type: ClusterIP
Loading

0 comments on commit 0fb9865

Please sign in to comment.