add resources requests and limits to nodePoolOptions

This commit is contained in:
rushtehrani
2020-07-02 22:29:05 -07:00
parent 18428c4e82
commit 2868ab69c9
4 changed files with 133 additions and 81 deletions

View File

@@ -2,92 +2,13 @@ package v1
import ( import (
"encoding/base64" "encoding/base64"
"fmt"
"github.com/onepanelio/core/pkg/util" "github.com/onepanelio/core/pkg/util"
"github.com/onepanelio/core/pkg/util/ptr"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
"strings"
) )
// SystemConfig is configuration loaded from kubernetes config and secrets that includes information about the
// database, server, etc.
type SystemConfig map[string]string
// GetValue returns the value in the underlying map if it exists, otherwise nil is returned
// If the value does not exist, it is also logged.
func (s SystemConfig) GetValue(name string) *string {
value, ok := s[name]
if !ok {
log.WithFields(log.Fields{
"Method": "SystemConfig.GetValue",
"Name": name,
"Error": "does not exist",
})
return nil
}
return &value
}
// Domain gets the ONEPANEL_DOMAIN value, or nil.
func (s SystemConfig) Domain() *string {
return s.GetValue("ONEPANEL_DOMAIN")
}
// APIURL gets the ONEPANEL_API_URL, or nil.
func (s SystemConfig) APIURL() *string {
return s.GetValue("ONEPANEL_API_URL")
}
// APIProtocol returns either http:// or https:// or nil.
// It is based on the ONEPANEL_API_URL config value and checks if it has https or http
func (s SystemConfig) APIProtocol() *string {
url := s.APIURL()
if url == nil {
return nil
}
if strings.HasPrefix(*url, "https://") {
return ptr.String("https://")
}
return ptr.String("http://")
}
// FQDN gets the ONEPANEL_FQDN value or nil.
func (s SystemConfig) FQDN() *string {
return s.GetValue("ONEPANEL_FQDN")
}
// NodePoolLabel gets the applicationNodePoolLabel from the config or returns nil.
func (s SystemConfig) NodePoolLabel() (label *string) {
return s.GetValue("applicationNodePoolLabel")
}
// NodePoolOptions loads and parses the applicationNodePoolOptions from the config.
// If there is no data, an error is returned.
func (s SystemConfig) NodePoolOptions() (options []*ParameterOption, err error) {
data := s.GetValue("applicationNodePoolOptions")
if data == nil {
return nil, fmt.Errorf("no nodePoolOptions in config")
}
if err = yaml.Unmarshal([]byte(*data), &options); err != nil {
return
}
return
}
// DatabaseDriverName gets the databaseDriverName value, or nil.
func (s SystemConfig) DatabaseDriverName() *string {
return s.GetValue("databaseDriverName")
}
func (c *Client) getConfigMap(namespace, name string) (configMap *ConfigMap, err error) { func (c *Client) getConfigMap(namespace, name string) (configMap *ConfigMap, err error) {
cm, err := c.CoreV1().ConfigMaps(namespace).Get(name, metav1.GetOptions{}) cm, err := c.CoreV1().ConfigMaps(namespace).Get(name, metav1.GetOptions{})
if err != nil { if err != nil {

View File

@@ -1,10 +1,109 @@
package v1 package v1
import ( import (
"fmt"
"github.com/onepanelio/core/pkg/util/ptr"
log "github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/yaml"
"strings" "strings"
) )
// SystemConfig is configuration loaded from kubernetes config and secrets that includes information about the
// database, server, etc.
type SystemConfig map[string]string
type NodePoolOption struct {
ParameterOption
Resources corev1.ResourceRequirements
}
// GetValue returns the value in the underlying map if it exists, otherwise nil is returned
// If the value does not exist, it is also logged.
func (s SystemConfig) GetValue(name string) *string {
value, ok := s[name]
if !ok {
log.WithFields(log.Fields{
"Method": "SystemConfig.GetValue",
"Name": name,
"Error": "does not exist",
})
return nil
}
return &value
}
// Domain gets the ONEPANEL_DOMAIN value, or nil.
func (s SystemConfig) Domain() *string {
return s.GetValue("ONEPANEL_DOMAIN")
}
// APIURL gets the ONEPANEL_API_URL, or nil.
func (s SystemConfig) APIURL() *string {
return s.GetValue("ONEPANEL_API_URL")
}
// APIProtocol returns either http:// or https:// or nil.
// It is based on the ONEPANEL_API_URL config value and checks if it has https or http
func (s SystemConfig) APIProtocol() *string {
url := s.APIURL()
if url == nil {
return nil
}
if strings.HasPrefix(*url, "https://") {
return ptr.String("https://")
}
return ptr.String("http://")
}
// FQDN gets the ONEPANEL_FQDN value or nil.
func (s SystemConfig) FQDN() *string {
return s.GetValue("ONEPANEL_FQDN")
}
// NodePoolLabel gets the applicationNodePoolLabel from the config or returns nil.
func (s SystemConfig) NodePoolLabel() (label *string) {
return s.GetValue("applicationNodePoolLabel")
}
// NodePoolOptions loads and parses the applicationNodePoolOptions from the config.
// If there is no data, an error is returned.
func (s SystemConfig) NodePoolOptions() (options []*NodePoolOption, err error) {
data := s.GetValue("applicationNodePoolOptions")
if data == nil {
return nil, fmt.Errorf("no nodePoolOptions in config")
}
if err = yaml.Unmarshal([]byte(*data), &options); err != nil {
return
}
return
}
func (s SystemConfig) NodePoolOptionByValue(value string) (option *NodePoolOption, err error) {
options, err := s.NodePoolOptions()
if err != nil {
return
}
for _, opt := range options {
if opt.Value == value {
option = opt
return
}
}
return
}
// DatabaseDriverName gets the databaseDriverName value, or nil.
func (s SystemConfig) DatabaseDriverName() *string {
return s.GetValue("databaseDriverName")
}
type ArtifactRepositoryS3Config struct { type ArtifactRepositoryS3Config struct {
KeyFormat string KeyFormat string
Bucket string Bucket string

View File

@@ -104,6 +104,7 @@ func injectArtifactRepositoryConfig(artifact *wfv1.Artifact, namespaceConfig *Na
} }
} }
// injectNvidiaGPUFields adds GPU specific fields if there is a GPU request
func injectNvidiaGPUFields(template *wfv1.Template, systemConfig SystemConfig) { func injectNvidiaGPUFields(template *wfv1.Template, systemConfig SystemConfig) {
limitsGPUCount := template.Container.Resources.Limits["nvidia.com/gpu"] limitsGPUCount := template.Container.Resources.Limits["nvidia.com/gpu"]
requestsGPUCount := template.Container.Resources.Requests["nvidia.com/gpu"] requestsGPUCount := template.Container.Resources.Requests["nvidia.com/gpu"]
@@ -129,6 +130,29 @@ func injectNvidiaGPUFields(template *wfv1.Template, systemConfig SystemConfig) {
} }
} }
// injectNodeSelectorResources adds resource requests and limits if they exist
func injectNodeSelectorResources(template *wfv1.Template, systemConfig SystemConfig) {
if template.NodeSelector == nil {
return
}
var (
option *NodePoolOption
err error
)
for k, v := range template.NodeSelector {
if k == *systemConfig.NodePoolLabel() {
option, err = systemConfig.NodePoolOptionByValue(v)
if err != nil {
return
}
}
}
if option != nil && (option.Resources.Requests != nil || option.Resources.Limits != nil) {
template.Container.Resources = option.Resources
}
}
func (c *Client) injectAutomatedFields(namespace string, wf *wfv1.Workflow, opts *WorkflowExecutionOptions) (err error) { func (c *Client) injectAutomatedFields(namespace string, wf *wfv1.Workflow, opts *WorkflowExecutionOptions) (err error) {
if opts.PodGCStrategy == nil { if opts.PodGCStrategy == nil {
if wf.Spec.PodGC == nil { if wf.Spec.PodGC == nil {
@@ -209,6 +233,7 @@ func (c *Client) injectAutomatedFields(namespace string, wf *wfv1.Workflow, opts
template.Inputs.Artifacts[j] = artifact template.Inputs.Artifacts[j] = artifact
} }
injectNodeSelectorResources(template, systemConfig)
injectNvidiaGPUFields(template, systemConfig) injectNvidiaGPUFields(template, systemConfig)
//Generate ENV vars from secret, if there is a container present in the workflow //Generate ENV vars from secret, if there is a container present in the workflow

View File

@@ -84,13 +84,20 @@ func generateRuntimeParameters(config SystemConfig) (parameters []Parameter, err
}) })
// Node pool parameter and options // Node pool parameter and options
options, err := config.NodePoolOptions() nodePoolOptions, err := config.NodePoolOptions()
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(options) == 0 { if len(nodePoolOptions) == 0 {
return nil, fmt.Errorf("no node pool options in config") return nil, fmt.Errorf("no node pool options in config")
} }
var options []*ParameterOption
for _, option := range nodePoolOptions {
options = append(options, &ParameterOption{
Name: option.Name,
Value: option.Value,
})
}
parameters = append(parameters, Parameter{ parameters = append(parameters, Parameter{
Name: "sys-node-pool-label", Name: "sys-node-pool-label",