Skip to content

Commit

Permalink
Add basic commands for k8ssandra, stop/start/restart CassandraDatacen…
Browse files Browse the repository at this point in the history
…ter. Add Github Actions to build docker image as well as run tests and lint
  • Loading branch information
burmanm committed Sep 6, 2022
1 parent d7ef6ee commit 4906951
Show file tree
Hide file tree
Showing 10 changed files with 491 additions and 10 deletions.
71 changes: 71 additions & 0 deletions .github/workflows/build-client.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: k8ssandra-client build and deploy
on:
push:
branches:
- main
pull_request:
branches: [ main ]
jobs:
build_and_test:
env:
CGO_ENABLED: 0
steps:
- uses: actions/checkout@v2
if: github.event_name == 'pull_request'
with:
ref: ${{ github.event.pull_request.head.sha }}
- uses: actions/checkout@v2
if: github.event_name != 'pull_request'
- name: Set up Go 1.19
uses: actions/setup-go@v1
with:
go-version: 1.19
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: latest
# GHA requires longer timeout
args: --timeout=10m
# Optional: show only new issues if it's a pull request. The default value is `false`.
only-new-issues: ${{ github.event_name == 'pull_request' }}
skip-pkg-cache: true
skip-build-cache: true
- name: Unit Tests
run: |
make test
build_docker_image:
name: Build k8ssandra-client Docker Image
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
- name: Set git parsed values
id: vars
run: |
echo ::set-output name=sha_short::$(git rev-parse --short=8 ${{ github.sha }})
echo ::set-output name=tag_name::${GITHUB_REF#refs/tags/}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
file: cmd/kubectl-k8ssandra/Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: k8ssandra/k8ssandra-client:${{ steps.vars.outputs.sha_short }}, k8ssandra/k8ssandra-client:latest
platforms: linux/amd64
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
# k8ssandra-client
# k8ssandra-client

Work in progress, breaking changes will occur. This is intended to be a kubectl plugin to simplify usage of k8ssandra.
8 changes: 4 additions & 4 deletions cmd/kubectl-k8ssandra/k8ssandra/k8ssandra.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
// "github.com/k8ssandra/k8ssandra-client/cmd/kubectl-k8ssandra/list"
// "github.com/k8ssandra/k8ssandra-client/cmd/kubectl-k8ssandra/migrate"
// "github.com/k8ssandra/k8ssandra-client/cmd/kubectl-k8ssandra/nodetool"
// "github.com/k8ssandra/k8ssandra-client/cmd/kubectl-k8ssandra/operate"
"github.com/k8ssandra/k8ssandra-client/cmd/kubectl-k8ssandra/operate"
// "github.com/k8ssandra/k8ssandra-client/cmd/kubectl-k8ssandra/users"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -42,9 +42,9 @@ func NewCmd(streams genericclioptions.IOStreams) *cobra.Command {
// cmd.AddCommand(cleaner.NewCmd(streams))
// cmd.AddCommand(crds.NewCmd(streams))
// cmd.AddCommand(edit.NewCmd(streams))
// cmd.AddCommand(operate.NewStartCmd(streams))
// cmd.AddCommand(operate.NewRestartCmd(streams))
// cmd.AddCommand(operate.NewStopCmd(streams))
cmd.AddCommand(operate.NewStartCmd(streams))
cmd.AddCommand(operate.NewRestartCmd(streams))
cmd.AddCommand(operate.NewStopCmd(streams))
// cmd.AddCommand(list.NewCmd(streams))
// cmd.AddCommand(migrate.NewCmd(streams))
// cmd.AddCommand(users.NewCmd(streams))
Expand Down
206 changes: 206 additions & 0 deletions cmd/kubectl-k8ssandra/operate/operate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
package operate

import (
"fmt"

"github.com/k8ssandra/k8ssandra-client/pkg/cassdcutil"
"github.com/k8ssandra/k8ssandra-client/pkg/kubernetes"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
)

var (
startExample = `
# start an existing datacenter that was stopped
%[1]s start <datacenter>
`

stopExample = `
# shutdown an existing datacenter
%[1]s stop <datacenter>
# shutdown an existing datacenter and wait for all the pods to shutdown
%[1]s stop <datacenter> --wait
`

restartExample = `
# request a rolling restart for datacenter
%[1]s restart <datacenter>
# request a rolling restart of a single rack called r1
%[1]s restart <datacenter> --rack r1
`

errNoDatacenterDefined = fmt.Errorf("no target datacenter given")
errRestartingStopped = fmt.Errorf("unable to do rolling restart to a stopped datacenter")
)

type options struct {
configFlags *genericclioptions.ConfigFlags
genericclioptions.IOStreams
namespace string
dcName string
rackName string
wait bool
cassManager *cassdcutil.CassManager
}

func newOptions(streams genericclioptions.IOStreams) *options {
return &options{
configFlags: genericclioptions.NewConfigFlags(true),
IOStreams: streams,
}
}

func NewStartCmd(streams genericclioptions.IOStreams) *cobra.Command {
o := newOptions(streams)

cmd := &cobra.Command{
Use: "start [cluster]",
Short: "restart an existing shutdown Cassandra cluster",
Example: fmt.Sprintf(startExample, "kubectl k8ssandra"),
SilenceUsage: true,
RunE: func(c *cobra.Command, args []string) error {
if err := o.Complete(c, args); err != nil {
return err
}
if err := o.Validate(); err != nil {
return err
}
if err := o.Run(false); err != nil {
return err
}

return nil
},
}

fl := cmd.Flags()
fl.BoolVarP(&o.wait, "wait", "w", false, "wait until all pods have started")
fl.StringVar(&o.rackName, "rack", "", "restart only target rack")
o.configFlags.AddFlags(fl)
return cmd
}

func NewRestartCmd(streams genericclioptions.IOStreams) *cobra.Command {
o := newOptions(streams)

cmd := &cobra.Command{
Use: "restart [cluster]",
Short: "request rolling restart for an existing running Cassandra cluster",
Example: fmt.Sprintf(restartExample, "kubectl k8ssandra"),
SilenceUsage: true,
RunE: func(c *cobra.Command, args []string) error {
if err := o.Complete(c, args); err != nil {
return err
}
if err := o.ValidateRestart(); err != nil {
return err
}
if err := o.Restart(); err != nil {
return err
}

return nil
},
}

fl := cmd.Flags()
fl.BoolVarP(&o.wait, "wait", "w", false, "wait until all pods have restarted")
o.configFlags.AddFlags(fl)
return cmd
}

func NewStopCmd(streams genericclioptions.IOStreams) *cobra.Command {
o := newOptions(streams)

cmd := &cobra.Command{
Use: "stop [cluster]",
Short: "shutdown running Cassandra cluster",
Example: fmt.Sprintf(stopExample, "kubectl k8ssandra"),
SilenceUsage: true,
RunE: func(c *cobra.Command, args []string) error {
if err := o.Complete(c, args); err != nil {
return err
}
if err := o.Validate(); err != nil {
return err
}
if err := o.Run(true); err != nil {
return err
}

return nil
},
}

fl := cmd.Flags()
fl.BoolVarP(&o.wait, "wait", "w", false, "wait until all pods have terminated")
o.configFlags.AddFlags(fl)
return cmd
}

// Complete parses the arguments and necessary flags to options
func (c *options) Complete(cmd *cobra.Command, args []string) error {
var err error

if len(args) < 1 {
return errNoDatacenterDefined
}

c.dcName = args[0]

c.namespace, _, err = c.configFlags.ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}

restConfig, err := c.configFlags.ToRESTConfig()
if err != nil {
return err
}

kubeClient, err := kubernetes.GetClientInNamespace(restConfig, c.namespace)
if err != nil {
return err
}

c.cassManager = cassdcutil.NewManager(kubeClient)

return nil
}

