mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-05 07:27:21 +00:00
Merge pull request #15921 from brendandburns/fix2
Add a --expose flag to kubectl run
This commit is contained in:
@@ -24,12 +24,14 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -77,6 +79,11 @@ func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c
|
||||
},
|
||||
}
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
addRunFlags(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func addRunFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().String("generator", "", "The name of the API generator to use. Default is 'run/v1' if --restart=Always, otherwise the default is 'run-pod/v1'.")
|
||||
cmd.Flags().String("image", "", "The image for the container to run.")
|
||||
cmd.MarkFlagRequired("image")
|
||||
@@ -84,7 +91,7 @@ func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c
|
||||
cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.")
|
||||
cmd.Flags().String("overrides", "", "An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.")
|
||||
cmd.Flags().StringSlice("env", []string{}, "Environment variables to set in the container")
|
||||
cmd.Flags().Int("port", -1, "The port that this container exposes.")
|
||||
cmd.Flags().Int("port", -1, "The port that this container exposes. If --expose is true, this is also the port used by the service that is created.")
|
||||
cmd.Flags().Int("hostport", -1, "The host port mapping for the container port. To demonstrate a single-machine container.")
|
||||
cmd.Flags().StringP("labels", "l", "", "Labels to apply to the pod(s).")
|
||||
cmd.Flags().BoolP("stdin", "i", false, "Keep stdin open on the container(s) in the pod, even if nothing is attached.")
|
||||
@@ -95,7 +102,9 @@ func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c
|
||||
cmd.Flags().Bool("command", false, "If true and extra arguments are present, use them as the 'command' field in the container, rather than the 'args' field which is the default.")
|
||||
cmd.Flags().String("requests", "", "The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'")
|
||||
cmd.Flags().String("limits", "", "The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'")
|
||||
return cmd
|
||||
cmd.Flags().Bool("expose", false, "If true, a public, external service is created for the container(s) which are run")
|
||||
cmd.Flags().String("service-generator", "service/v2", "The name of the generator to use for creating a service. Only used if --expose is true")
|
||||
cmd.Flags().String("service-overrides", "", "An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.")
|
||||
}
|
||||
|
||||
func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.Command, args []string) error {
|
||||
@@ -129,6 +138,7 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob
|
||||
if restartPolicy != api.RestartPolicyAlways && replicas != 1 {
|
||||
return cmdutil.UsageError(cmd, fmt.Sprintf("--restart=%s requires that --replicas=1, found %d", restartPolicy, replicas))
|
||||
}
|
||||
|
||||
generatorName := cmdutil.GetFlagString(cmd, "generator")
|
||||
if len(generatorName) == 0 {
|
||||
if restartPolicy == api.RestartPolicyAlways {
|
||||
@@ -150,64 +160,20 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob
|
||||
|
||||
params["env"] = cmdutil.GetFlagStringSlice(cmd, "env")
|
||||
|
||||
err = kubectl.ValidateParams(names, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
obj, err := generator.Generate(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mapper, typer := f.Object()
|
||||
version, kind, err := typer.ObjectVersionAndKind(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
inline := cmdutil.GetFlagString(cmd, "overrides")
|
||||
if len(inline) > 0 {
|
||||
obj, err = cmdutil.Merge(obj, inline, kind)
|
||||
if err != nil {
|
||||
if cmdutil.GetFlagBool(cmd, "expose") {
|
||||
serviceGenerator := cmdutil.GetFlagString(cmd, "service-generator")
|
||||
if len(serviceGenerator) == 0 {
|
||||
return cmdutil.UsageError(cmd, fmt.Sprintf("No service generator specified"))
|
||||
}
|
||||
if err := generateService(f, cmd, args, serviceGenerator, params, namespace, cmdOut); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
mapping, err := mapper.RESTMapping(kind, version)
|
||||
obj, kind, mapper, mapping, err := createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "overrides"), namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := f.RESTClient(mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: extract this flag to a central location, when such a location exists.
|
||||
if !cmdutil.GetFlagBool(cmd, "dry-run") {
|
||||
resourceMapper := &resource.Mapper{ObjectTyper: typer, RESTMapper: mapper, ClientMapper: f.ClientMapperForCommand()}
|
||||
info, err := resourceMapper.InfoForObject(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Serialize the configuration into an annotation.
|
||||
if err := kubectl.UpdateApplyAnnotation(info); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Serialize the object with the annotation applied.
|
||||
data, err := mapping.Codec.Encode(info.Object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
obj, err = resource.NewHelper(client, mapping).Create(namespace, false, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
attachFlag := cmd.Flags().Lookup("attach")
|
||||
attach := cmdutil.GetFlagBool(cmd, "attach")
|
||||
|
||||
@@ -337,3 +303,110 @@ func getRestartPolicy(cmd *cobra.Command, interactive bool) (api.RestartPolicy,
|
||||
return "", cmdutil.UsageError(cmd, fmt.Sprintf("invalid restart policy: %s", restart))
|
||||
}
|
||||
}
|
||||
|
||||
func generateService(f *cmdutil.Factory, cmd *cobra.Command, args []string, serviceGenerator string, paramsIn map[string]interface{}, namespace string, out io.Writer) error {
|
||||
generator, found := f.Generator(serviceGenerator)
|
||||
if !found {
|
||||
return fmt.Errorf("missing service generator: %s", serviceGenerator)
|
||||
}
|
||||
names := generator.ParamNames()
|
||||
|
||||
port := cmdutil.GetFlagInt(cmd, "port")
|
||||
if port < 1 {
|
||||
return fmt.Errorf("--port must be a positive integer when exposing a service")
|
||||
}
|
||||
|
||||
params := map[string]interface{}{}
|
||||
for key, value := range paramsIn {
|
||||
_, isString := value.(string)
|
||||
if isString {
|
||||
params[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
name, found := params["name"]
|
||||
if !found || len(name.(string)) == 0 {
|
||||
return fmt.Errorf("name is a required parameter")
|
||||
}
|
||||
selector, found := params["labels"]
|
||||
if !found || len(selector.(string)) == 0 {
|
||||
selector = fmt.Sprintf("run=%s", name.(string))
|
||||
}
|
||||
params["selector"] = selector
|
||||
|
||||
if defaultName, found := params["default-name"]; !found || len(defaultName.(string)) == 0 {
|
||||
params["default-name"] = name
|
||||
}
|
||||
|
||||
obj, _, mapper, mapping, err := createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "service-overrides"), namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmdutil.GetFlagString(cmd, "output") != "" {
|
||||
return f.PrintObject(cmd, obj, out)
|
||||
}
|
||||
cmdutil.PrintSuccess(mapper, false, out, mapping.Resource, args[0], "created")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createGeneratedObject(f *cmdutil.Factory, cmd *cobra.Command, generator kubectl.Generator, names []kubectl.GeneratorParam, params map[string]interface{}, overrides, namespace string) (runtime.Object, string, meta.RESTMapper, *meta.RESTMapping, error) {
|
||||
err := kubectl.ValidateParams(names, params)
|
||||
if err != nil {
|
||||
return nil, "", nil, nil, err
|
||||
}
|
||||
|
||||
obj, err := generator.Generate(params)
|
||||
if err != nil {
|
||||
return nil, "", nil, nil, err
|
||||
}
|
||||
|
||||
mapper, typer := f.Object()
|
||||
version, kind, err := typer.ObjectVersionAndKind(obj)
|
||||
if err != nil {
|
||||
return nil, "", nil, nil, err
|
||||
}
|
||||
|
||||
if len(overrides) > 0 {
|
||||
obj, err = cmdutil.Merge(obj, overrides, kind)
|
||||
if err != nil {
|
||||
return nil, "", nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
mapping, err := mapper.RESTMapping(kind, version)
|
||||
if err != nil {
|
||||
return nil, "", nil, nil, err
|
||||
}
|
||||
client, err := f.RESTClient(mapping)
|
||||
if err != nil {
|
||||
return nil, "", nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: extract this flag to a central location, when such a location exists.
|
||||
if !cmdutil.GetFlagBool(cmd, "dry-run") {
|
||||
resourceMapper := &resource.Mapper{ObjectTyper: typer, RESTMapper: mapper, ClientMapper: f.ClientMapperForCommand()}
|
||||
info, err := resourceMapper.InfoForObject(obj)
|
||||
if err != nil {
|
||||
return nil, "", nil, nil, err
|
||||
}
|
||||
|
||||
// Serialize the configuration into an annotation.
|
||||
if err := kubectl.UpdateApplyAnnotation(info); err != nil {
|
||||
return nil, "", nil, nil, err
|
||||
}
|
||||
|
||||
// Serialize the object with the annotation applied.
|
||||
data, err := mapping.Codec.Encode(info.Object)
|
||||
if err != nil {
|
||||
return nil, "", nil, nil, err
|
||||
}
|
||||
|
||||
obj, err = resource.NewHelper(client, mapping).Create(namespace, false, data)
|
||||
if err != nil {
|
||||
return nil, "", nil, nil, err
|
||||
}
|
||||
}
|
||||
return obj, kind, mapper, mapping, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user