Skip to content

Commit ee9301c

Browse files
author
Oleg Sucharevich
authored
Acceptance test (#112)
* add acceptance test during installation
1 parent 5a07279 commit ee9301c

File tree

8 files changed

+172
-42
lines changed

8 files changed

+172
-42
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "venona",
3-
"version": "1.0.8",
3+
"version": "1.1.0",
44
"description": "Codefresh agent to run on Codefresh's runtime environment and execute pipeline",
55
"main": "index.js",
66
"scripts": {

venonactl/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.0.8
1+
1.1.0

venonactl/cmd/install-agent.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ var installAgentCmdOptions struct {
3737
venona struct {
3838
version string
3939
}
40-
agentToken string
41-
agentID string
42-
kubernetesRunnerType bool
43-
tolerations string
40+
agentToken string
41+
agentID string
42+
kubernetesRunnerType bool
43+
tolerations string
44+
skipClusterAcceptanceTest bool
4445
}
4546

4647
var installAgentCmd = &cobra.Command{
@@ -54,12 +55,12 @@ var installAgentCmd = &cobra.Command{
5455
extendStoreWithKubeClient(lgr)
5556
fillCodefreshAPI(lgr)
5657
builder := plugins.NewBuilder(lgr)
57-
5858
if cfAPIHost == "" {
5959
cfAPIHost = "https://g.codefresh.io"
6060
}
6161
builderInstallOpt := &plugins.InstallOptions{
62-
CodefreshHost: cfAPIHost,
62+
CodefreshHost: cfAPIHost,
63+
SkipAcceptanceTest: installAgentCmdOptions.skipClusterAcceptanceTest,
6364
}
6465

6566
if installAgentCmdOptions.agentToken == "" {
@@ -115,7 +116,6 @@ var installAgentCmd = &cobra.Command{
115116
}
116117
}
117118
lgr.Info("Agent installation completed Successfully")
118-
119119
},
120120
}
121121

@@ -135,6 +135,7 @@ func init() {
135135
installAgentCmd.Flags().BoolVar(&installAgentCmdOptions.kube.inCluster, "in-cluster", false, "Set flag if venona is been installed from inside a cluster")
136136
installAgentCmd.Flags().BoolVar(&installAgentCmdOptions.dryRun, "dry-run", false, "Set to true to simulate installation")
137137
installAgentCmd.Flags().BoolVar(&installAgentCmdOptions.kubernetesRunnerType, "kubernetes-runner-type", false, "Set the runner type to kubernetes (alpha feature)")
138+
installAgentCmd.Flags().BoolVar(&installAgentCmdOptions.skipClusterAcceptanceTest, "skip-cluster-test", false, "Do not run cluster acceptance test")
138139
}
139140

140141
func fillCodefreshAPI(logger logger.Logger) {

venonactl/cmd/install-runtime.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,18 @@ var installRuntimeCmdOptions struct {
2929
codefreshToken string
3030
dryRun bool
3131
kube struct {
32-
namespace string
33-
inCluster bool
34-
context string
32+
namespace string
33+
inCluster bool
34+
context string
3535
nodeSelector string
3636
}
37-
storageClass string
38-
runtimeEnvironmentName string
39-
kubernetesRunnerType bool
40-
tolerations string
41-
templateValues []string
42-
templateFileValues []string
37+
storageClass string
38+
runtimeEnvironmentName string
39+
kubernetesRunnerType bool
40+
tolerations string
41+
templateValues []string
42+
templateFileValues []string
43+
skipClusterAcceptanceTest bool
4344
}
4445

4546
var installRuntimeCmd = &cobra.Command{
@@ -99,6 +100,7 @@ var installRuntimeCmd = &cobra.Command{
99100
CodefreshToken: installRuntimeCmdOptions.codefreshToken,
100101
RuntimeEnvironment: installRuntimeCmdOptions.runtimeEnvironmentName,
101102
ClusterNamespace: installRuntimeCmdOptions.kube.namespace,
103+
SkipAcceptanceTest: installRuntimeCmdOptions.skipClusterAcceptanceTest,
102104
}
103105

104106
if installRuntimeCmdOptions.kubernetesRunnerType {
@@ -176,5 +178,6 @@ func init() {
176178

177179
installRuntimeCmd.Flags().StringArrayVar(&installRuntimeCmdOptions.templateValues, "set-value", []string{}, "Set values for templates, example: --set-value LocalVolumesDir=/mnt/disks/ssd0/codefresh-volumes")
178180
installRuntimeCmd.Flags().StringArrayVar(&installRuntimeCmdOptions.templateFileValues, "set-file", []string{}, "Set values for templates from file, example: --set-file Storage.GoogleServiceAccount=/path/to/service-account.json")
181+
installRuntimeCmd.Flags().BoolVar(&installRuntimeCmdOptions.skipClusterAcceptanceTest, "skip-cluster-test", false, "Do not run cluster acceptance test")
179182

180183
}

venonactl/pkg/plugins/helper.go

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,40 @@ package plugins
1818

1919
import (
2020
"bytes"
21+
"errors"
2122
"fmt"
2223
"html/template"
2324
"regexp"
2425
"strings"
2526

2627
// import all cloud providers auth clients
28+
v1 "k8s.io/api/core/v1"
29+
"k8s.io/client-go/kubernetes"
2730
_ "k8s.io/client-go/plugin/pkg/client/auth"
2831

2932
"github.com/Masterminds/sprig"
3033
"github.com/codefresh-io/venona/venonactl/pkg/logger"
3134
templates "github.com/codefresh-io/venona/venonactl/pkg/templates/kubernetes"
3235

36+
"k8s.io/apimachinery/pkg/api/resource"
37+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3338
"k8s.io/apimachinery/pkg/runtime"
3439
"k8s.io/client-go/kubernetes/scheme"
3540
)
3641

42+
type (
43+
validationResult struct {
44+
isValid bool
45+
message []string
46+
}
47+
48+
validationRequest struct {
49+
cpu string
50+
localDiskMinimumSize string
51+
momorySize string
52+
}
53+
)
54+
3755
func unescape(s string) template.HTML {
3856
return template.HTML(s)
3957
}
@@ -42,7 +60,7 @@ func unescape(s string) template.HTML {
4260
func nodeSelectorParamToYaml(ns string) string {
4361
nodeSelectorParts := strings.Split(ns, ",")
4462
var nodeSelectorYaml string
45-
for _, p := range(nodeSelectorParts){
63+
for _, p := range nodeSelectorParts {
4664
pSplit := strings.Split(p, "=")
4765
if len(pSplit) != 2 {
4866
continue
@@ -59,9 +77,9 @@ func nodeSelectorParamToYaml(ns string) string {
5977
// ExecuteTemplate - executes templates in tpl str with config as values
6078
func ExecuteTemplate(tplStr string, data interface{}) (string, error) {
6179
funcMap := template.FuncMap{
62-
"unescape": unescape,
63-
"nodeSelectorParamToYaml": nodeSelectorParamToYaml,
64-
}
80+
"unescape": unescape,
81+
"nodeSelectorParamToYaml": nodeSelectorParamToYaml,
82+
}
6583
template, err := template.New("base").Funcs(sprig.FuncMap()).Funcs(funcMap).Parse(tplStr)
6684
if err != nil {
6785
return "", err
@@ -130,3 +148,68 @@ func getKubeObjectsFromTempalte(values map[string]interface{}, pattern string, l
130148
templatesMap := templates.TemplatesMap()
131149
return KubeObjectsFromTemplates(templatesMap, values, pattern, logger)
132150
}
151+
152+
func ensureClusterRequirements(client *kubernetes.Clientset, req validationRequest) (validationResult, error) {
153+
result := validationResult{}
154+
nodes, err := client.CoreV1().Nodes().List(metav1.ListOptions{})
155+
if err != nil {
156+
return result, err
157+
}
158+
if nodes == nil {
159+
return result, errors.New("Nodes not found")
160+
}
161+
162+
result.isValid = true
163+
if len(nodes.Items) == 0 {
164+
result.message = append(result.message, "No nodes in cluster")
165+
result.isValid = false
166+
}
167+
168+
atLeastOneMet := false
169+
for _, n := range nodes.Items {
170+
res := testNode(n, req)
171+
if len(res) > 0 {
172+
result.message = append(result.message, res...)
173+
} else {
174+
atLeastOneMet = true
175+
}
176+
}
177+
if !atLeastOneMet {
178+
result.isValid = false
179+
return result, nil
180+
}
181+
return result, nil
182+
}
183+
184+
func testNode(n v1.Node, req validationRequest) []string {
185+
result := []string{}
186+
187+
if req.cpu != "" {
188+
requiredCPU, err := resource.ParseQuantity(req.cpu)
189+
if err != nil {
190+
result = append(result, err.Error())
191+
return result
192+
}
193+
cpu := n.Status.Capacity.Cpu()
194+
195+
if cpu != nil && cpu.Cmp(requiredCPU) == -1 {
196+
msg := fmt.Sprintf("Insufficiant CPU on node %s, current: %s - required: %s", n.GetObjectMeta().GetName(), cpu.String(), requiredCPU.String())
197+
result = append(result, msg)
198+
}
199+
}
200+
201+
if req.momorySize != "" {
202+
requiredMemory, err := resource.ParseQuantity(req.momorySize)
203+
if err != nil {
204+
result = append(result, err.Error())
205+
return result
206+
}
207+
memory := n.Status.Capacity.Memory()
208+
if memory != nil && memory.Cmp(requiredMemory) == -1 {
209+
msg := fmt.Sprintf("Insufficiant Memory on node %s, current: %s - required: %s", n.GetObjectMeta().GetName(), memory.String(), requiredMemory.String())
210+
result = append(result, msg)
211+
}
212+
}
213+
214+
return result
215+
}

venonactl/pkg/plugins/plugin.go

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const (
1717
VolumeProvisionerPluginType = "volume-provisioner"
1818
EnginePluginType = "engine"
1919
DefaultStorageClassNamePrefix = "dind-local-volumes-venona"
20-
RuntimeAttachType = "runtime-attach"
20+
RuntimeAttachType = "runtime-attach"
2121
)
2222

2323
type (
@@ -56,35 +56,34 @@ type (
5656
KubeBuilder interface {
5757
BuildClient() (*kubernetes.Clientset, error)
5858
BuildConfig() clientcmd.ClientConfig
59-
EnsureNamespaceExists(cs *kubernetes.Clientset) (error)
60-
59+
EnsureNamespaceExists(cs *kubernetes.Clientset) error
6160
}
62-
AgentKubeBuilder interface {
61+
AgentKubeBuilder interface {
6362
BuildClient() (*kubernetes.Clientset, error)
64-
EnsureNamespaceExists(cs *kubernetes.Clientset) (error)
63+
EnsureNamespaceExists(cs *kubernetes.Clientset) error
6564
}
66-
DryRun bool
67-
KubernetesRunnerType bool
68-
BuildNodeSelector map[string]string
69-
Annotations map[string]string
70-
RuntimeEnvironment string
71-
RuntimeClusterName string
65+
DryRun bool
66+
KubernetesRunnerType bool
67+
BuildNodeSelector map[string]string
68+
Annotations map[string]string
69+
RuntimeEnvironment string
70+
RuntimeClusterName string
7271
RuntimeServiceAccount string
73-
RestartAgent bool
72+
RestartAgent bool
73+
SkipAcceptanceTest bool
7474
}
7575

7676
DeleteOptions struct {
7777
KubeBuilder interface {
7878
BuildClient() (*kubernetes.Clientset, error)
7979
}
80-
AgentKubeBuilder interface {
80+
AgentKubeBuilder interface {
8181
BuildClient() (*kubernetes.Clientset, error)
8282
}
83-
ClusterNamespace string // runtime
84-
AgentNamespace string // agent
85-
RuntimeEnvironment string
86-
RestartAgent bool
87-
83+
ClusterNamespace string // runtime
84+
AgentNamespace string // agent
85+
RuntimeEnvironment string
86+
RestartAgent bool
8887
}
8988

9089
UpgradeOptions struct {

venonactl/pkg/plugins/runtime-environment.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package plugins
1818

1919
import (
2020
"encoding/base64"
21+
"errors"
2122
"fmt"
2223

2324
"github.com/codefresh-io/venona/venonactl/pkg/codefresh"
@@ -40,7 +41,7 @@ func (u *runtimeEnvironmentPlugin) Install(opt *InstallOptions, v Values) (Value
4041
if err != nil {
4142
return nil, fmt.Errorf("Cannot create kubernetes clientset: %v ", err)
4243
}
43-
44+
4445
err = opt.KubeBuilder.EnsureNamespaceExists(cs)
4546
if err != nil {
4647
u.logger.Error(fmt.Sprintf("Cannot ensure namespace exists: %v", err))
@@ -83,6 +84,27 @@ func (u *runtimeEnvironmentPlugin) Install(opt *InstallOptions, v Values) (Value
8384
return nil, err
8485
}
8586

87+
if !opt.SkipAcceptanceTest {
88+
u.logger.Debug("Running acceptance tests")
89+
res, err := ensureClusterRequirements(cs, validationRequest{
90+
cpu: "1",
91+
momorySize: "1Gi",
92+
})
93+
if err != nil {
94+
return nil, err
95+
}
96+
if !res.isValid {
97+
for _, m := range res.message {
98+
u.logger.Error(m)
99+
}
100+
return nil, errors.New("Failed to run acceptance test on cluster")
101+
}
102+
103+
for _, m := range res.message {
104+
u.logger.Warn(m)
105+
}
106+
}
107+
86108
v["RuntimeEnvironment"] = opt.RuntimeEnvironment
87109
err = install(&installOptions{
88110
logger: u.logger,

venonactl/pkg/plugins/venona.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package plugins
1818

1919
import (
2020
"encoding/base64"
21+
"errors"
2122
"fmt"
2223
"time"
2324

@@ -39,7 +40,7 @@ const (
3940

4041
// Install venona agent
4142
func (u *venonaPlugin) Install(opt *InstallOptions, v Values) (Values, error) {
42-
if v["AgentToken"] == "" {
43+
if v["AgentToken"] == "" {
4344
u.logger.Debug("Generating token for agent")
4445
tokenName := fmt.Sprintf("generated-%s", time.Now().Format("20060102150405"))
4546
u.logger.Debug(fmt.Sprintf("Token candidate name: %s", tokenName))
@@ -72,6 +73,27 @@ func (u *venonaPlugin) Install(opt *InstallOptions, v Values) (Values, error) {
7273
u.logger.Error(fmt.Sprintf("Cannot ensure namespace exists: %v", err))
7374
return nil, err
7475
}
76+
if !opt.SkipAcceptanceTest {
77+
u.logger.Debug("Running acceptance tests")
78+
res, err := ensureClusterRequirements(cs, validationRequest{
79+
cpu: "500m",
80+
momorySize: "1Gi",
81+
})
82+
if err != nil {
83+
return nil, err
84+
}
85+
if !res.isValid {
86+
for _, m := range res.message {
87+
u.logger.Error(m)
88+
}
89+
return nil, errors.New("Failed to run acceptance test on cluster")
90+
}
91+
92+
for _, m := range res.message {
93+
u.logger.Warn(m)
94+
}
95+
}
96+
7597
return v, install(&installOptions{
7698
logger: u.logger,
7799
templates: templates.TemplatesMap(),

0 commit comments

Comments
 (0)