This repository has been archived by the owner on Jan 13, 2023. It is now read-only.
/
generation.go
96 lines (83 loc) · 3.3 KB
/
generation.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
Copyright 2020 GramLabs, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generation
import (
"crypto/md5"
"fmt"
"io/ioutil"
"os"
"path/filepath"
redskyappsv1alpha1 "github.com/thestormforge/optimize-controller/api/apps/v1alpha1"
redskyv1beta1 "github.com/thestormforge/optimize-controller/api/v1beta1"
"github.com/thestormforge/optimize-controller/internal/application"
"github.com/yujunz/go-getter"
batchv1beta1 "k8s.io/api/batch/v1beta1"
corev1 "k8s.io/api/core/v1"
)
// newGoalMetric creates a new metric for the supplied goal with most fields pre-filled.
func newGoalMetric(obj *redskyappsv1alpha1.Goal, query string) redskyv1beta1.Metric {
defer func() { obj.Implemented = true }()
return redskyv1beta1.Metric{
Type: redskyv1beta1.MetricPrometheus,
Query: query,
Minimize: true,
Name: obj.Name,
Min: obj.Min,
Max: obj.Max,
Optimize: obj.Optimize,
}
}
// ensureTrialJobPod returns the pod template for the trial job, creating the job template if necessary.
func ensureTrialJobPod(exp *redskyv1beta1.Experiment) *corev1.PodTemplateSpec {
if exp.Spec.TrialTemplate.Spec.JobTemplate == nil {
exp.Spec.TrialTemplate.Spec.JobTemplate = &batchv1beta1.JobTemplateSpec{}
}
return &exp.Spec.TrialTemplate.Spec.JobTemplate.Spec.Template
}
// trialJobImage returns the image name for a type of job.
func trialJobImage(job string) string {
// Allow the image name to be overridden using environment variables, primarily for development work
imageName := os.Getenv("OPTIMIZE_TRIALS_IMAGE_REPOSITORY")
if imageName == "" {
imageName = "thestormforge/optimize-trials"
}
imageTag := os.Getenv("OPTIMIZE_TRIALS_IMAGE_TAG")
if imageTag == "" {
imageTagBase := os.Getenv("OPTIMIZE_TRIALS_IMAGE_TAG_BASE")
if imageTagBase == "" {
imageTagBase = "v0.0.1"
}
imageTag = imageTagBase + "-" + job
}
return imageName + ":" + imageTag
}
// loadApplicationData loads data (e.g. a supporting test file).
func loadApplicationData(app *redskyappsv1alpha1.Application, src string) ([]byte, error) {
dst := filepath.Join(os.TempDir(), fmt.Sprintf("load-application-data-%x", md5.Sum([]byte(src))))
defer os.Remove(dst)
// Only set the working directory to directory of the file the app.yaml was loaded from,
// we MUST NOT set this to the process working directory or relative paths in the app.yaml
// will be dependent on what directory you run the process from. If the path annotation is
// not present on the application, we MUST fail to load relative paths.
opts := []getter.ClientOption{
func(c *getter.Client) error {
c.Pwd = application.WorkingDirectory(app)
return nil
},
}
if err := getter.GetFile(dst, src, opts...); err != nil {
// TODO We need to be better about wrapping errors with more context here
return nil, fmt.Errorf("unable to load file: %w", err)
}
return ioutil.ReadFile(dst)
}