// Validate ensures that all required arguments and flag values are provided
func (c *options) Validate() error {
// Verify target cluster exists
_, err := c.cassManager.CassandraDatacenter(c.dcName, c.namespace)
if err != nil {
// NotFound is still an error
return err
}
return nil
}

// ValidateRestart ensures that all required arguments and flag values are provided
func (c *options) ValidateRestart() error {
// Verify target cluster exists
dc, err := c.cassManager.CassandraDatacenter(c.dcName, c.namespace)
if err != nil {
// NotFound is still an error
return err
}
if dc.Spec.Stopped {
return errRestartingStopped
}
return nil
}

// Run either stops or starts the existing datacenter
func (c *options) Run(stop bool) error {
return c.cassManager.ModifyStoppedState(c.dcName, c.namespace, stop, c.wait)
}

// Restart creates a restart task for the cluster
func (c *options) Restart() error {
return c.cassManager.RestartDc(c.dcName, c.namespace, c.rackName, c.wait)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/k8ssandra/k8ssandra-client
go 1.19

require (
github.com/k8ssandra/cass-operator v1.12.0
github.com/k8ssandra/cass-operator v1.12.1-0.20220906085913-02eeca96b2da
github.com/spf13/cobra v1.4.0
github.com/spf13/pflag v1.0.5
gopkg.in/yaml.v3 v3.0.1
Expand Down
6 changes: 3 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk=
github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
Expand Down Expand Up @@ -410,8 +410,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/k8ssandra/cass-operator v1.12.0 h1:PjYPlrZI7bH4NfpT0EP1+7jOoCQXXihIzUBb+OMJs6o=
github.com/k8ssandra/cass-operator v1.12.0/go.mod h1:vOjZ8NP9RNua8mbrZMkXFPBO9YbwVVfnJQIS8Yf8kHU=
github.com/k8ssandra/cass-operator v1.12.1-0.20220906085913-02eeca96b2da h1:pp6z8/mENl1cpF3akdcID1ProfZ6hfmJxzHKuK5Nilg=
github.com/k8ssandra/cass-operator v1.12.1-0.20220906085913-02eeca96b2da/go.mod h1:ceNjUpBg+1lKEXzii8jJg45R9phRBYMR0ovjY0bFQV0=
github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw=
github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
Expand Down
Loading

0 comments on commit 4906951

Please sign in to comment.