Skip to content

Commit 386efa1

Browse files
authored
[Feature] Scheduler CLI (#1624)
1 parent e5ae994 commit 386efa1

File tree

7 files changed

+714
-0
lines changed

7 files changed

+714
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
- (Feature) ArangoProfile Selectors
1313
- (Bugfix) Remove ImagePullSecrets Reference from Container
1414
- (Feature) DebugPackage ArangoProfiles
15+
- (Feature) Scheduler CLI
1516

1617
## [1.2.39](https://github.com/arangodb/kube-arangodb/tree/1.2.39) (2024-03-11)
1718
- (Feature) Extract Scheduler API

cmd/scheduler.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
21+
package cmd
22+
23+
import (
24+
"github.com/spf13/cobra"
25+
26+
"github.com/arangodb/kube-arangodb/pkg/scheduler"
27+
)
28+
29+
func init() {
30+
cmd := &cobra.Command{
31+
Use: "scheduler",
32+
}
33+
34+
if err := scheduler.InitCommand(cmd); err != nil {
35+
panic(err.Error())
36+
}
37+
38+
cmdMain.AddCommand(cmd)
39+
}

pkg/scheduler/cli.go

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
21+
package scheduler
22+
23+
import (
24+
"context"
25+
"os"
26+
"strings"
27+
28+
"github.com/spf13/cobra"
29+
"sigs.k8s.io/yaml"
30+
31+
"github.com/arangodb/kube-arangodb/pkg/logging"
32+
"github.com/arangodb/kube-arangodb/pkg/util"
33+
"github.com/arangodb/kube-arangodb/pkg/util/constants"
34+
"github.com/arangodb/kube-arangodb/pkg/util/errors"
35+
"github.com/arangodb/kube-arangodb/pkg/util/kclient"
36+
)
37+
38+
func InitCommand(cmd *cobra.Command) error {
39+
var c cli
40+
return c.register(cmd)
41+
}
42+
43+
type cli struct {
44+
Namespace string
45+
46+
Labels []string
47+
Envs []string
48+
49+
Profiles []string
50+
51+
Container string
52+
53+
Image string
54+
}
55+
56+
func (c *cli) asRequest(args ...string) (Request, error) {
57+
var r = Request{
58+
Labels: map[string]string{},
59+
Envs: map[string]string{},
60+
}
61+
62+
for _, l := range c.Labels {
63+
p := strings.SplitN(l, "=", 2)
64+
if len(p) == 1 {
65+
r.Labels[p[0]] = ""
66+
logger.Debug("Label Discovered: %s", p[0])
67+
} else {
68+
r.Labels[p[0]] = p[1]
69+
logger.Debug("Label Discovered: %s=%s", p[0], p[1])
70+
}
71+
}
72+
73+
for _, l := range c.Envs {
74+
p := strings.SplitN(l, "=", 2)
75+
if len(p) == 1 {
76+
return r, errors.Errorf("Missing value for env: %s", p[0])
77+
} else {
78+
r.Envs[p[0]] = p[1]
79+
logger.Debug("Env Discovered: %s=%s", p[0], p[1])
80+
}
81+
}
82+
83+
if len(c.Profiles) > 0 {
84+
r.Profiles = c.Profiles
85+
logger.Debug("Enabling profiles: %s", strings.Join(c.Profiles, ", "))
86+
}
87+
88+
r.Container = util.NewType(c.Container)
89+
if c.Image != "" {
90+
r.Image = util.NewType(c.Image)
91+
}
92+
93+
r.Args = args
94+
95+
return r, nil
96+
}
97+
98+
func (c *cli) register(cmd *cobra.Command) error {
99+
if err := logging.Init(cmd); err != nil {
100+
return err
101+
}
102+
103+
cmd.RunE = c.run
104+
105+
f := cmd.PersistentFlags()
106+
107+
f.StringVarP(&c.Namespace, "namespace", "n", constants.NamespaceWithDefault("default"), "Kubernetes namespace")
108+
f.StringSliceVarP(&c.Labels, "label", "l", nil, "Scheduler Render Labels in format <key>=<value>")
109+
f.StringSliceVarP(&c.Envs, "env", "e", nil, "Scheduler Render Envs in format <key>=<value>")
110+
f.StringSliceVarP(&c.Profiles, "profile", "p", nil, "Scheduler Render Profiles")
111+
f.StringVar(&c.Container, "container", DefaultContainerName, "Container Name")
112+
f.StringVar(&c.Image, "image", "", "Image")
113+
114+
return nil
115+
}
116+
117+
func (c *cli) run(cmd *cobra.Command, args []string) error {
118+
if err := logging.Enable(); err != nil {
119+
return err
120+
}
121+
122+
r, err := c.asRequest()
123+
if err != nil {
124+
return err
125+
}
126+
127+
k, ok := kclient.GetDefaultFactory().Client()
128+
if !ok {
129+
return errors.Errorf("Unable to create Kubernetes Client")
130+
}
131+
132+
s := NewScheduler(k, c.Namespace)
133+
134+
rendered, profiles, err := s.Render(context.Background(), r)
135+
if err != nil {
136+
return err
137+
}
138+
logger.Debug("Enabled profiles: %s", strings.Join(profiles, ", "))
139+
140+
data, err := yaml.Marshal(rendered)
141+
if err != nil {
142+
return err
143+
}
144+
145+
if _, err := util.WriteAll(os.Stdout, data); err != nil {
146+
return err
147+
}
148+
149+
return nil
150+
}

pkg/scheduler/input.go

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
21+
package scheduler
22+
23+
import (
24+
"math"
25+
26+
core "k8s.io/api/core/v1"
27+
28+
schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1alpha1"
29+
schedulerContainerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1alpha1/container"
30+
schedulerContainerResourcesApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1alpha1/container/resources"
31+
schedulerPodApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1alpha1/pod"
32+
schedulerPodResourcesApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1alpha1/pod/resources"
33+
"github.com/arangodb/kube-arangodb/pkg/util"
34+
)
35+
36+
const DefaultContainerName = "job"
37+
38+
type Request struct {
39+
Labels map[string]string
40+
41+
Profiles []string
42+
43+
Envs map[string]string
44+
45+
Container *string
46+
47+
Image *string
48+
49+
Args []string
50+
}
51+
52+
func (r Request) AsTemplate() *schedulerApi.ProfileTemplate {
53+
var container schedulerContainerApi.Container
54+
55+
if len(r.Envs) > 0 {
56+
container.Environments = &schedulerContainerResourcesApi.Environments{}
57+
58+
for k, v := range r.Envs {
59+
container.Environments.Env = append(container.Environments.Env, core.EnvVar{
60+
Name: k,
61+
Value: v,
62+
})
63+
}
64+
}
65+
66+
if len(r.Args) > 0 {
67+
container.Core = &schedulerContainerResourcesApi.Core{
68+
Args: r.Args,
69+
}
70+
}
71+
72+
if r.Image != nil {
73+
container.Image = &schedulerContainerResourcesApi.Image{
74+
Image: util.NewType(util.TypeOrDefault(r.Image)),
75+
}
76+
}
77+
78+
return &schedulerApi.ProfileTemplate{
79+
Priority: util.NewType(math.MaxInt),
80+
Pod: &schedulerPodApi.Pod{
81+
Metadata: &schedulerPodResourcesApi.Metadata{
82+
Labels: util.MergeMaps(true, r.Labels),
83+
},
84+
},
85+
Container: &schedulerApi.ProfileContainerTemplate{
86+
Containers: map[string]schedulerContainerApi.Container{
87+
util.TypeOrDefault(r.Container, DefaultContainerName): container,
88+
},
89+
},
90+
}
91+
}

pkg/scheduler/logger.go

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
21+
package scheduler
22+
23+
import "github.com/arangodb/kube-arangodb/pkg/logging"
24+
25+
var logger = logging.Global().RegisterAndGetLogger("scheduler", logging.Info)

0 commit comments

Comments
 (0)