volcano.sh/volcano@v1.9.0/pkg/cli/job/util.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 job 18 19 import ( 20 "context" 21 "fmt" 22 "os" 23 "strings" 24 "time" 25 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 28 v1 "k8s.io/api/core/v1" 29 "k8s.io/apimachinery/pkg/api/resource" 30 "k8s.io/client-go/rest" 31 32 vcbus "volcano.sh/apis/pkg/apis/bus/v1alpha1" 33 "volcano.sh/apis/pkg/apis/helpers" 34 "volcano.sh/apis/pkg/client/clientset/versioned" 35 ) 36 37 func homeDir() string { 38 if h := os.Getenv("HOME"); h != "" { 39 return h 40 } 41 return os.Getenv("USERPROFILE") // windows 42 } 43 44 // populateResourceListV1 takes strings of form <resourceName1>=<value1>,<resourceName2>=<value2> 45 // and returns ResourceList. 46 func populateResourceListV1(spec string) (v1.ResourceList, error) { 47 // empty input gets a nil response to preserve generator test expected behaviors 48 if spec == "" { 49 return nil, nil 50 } 51 52 result := v1.ResourceList{} 53 resourceStatements := strings.Split(spec, ",") 54 for _, resourceStatement := range resourceStatements { 55 parts := strings.Split(resourceStatement, "=") 56 if len(parts) != 2 { 57 return nil, fmt.Errorf("invalid argument syntax %v, expected <resource>=<value>", resourceStatement) 58 } 59 resourceName := v1.ResourceName(parts[0]) 60 resourceQuantity, err := resource.ParseQuantity(parts[1]) 61 if err != nil { 62 return nil, err 63 } 64 result[resourceName] = resourceQuantity 65 } 66 return result, nil 67 } 68 69 func createJobCommand(config *rest.Config, ns, name string, action vcbus.Action) error { 70 jobClient := versioned.NewForConfigOrDie(config) 71 job, err := jobClient.BatchV1alpha1().Jobs(ns).Get(context.TODO(), name, metav1.GetOptions{}) 72 if err != nil { 73 return err 74 } 75 76 ctrlRef := metav1.NewControllerRef(job, helpers.JobKind) 77 cmd := &vcbus.Command{ 78 ObjectMeta: metav1.ObjectMeta{ 79 GenerateName: fmt.Sprintf("%s-%s-", 80 job.Name, strings.ToLower(string(action))), 81 Namespace: job.Namespace, 82 OwnerReferences: []metav1.OwnerReference{ 83 *ctrlRef, 84 }, 85 }, 86 TargetObject: ctrlRef, 87 Action: string(action), 88 } 89 90 if _, err := jobClient.BusV1alpha1().Commands(ns).Create(context.TODO(), cmd, metav1.CreateOptions{}); err != nil { 91 return err 92 } 93 94 return nil 95 } 96 97 func translateTimestampSince(timestamp metav1.Time) string { 98 if timestamp.IsZero() { 99 return "<unknown>" 100 } 101 return HumanDuration(time.Since(timestamp.Time)) 102 } 103 104 // HumanDuration translate time.Duration to human readable time string. 105 func HumanDuration(d time.Duration) string { 106 // Allow deviation no more than 2 seconds(excluded) to tolerate machine time 107 // inconsistence, it can be considered as almost now. 108 if seconds := int(d.Seconds()); seconds < -1 { 109 return "<invalid>" 110 } else if seconds < 0 { 111 return "0s" 112 } else if seconds < 60*2 { 113 return fmt.Sprintf("%ds", seconds) 114 } 115 minutes := int(d / time.Minute) 116 if minutes < 10 { 117 s := int(d/time.Second) % 60 118 if s == 0 { 119 return fmt.Sprintf("%dm", minutes) 120 } 121 return fmt.Sprintf("%dm%ds", minutes, s) 122 } else if minutes < 60*3 { 123 return fmt.Sprintf("%dm", minutes) 124 } 125 hours := int(d / time.Hour) 126 if hours < 8 { 127 m := int(d/time.Minute) % 60 128 if m == 0 { 129 return fmt.Sprintf("%dh", hours) 130 } 131 return fmt.Sprintf("%dh%dm", hours, m) 132 } else if hours < 48 { 133 return fmt.Sprintf("%dh", hours) 134 } else if hours < 24*8 { 135 h := hours % 24 136 if h == 0 { 137 return fmt.Sprintf("%dd", hours/24) 138 } 139 return fmt.Sprintf("%dd%dh", hours/24, h) 140 } else if hours < 24*365*2 { 141 return fmt.Sprintf("%dd", hours/24) 142 } else if hours < 24*365*8 { 143 return fmt.Sprintf("%dy%dd", hours/24/365, (hours/24)%365) 144 } 145 return fmt.Sprintf("%dy", hours/24/365) 146 }