in istioctl/cmd/kubeinject.go [508:668]
func injectCommand() *cobra.Command {
var opts clioptions.ControlPlaneOptions
var centralOpts clioptions.CentralControlPlaneOptions
injectCmd := &cobra.Command{
Use: "kube-inject",
Short: "Inject Istio sidecar into Kubernetes pod resources",
Long: `
kube-inject manually injects the Istio sidecar into Kubernetes
workloads. Unsupported resources are left unmodified so it is safe to
run kube-inject over a single file that contains multiple Service,
ConfigMap, Deployment, etc. definitions for a complex application. When in
doubt re-run istioctl kube-inject on deployments to get the most up-to-date changes.
It's best to do kube-inject when the resource is initially created.
`,
Example: ` # Update resources on the fly before applying.
kubectl apply -f <(istioctl kube-inject -f <resource.yaml>)
# Create a persistent version of the deployment with Istio sidecar injected.
istioctl kube-inject -f deployment.yaml -o deployment-injected.yaml
# Update an existing deployment.
kubectl get deployment -o yaml | istioctl kube-inject -f - | kubectl apply -f -
# Capture cluster configuration for later use with kube-inject
kubectl -n dubbo-system get cm istio-sidecar-injector -o jsonpath="{.data.config}" > /tmp/inj-template.tmpl
kubectl -n dubbo-system get cm istio -o jsonpath="{.data.mesh}" > /tmp/mesh.yaml
kubectl -n dubbo-system get cm istio-sidecar-injector -o jsonpath="{.data.values}" > /tmp/values.json
# Use kube-inject based on captured configuration
istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml \
--injectConfigFile /tmp/inj-template.tmpl \
--meshConfigFile /tmp/mesh.yaml \
--valuesFile /tmp/values.json
`,
RunE: func(c *cobra.Command, _ []string) (err error) {
if err = validateFlags(); err != nil {
return err
}
var reader io.Reader
if inFilename == "-" {
reader = os.Stdin
} else {
var in *os.File
if in, err = os.Open(inFilename); err != nil {
return err
}
reader = in
defer func() {
if errClose := in.Close(); errClose != nil {
log.Errorf("Error: close file from %s, %s", inFilename, errClose)
// don't overwrite the previous error
if err == nil {
err = errClose
}
}
}()
}
var writer io.Writer
if outFilename == "" {
writer = c.OutOrStdout()
} else {
var out *os.File
if out, err = os.Create(outFilename); err != nil {
return err
}
writer = out
defer func() {
if errClose := out.Close(); errClose != nil {
log.Errorf("Error: close file from %s, %s", outFilename, errClose)
// don't overwrite the previous error
if err == nil {
err = errClose
}
}
}()
}
var valuesConfig string
var sidecarTemplate inject.RawTemplates
var meshConfig *meshconfig.MeshConfig
rev := opts.Revision
// if the revision is "default", render templates with an empty revision
if rev == tag.DefaultRevisionName {
rev = ""
}
injectorAddress := centralOpts.Xds
index := strings.IndexByte(injectorAddress, ':')
if index != -1 {
injectorAddress = injectorAddress[:index]
}
injector, meshConfig, err := setupKubeInjectParameters(&sidecarTemplate, &valuesConfig, rev, injectorAddress)
if err != nil {
return err
}
if injector.client == nil && meshConfig == nil {
return fmt.Errorf(
"failed to get injection config from mutatingWebhookConfigurations and injection configmap - " +
"check injection configmap or pass --revision flag",
)
}
var warnings []string
templs, err := inject.ParseTemplates(sidecarTemplate)
if err != nil {
return err
}
vc, err := inject.NewValuesConfig(valuesConfig)
if err != nil {
return err
}
retval := inject.IntoResourceFile(injector, templs, vc, rev, meshConfig,
reader, writer, func(warning string) {
warnings = append(warnings, warning)
})
if len(warnings) > 0 {
fmt.Fprintln(c.ErrOrStderr())
}
for _, warning := range warnings {
fmt.Fprintln(c.ErrOrStderr(), warning)
}
return retval
},
PersistentPreRunE: func(c *cobra.Command, args []string) error {
// istioctl kube-inject is typically redirected to a .yaml file;
// the default for log messages should be stderr, not stdout
_ = c.Root().PersistentFlags().Set("log_target", "stderr")
return c.Parent().PersistentPreRunE(c, args)
},
}
injectCmd.PersistentFlags().StringVar(&meshConfigFile, "meshConfigFile", "",
"Mesh configuration filename. Takes precedence over --meshConfigMapName if set")
injectCmd.PersistentFlags().StringVar(&injectConfigFile, "injectConfigFile", "",
"Injection configuration filename. Cannot be used with --injectConfigMapName")
injectCmd.PersistentFlags().StringVar(&valuesFile, "valuesFile", "",
"Injection values configuration filename.")
injectCmd.PersistentFlags().StringVarP(&inFilename, "filename", "f",
"", "Input Kubernetes resource filename")
injectCmd.PersistentFlags().StringVarP(&outFilename, "output", "o",
"", "Modified output Kubernetes resource filename")
injectCmd.PersistentFlags().StringVar(&iopFilename, "operatorFileName", "",
"Path to file containing IstioOperator custom resources. If configs from files like "+
"meshConfigFile, valuesFile are provided, they will be overridden by iop config values.")
injectCmd.PersistentFlags().StringVar(&meshConfigMapName, "meshConfigMapName", defaultMeshConfigMapName,
fmt.Sprintf("ConfigMap name for Istio mesh configuration, key should be %q", configMapKey))
injectCmd.PersistentFlags().StringVar(&injectConfigMapName, "injectConfigMapName", defaultInjectConfigMapName,
fmt.Sprintf("ConfigMap name for Istio sidecar injection, key should be %q.", injectConfigMapKey))
_ = injectCmd.PersistentFlags().MarkHidden("injectConfigMapName")
injectCmd.PersistentFlags().StringVar(&whcName, "webhookConfig", defaultInjectWebhookConfigName,
"MutatingWebhookConfiguration name for Istio")
opts.AttachControlPlaneFlags(injectCmd)
centralOpts.AttachControlPlaneFlags(injectCmd)
return injectCmd
}