Skip to content

Commit

Permalink
Validate: add support for kubernetes deployment validation with `src …
Browse files Browse the repository at this point in the history
…validate kube` subcommand (#926)

* Refactor out shared vars
* Add basic kube validation
* Add pod validation
* Add skeleton for service and connection validation
* Add connection validations
* Add go modules files
* Fix --kubeconfig flag
* Fix line output
* Add usage output to cli
* Fix path in example
* Add quiet flag to suppress output and return exit status only
* Fix exit status to be consistent if there are failures
* Remove TODOs
* Update CHANGELOG.md
  • Loading branch information
jdpleiness authored Jan 23, 2023
1 parent 270b736 commit 8779a73
Show file tree
Hide file tree
Showing 11 changed files with 1,014 additions and 39 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ All notable changes to `src-cli` are documented in this file.

- `src codeintel upload` will now upload SCIP indexes (over LSIF indexes) when the target instance supports it. [#897](https://github.com/sourcegraph/src-cli/pull/897)

- `src validate kube` adds support for validating Sourcegraph deployments on Kubernetes. Validations include Pods, Services, PVCs, and network connectivity. [#926](https://github.com/sourcegraph/src-cli/pull/926)

### Changed

### Fixed
Expand Down
1 change: 1 addition & 0 deletions cmd/src/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Usage:
The commands are:
install validates a Sourcegraph installation
kube validates a Sourcegraph deployment on a Kubernetes cluster
Use "src validate [command] -h" for more information about a command.
`
Expand Down
21 changes: 9 additions & 12 deletions cmd/src/validate_install.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,12 @@ import (
"strings"

"github.com/mattn/go-isatty"

"github.com/sourcegraph/src-cli/internal/api"
"github.com/sourcegraph/src-cli/internal/validate"
"github.com/sourcegraph/src-cli/internal/validate/install"

"github.com/sourcegraph/sourcegraph/lib/errors"
"github.com/sourcegraph/sourcegraph/lib/output"
)

var (
validateWarningEmoji = output.EmojiWarning
)

func init() {
Expand Down Expand Up @@ -60,7 +57,7 @@ Environmental variables

client := cfg.apiClient(apiFlags, flagSet.Output())

var validationSpec *validate.ValidationSpec
var validationSpec *install.ValidationSpec

if len(flagSet.Args()) == 1 {
fileName := flagSet.Arg(0)
Expand All @@ -70,14 +67,14 @@ Environmental variables
}

if strings.HasSuffix(fileName, ".yaml") || strings.HasSuffix(fileName, ".yml") {
validationSpec, err = validate.LoadYamlConfig(f)
validationSpec, err = install.LoadYamlConfig(f)
if err != nil {
return err
}
}

if strings.HasSuffix(fileName, ".json") {
validationSpec, err = validate.LoadJsonConfig(f)
validationSpec, err = install.LoadJsonConfig(f)
if err != nil {
return err
}
Expand All @@ -90,26 +87,26 @@ Environmental variables
if err != nil {
return errors.Wrap(err, "failed to read installation validation config from pipe")
}
validationSpec, err = validate.LoadYamlConfig(input)
validationSpec, err = install.LoadYamlConfig(input)
if err != nil {
return err
}
}

if validationSpec == nil {
validationSpec = validate.DefaultConfig()
validationSpec = install.DefaultConfig()
}

envGithubToken := os.Getenv("SRC_GITHUB_TOKEN")

// will work for now with only GitHub supported but will need to be revisited when other code hosts are supported
if envGithubToken == "" {
return errors.Newf("%s failed to read `SRC_GITHUB_TOKEN` environment variable", validateWarningEmoji)
return errors.Newf("%s failed to read `SRC_GITHUB_TOKEN` environment variable", validate.WarningSign)
}

validationSpec.ExternalService.Config.GitHub.Token = envGithubToken

return validate.Installation(context.Background(), client, validationSpec)
return install.Validate(context.Background(), client, validationSpec)
}

validateCommands = append(validateCommands, &command{
Expand Down
90 changes: 90 additions & 0 deletions cmd/src/validate_kube.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package main

import (
"context"
"flag"
"fmt"
"path/filepath"

"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"

"github.com/sourcegraph/src-cli/internal/validate/kube"

"github.com/sourcegraph/sourcegraph/lib/errors"
)

func init() {
usage := `'src validate kube' is a tool that validates a Kubernetes based Sourcegraph deployment
Examples:
Run default deployment validation:
$ src validate kube
Specify Kubernetes namespace:
$ src validate kube --namespace sourcegraph
Specify the kubeconfig file location:
$ src validate kube --kubeconfig ~/.kube/config
Suppress output (useful for CI/CD pipelines)
$ src validate kube --quiet
`

flagSet := flag.NewFlagSet("kube", flag.ExitOnError)
usageFunc := func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src validate %s':\n", flagSet.Name())
flagSet.PrintDefaults()
fmt.Println(usage)
}

var (
kubeConfig *string
namespace = flagSet.String("namespace", "", "(optional) specify the kubernetes namespace to use")
quiet = flagSet.Bool("quiet", false, "(optional) suppress output and return exit status only")
)

if home := homedir.HomeDir(); home != "" {
kubeConfig = flagSet.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
} else {
kubeConfig = flagSet.String("kubeconfig", "", "absolute path to the kubeconfig file")
}

handler := func(args []string) error {
if err := flagSet.Parse(args); err != nil {
return err
}

// use the current context in kubeConfig
config, err := clientcmd.BuildConfigFromFlags("", *kubeConfig)
if err != nil {
return errors.Wrap(err, "failed to load kubernetes config")
}

clientSet, err := kubernetes.NewForConfig(config)
if err != nil {
return errors.Wrap(err, "failed to create kubernetes client")
}

// parse through flag options
var options []kube.Option

if *namespace != "" {
options = append(options, kube.WithNamespace(*namespace))
}

if *quiet {
options = append(options, kube.Quiet())
}

return kube.Validate(context.Background(), clientSet, config, options...)
}

validateCommands = append(validateCommands, &command{
flagSet: flagSet,
handler: handler,
usageFunc: usageFunc,
})
}
24 changes: 23 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ require (
google.golang.org/protobuf v1.28.1
gopkg.in/yaml.v3 v3.0.1
jaytaylor.com/html2text v0.0.0-20200412013138-3577fbdbcff7
k8s.io/api v0.26.1
k8s.io/apimachinery v0.26.1
k8s.io/client-go v0.26.1
)

require (
Expand All @@ -50,41 +53,52 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/envoyproxy/protoc-gen-validate v0.3.0-java // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/getsentry/sentry-go v0.13.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gofrs/uuid v4.2.0+incompatible // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
github.com/googleapis/gax-go/v2 v2.6.0 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/hexops/gotextdiff v1.0.3 // indirect
github.com/hexops/valast v1.4.1 // indirect
github.com/huandu/xstrings v1.0.0 // indirect
github.com/imdario/mergo v0.3.4 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jdxcode/netrc v0.0.0-20210204082910-926c7f70242a // indirect
github.com/jhump/protocompile v0.0.0-20220216033700-d705409f108f // indirect
github.com/jhump/protoreflect v1.12.1-0.20220417024638-438db461d753 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.15.1 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/microcosm-cc/bluemonday v1.0.17 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.12.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007 // indirect
github.com/nightlyone/lockfile v1.0.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
Expand Down Expand Up @@ -117,13 +131,21 @@ require (
golang.org/x/sys v0.4.0 // indirect
golang.org/x/term v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
golang.org/x/tools v0.5.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e // indirect
google.golang.org/grpc v1.50.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/klog/v2 v2.80.1 // indirect
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect
mvdan.cc/gofumpt v0.2.1 // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

// See: https://github.com/ghodss/yaml/pull/65
Expand Down
Loading

0 comments on commit 8779a73

Please sign in to comment.