volcano.sh/volcano@v1.9.0/pkg/cli/vsub/run.go (about)

     1  /*
     2  Copyright 2018 The Volcano Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package vsub
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"os"
    23  
    24  	"github.com/google/shlex"
    25  	"github.com/spf13/cobra"
    26  
    27  	v1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  
    30  	vcbatch "volcano.sh/apis/pkg/apis/batch/v1alpha1"
    31  	"volcano.sh/apis/pkg/client/clientset/versioned"
    32  	"volcano.sh/volcano/pkg/cli/util"
    33  )
    34  
    35  type runFlags struct {
    36  	util.CommonFlags
    37  
    38  	Name      string
    39  	Namespace string
    40  	Image     string
    41  
    42  	MinAvailable  int
    43  	Replicas      int
    44  	Requests      string
    45  	Limits        string
    46  	SchedulerName string
    47  	FileName      string
    48  	Command       string
    49  }
    50  
    51  var launchJobFlags = &runFlags{}
    52  
    53  const (
    54  	// SchedulerNameEnv is the env name of default scheduler name.
    55  	SchedulerNameEnv = "VOLCANO_SCHEDULER_NAME"
    56  
    57  	// DefaultImageEnv is the env name of default image.
    58  	DefaultImageEnv = "VOLCANO_DEFAULT_IMAGE"
    59  
    60  	// DefaultJobNamespaceEnv is the env name of default namespace of the job
    61  	DefaultJobNamespaceEnv = "VOLCANO_DEFAULT_JOB_NAMESPACE"
    62  
    63  	defaultImage         = "busybox"
    64  	defaultSchedulerName = "volcano"
    65  	defaultJobNamespace  = "default"
    66  )
    67  
    68  // InitRunFlags init the run flags.
    69  func InitRunFlags(cmd *cobra.Command) {
    70  	util.InitFlags(cmd, &launchJobFlags.CommonFlags)
    71  
    72  	cmd.Flags().StringVarP(&launchJobFlags.Image, "image", "i", "",
    73  		fmt.Sprintf("the container image of job, overwrite the value of '%s' (default \"%s\")",
    74  			DefaultImageEnv, defaultImage))
    75  	cmd.Flags().StringVarP(&launchJobFlags.Namespace, "namespace", "N", "",
    76  		fmt.Sprintf("the namespace of job, overwrite the value of '%s' (default \"%s\")", DefaultJobNamespaceEnv, defaultJobNamespace))
    77  	cmd.Flags().StringVarP(&launchJobFlags.Name, "name", "n", "", "the name of job")
    78  	cmd.Flags().IntVarP(&launchJobFlags.MinAvailable, "min", "m", 1, "the minimal available tasks of job")
    79  	cmd.Flags().IntVarP(&launchJobFlags.Replicas, "replicas", "r", 1, "the total tasks of job")
    80  	cmd.Flags().StringVarP(&launchJobFlags.Requests, "requests", "R", "cpu=1000m,memory=100Mi", "the resource request of the task")
    81  	cmd.Flags().StringVarP(&launchJobFlags.Limits, "limits", "L", "cpu=1000m,memory=100Mi", "the resource limit of the task")
    82  	cmd.Flags().StringVarP(&launchJobFlags.SchedulerName, "scheduler", "S", "",
    83  		fmt.Sprintf("the scheduler for this job, overwrite the value of '%s' (default \"%s\")",
    84  			SchedulerNameEnv, defaultSchedulerName))
    85  	cmd.Flags().StringVarP(&launchJobFlags.Command, "command", "c", "", "the command of of job")
    86  
    87  	setDefaultArgs()
    88  }
    89  
    90  func setDefaultArgs() {
    91  	if launchJobFlags.SchedulerName == "" {
    92  		schedulerName := os.Getenv(SchedulerNameEnv)
    93  
    94  		if schedulerName != "" {
    95  			launchJobFlags.SchedulerName = schedulerName
    96  		} else {
    97  			launchJobFlags.SchedulerName = defaultSchedulerName
    98  		}
    99  	}
   100  
   101  	if launchJobFlags.Image == "" {
   102  		image := os.Getenv(DefaultImageEnv)
   103  
   104  		if image != "" {
   105  			launchJobFlags.Image = image
   106  		} else {
   107  			launchJobFlags.Image = defaultImage
   108  		}
   109  	}
   110  
   111  	if launchJobFlags.Namespace == "" {
   112  		namespace := os.Getenv(DefaultJobNamespaceEnv)
   113  
   114  		if namespace != "" {
   115  			launchJobFlags.Namespace = namespace
   116  		} else {
   117  			launchJobFlags.Namespace = defaultJobNamespace
   118  		}
   119  	}
   120  }
   121  
   122  var jobName = "job.volcano.sh"
   123  
   124  // RunJob creates the job.
   125  func RunJob() error {
   126  	config, err := util.BuildConfig(launchJobFlags.Master, launchJobFlags.Kubeconfig)
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	if launchJobFlags.Name == "" {
   132  		err = fmt.Errorf("job name cannot be left blank")
   133  		return err
   134  	}
   135  
   136  	req, err := util.PopulateResourceListV1(launchJobFlags.Requests)
   137  	if err != nil {
   138  		return err
   139  	}
   140  
   141  	limit, err := util.PopulateResourceListV1(launchJobFlags.Limits)
   142  	if err != nil {
   143  		return err
   144  	}
   145  
   146  	job, err := constructLaunchJobFlagsJob(launchJobFlags, req, limit)
   147  	if err != nil {
   148  		return err
   149  	}
   150  
   151  	jobClient := versioned.NewForConfigOrDie(config)
   152  	newJob, err := jobClient.BatchV1alpha1().Jobs(launchJobFlags.Namespace).Create(context.TODO(), job, metav1.CreateOptions{})
   153  	if err != nil {
   154  		return err
   155  	}
   156  
   157  	if newJob.Spec.Queue == "" {
   158  		newJob.Spec.Queue = "default"
   159  	}
   160  
   161  	fmt.Printf("run job %v successfully\n", newJob.Name)
   162  
   163  	return nil
   164  }
   165  
   166  func constructLaunchJobFlagsJob(launchJobFlags *runFlags, req, limit v1.ResourceList) (*vcbatch.Job, error) {
   167  	var commands []string
   168  
   169  	if launchJobFlags.Command != "" {
   170  		var err error
   171  		if commands, err = shlex.Split(launchJobFlags.Command); err != nil {
   172  			return nil, err
   173  		}
   174  	}
   175  
   176  	return &vcbatch.Job{
   177  		ObjectMeta: metav1.ObjectMeta{
   178  			Name:      launchJobFlags.Name,
   179  			Namespace: launchJobFlags.Namespace,
   180  		},
   181  		Spec: vcbatch.JobSpec{
   182  			MinAvailable:  int32(launchJobFlags.MinAvailable),
   183  			SchedulerName: launchJobFlags.SchedulerName,
   184  			Tasks: []vcbatch.TaskSpec{
   185  				{
   186  					Replicas: int32(launchJobFlags.Replicas),
   187  
   188  					Template: v1.PodTemplateSpec{
   189  						ObjectMeta: metav1.ObjectMeta{
   190  							Name:   launchJobFlags.Name,
   191  							Labels: map[string]string{jobName: launchJobFlags.Name},
   192  						},
   193  						Spec: v1.PodSpec{
   194  							RestartPolicy: v1.RestartPolicyNever,
   195  							Containers: []v1.Container{
   196  								{
   197  									Image:           launchJobFlags.Image,
   198  									Name:            launchJobFlags.Name,
   199  									ImagePullPolicy: v1.PullIfNotPresent,
   200  									Command:         commands,
   201  									Resources: v1.ResourceRequirements{
   202  										Limits:   limit,
   203  										Requests: req,
   204  									},
   205  								},
   206  							},
   207  						},
   208  					},
   209  				},
   210  			},
   211  		},
   212  	}, nil
   213  }