Skip to content

Commit

Permalink
add test cluster cmd (#142)
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleg Sucharevich authored Jun 2, 2020
1 parent dd11b74 commit 1468792
Show file tree
Hide file tree
Showing 14 changed files with 462 additions and 79 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ venonactl/dist/*
venonactl-linux
venonalog.json
.venonaconf
.cover
configdir
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "venona",
"version": "1.2.17",
"version": "1.3.0",
"description": "Codefresh agent to run on Codefresh's runtime environment and execute pipeline",
"main": "index.js",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion venonactl/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.2.17
1.3.0
13 changes: 5 additions & 8 deletions venonactl/cmd/install-agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ var installAgentCmdOptions struct {
venona struct {
version string
}
agentToken string
agentID string
kubernetesRunnerType bool
tolerations string
skipClusterAcceptanceTest bool
agentToken string
agentID string
kubernetesRunnerType bool
tolerations string
}

var installAgentCmd = &cobra.Command{
Expand All @@ -59,8 +58,7 @@ var installAgentCmd = &cobra.Command{
cfAPIHost = "https://g.codefresh.io"
}
builderInstallOpt := &plugins.InstallOptions{
CodefreshHost: cfAPIHost,
SkipAcceptanceTest: installAgentCmdOptions.skipClusterAcceptanceTest,
CodefreshHost: cfAPIHost,
}

if installAgentCmdOptions.agentToken == "" {
Expand Down Expand Up @@ -133,7 +131,6 @@ func init() {
installAgentCmd.Flags().BoolVar(&installAgentCmdOptions.kube.inCluster, "in-cluster", false, "Set flag if venona is been installed from inside a cluster")
installAgentCmd.Flags().BoolVar(&installAgentCmdOptions.dryRun, "dry-run", false, "Set to true to simulate installation")
installAgentCmd.Flags().BoolVar(&installAgentCmdOptions.kubernetesRunnerType, "kubernetes-runner-type", false, "Set the runner type to kubernetes (alpha feature)")
installAgentCmd.Flags().BoolVar(&installAgentCmdOptions.skipClusterAcceptanceTest, "skip-cluster-test", false, "Do not run cluster acceptance test")
}

func fillCodefreshAPI(logger logger.Logger) {
Expand Down
16 changes: 6 additions & 10 deletions venonactl/cmd/install-runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@ var installRuntimeCmdOptions struct {
context string
nodeSelector string
}
storageClass string
runtimeEnvironmentName string
kubernetesRunnerType bool
tolerations string
templateValues []string
templateFileValues []string
skipClusterAcceptanceTest bool
storageClass string
runtimeEnvironmentName string
kubernetesRunnerType bool
tolerations string
templateValues []string
templateFileValues []string
}

var installRuntimeCmd = &cobra.Command{
Expand Down Expand Up @@ -96,7 +95,6 @@ var installRuntimeCmd = &cobra.Command{
CodefreshToken: installRuntimeCmdOptions.codefreshToken,
RuntimeEnvironment: installRuntimeCmdOptions.runtimeEnvironmentName,
ClusterNamespace: installRuntimeCmdOptions.kube.namespace,
SkipAcceptanceTest: installRuntimeCmdOptions.skipClusterAcceptanceTest,
}

if installRuntimeCmdOptions.kubernetesRunnerType {
Expand Down Expand Up @@ -175,6 +173,4 @@ func init() {

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

}
105 changes: 105 additions & 0 deletions venonactl/cmd/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package cmd

/*
Copyright 2019 The Codefresh Authors.
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.
*/

import (
"fmt"

"github.com/codefresh-io/venona/venonactl/pkg/plugins"
"github.com/codefresh-io/venona/venonactl/pkg/store"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var allTestPluginTypes = []string{
plugins.RuntimeEnvironmentPluginType,
plugins.VenonaPluginType,
plugins.MonitorAgentPluginType,
plugins.VolumeProvisionerPluginType,
plugins.EnginePluginType,
plugins.RuntimeAttachType,
}

var testCommandOptions struct {
kube struct {
namespace string
context string
}
plugin []string
}

var testCommand = &cobra.Command{
Use: "test",
Short: "Run test on the target cluster prior installation",
Run: func(cmd *cobra.Command, args []string) {
lgr := createLogger("test", verbose)
s := store.GetStore()
extendStoreWithKubeClient(lgr)
fillKubernetesAPI(lgr, testCommandOptions.kube.context, testCommandOptions.kube.namespace, false)

builder := plugins.NewBuilder(lgr)
for _, p := range testCommandOptions.plugin {
if p == plugins.RuntimeEnvironmentPluginType {
builder.Add(plugins.RuntimeEnvironmentPluginType)
}
if p == plugins.VenonaPluginType {
builder.Add(plugins.VenonaPluginType)
}
if p == plugins.MonitorAgentPluginType {
builder.Add(plugins.MonitorAgentPluginType)
}
if p == plugins.VolumeProvisionerPluginType {
builder.Add(plugins.VolumeProvisionerPluginType)
}
if p == plugins.EnginePluginType {
builder.Add(plugins.EnginePluginType)
}
if p == plugins.RuntimeAttachType {
builder.Add(plugins.RuntimeAttachType)
}
}
var finalerr error
for _, p := range builder.Get() {
lgr.Info("Testing requirements", "installer", p.Name())
err := p.Test(plugins.TestOptions{
KubeBuilder: getKubeClientBuilder(s.KubernetesAPI.ContextName, s.KubernetesAPI.Namespace, s.KubernetesAPI.ConfigPath, false),
ClusterNamespace: s.KubernetesAPI.Namespace,
})
if err != nil {
if finalerr != nil {
finalerr = fmt.Errorf("%s - %s", finalerr.Error(), err.Error())
} else {
finalerr = fmt.Errorf("%s", err.Error())

}
}
}
dieOnError(finalerr)

lgr.Info("Cluster passed acceptance test")
},
}

func init() {
viper.BindEnv("kube-namespace", "KUBE_NAMESPACE")
viper.BindEnv("kube-context", "KUBE_CONTEXT")

testCommand.Flags().StringVar(&testCommandOptions.kube.namespace, "kube-namespace", viper.GetString("kube-namespace"), "Name of the namespace on which monitor should be installed [$KUBE_NAMESPACE]")
testCommand.Flags().StringVar(&testCommandOptions.kube.context, "kube-context-name", viper.GetString("kube-context"), "Name of the kubernetes context on which monitor should be installed (default is current-context) [$KUBE_CONTEXT]")
testCommand.Flags().StringArrayVar(&testCommandOptions.plugin, "installer", allTestPluginTypes, "Which test to run, based on the installer type")

rootCmd.AddCommand(testCommand)
}
8 changes: 8 additions & 0 deletions venonactl/pkg/plugins/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,11 @@ func (u *enginePlugin) Upgrade(opt *UpgradeOptions, v Values) (Values, error) {
func (u *enginePlugin) Migrate(*MigrateOptions, Values) error {
return fmt.Errorf("not supported")
}

func (u *enginePlugin) Test(opt TestOptions) error {
return nil
}

func (u *enginePlugin) Name() string {
return EnginePluginType
}
73 changes: 73 additions & 0 deletions venonactl/pkg/plugins/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"strings"

// import all cloud providers auth clients
authv1 "k8s.io/api/authorization/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth"
Expand All @@ -51,6 +52,14 @@ type (
cpu string
localDiskMinimumSize string
momorySize string
rbac []rbacValidation
}

rbacValidation struct {
Namespace string
Resource string
Verbs []string
Group string
}
)

Expand Down Expand Up @@ -155,6 +164,32 @@ func getKubeObjectsFromTempalte(values map[string]interface{}, pattern string, l

func ensureClusterRequirements(client *kubernetes.Clientset, req validationRequest, logger logger.Logger) (validationResult, error) {
result := validationResult{true, nil}
specs := []*authv1.SelfSubjectAccessReview{}
for _, rbac := range req.rbac {
for _, verb := range rbac.Verbs {
attr := &authv1.ResourceAttributes{
Resource: rbac.Resource,
Verb: verb,
Group: rbac.Group,
}
if rbac.Namespace != "" {
attr.Namespace = rbac.Namespace
}
specs = append(specs, &authv1.SelfSubjectAccessReview{
Spec: authv1.SelfSubjectAccessReviewSpec{
ResourceAttributes: attr,
},
})
}
}
rbacres := testRBAC(client, specs)
if len(rbacres) > 0 {
result.isValid = false
for _, res := range rbacres {
result.message = append(result.message, res)
}
return result, nil
}

v, err := client.ServerVersion()
if err != nil {
Expand Down Expand Up @@ -198,6 +233,20 @@ func ensureClusterRequirements(client *kubernetes.Clientset, req validationReque
return result, nil
}

func handleValidationResult(res validationResult, logger logger.Logger) error {
if !res.isValid {
for _, m := range res.message {
logger.Error(m)
}
return errors.New("Failed to run acceptance test on cluster")
}

for _, m := range res.message {
logger.Warn(m)
}
return nil
}

func testKubernetesVersion(version *version.Info) (bool, error) {
v, err := semver.NewVersion(version.String())
if err != nil {
Expand Down Expand Up @@ -244,3 +293,27 @@ func testNode(n v1.Node, req validationRequest) []string {

return result
}

func testRBAC(client *kubernetes.Clientset, specs []*authv1.SelfSubjectAccessReview) []string {
res := []string{}
for _, sar := range specs {
resp, err := client.AuthorizationV1().SelfSubjectAccessReviews().Create(sar)
if err != nil {
res = append(res, err.Error())
continue
}
if !resp.Status.Allowed {
verb := sar.Spec.ResourceAttributes.Verb
namespace := sar.Spec.ResourceAttributes.Namespace
resource := sar.Spec.ResourceAttributes.Resource
group := sar.Spec.ResourceAttributes.Group
msg := strings.Builder{}
msg.WriteString(fmt.Sprintf("Insufficient permission, %s %s/%s is not allowed", verb, group, resource))
if namespace != "" {
msg.WriteString(fmt.Sprintf(" on namespace %s", namespace))
}
res = append(res, msg.String())
}
}
return res
}
40 changes: 40 additions & 0 deletions venonactl/pkg/plugins/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package plugins

import (
"fmt"

"github.com/codefresh-io/venona/venonactl/pkg/logger"
templates "github.com/codefresh-io/venona/venonactl/pkg/templates/kubernetes"
)
Expand Down Expand Up @@ -84,3 +85,42 @@ func (u *monitorAgentPlugin) Upgrade(opt *UpgradeOptions, v Values) (Values, err
func (u *monitorAgentPlugin) Migrate(*MigrateOptions, Values) error {
return fmt.Errorf("not supported")
}

func (u *monitorAgentPlugin) Test(opt TestOptions) error {
validationRequest := validationRequest{
rbac: []rbacValidation{
{
Group: "apps",
Resource: "*",
Verbs: []string{"get", "list", "watch"},
Namespace: opt.ClusterNamespace,
},
{
Resource: "*",
Verbs: []string{"get", "list", "watch", "create", "delete"},
Namespace: opt.ClusterNamespace,
},
{
Group: "extensions",
Resource: "*",
Verbs: []string{"get", "list", "watch"},
Namespace: opt.ClusterNamespace,
},
{
Resource: "pods",
Verbs: []string{"deletecollection"},
Namespace: opt.ClusterNamespace,
},
},
}
return test(testOptions{
logger: u.logger,
kubeBuilder: opt.KubeBuilder,
namespace: opt.ClusterNamespace,
validationRequest: validationRequest,
})
}

func (u *monitorAgentPlugin) Name() string {
return MonitorAgentPluginType
}
Loading

0 comments on commit 1468792

Please sign in to comment.