Skip to content

Commit

Permalink
Merge pull request #1 from mamezou-tech/0.0.8
Browse files Browse the repository at this point in the history
v0.0.8 Release
  • Loading branch information
kudoh authored Dec 20, 2020
2 parents 4ec4929 + f829c7c commit 136dec8
Show file tree
Hide file tree
Showing 31 changed files with 740 additions and 201 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ jobs:
runs-on: ubuntu-latest
steps:

- name: Set up Go 1.13
- name: Set up Go 1.14
uses: actions/setup-go@v1
with:
go-version: 1.13
go-version: 1.14
id: go

- name: Check out code into the Go module directory
Expand Down
32 changes: 30 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This resource assumes that kubernetes deployment is executed by plain manifests(

In addition to deploy(`kubectl apply`) operation, it also supports delete(`kubectl delete`) and undo(`kubectl rollout undo`) operations.

This resource has been tested on 1.14 and 1.17 (probably works on 1.15 and 1.16).
This resource has been tested on kubernetes v1.20.1 and concourse v6.7.2.

## Source Configuration

Expand Down Expand Up @@ -43,6 +43,8 @@ Deploys the watched resources to kubernetes using plain manifests or Kustomize o
* `kustomize` - true if deploying by kustomize. Default to `false`.
* `status_check_timeout` - The time(seconds) to wait for deployment to complete. Default to 5 minutes.
* `command_timeout` - The time(seconds) to wait for kubectl apply or delete. Default to unlimited(0).
* `diff` - true if using `kubectl diff`. Default to `false`.
* `server_dry_run` - true if using `kubectl apply --dry-run=server`. Default to `false`.
* `delete` - true if using `kubectl delete` operation. Default to `false`.
* `undo` - true if using `kubectl rollout undo` operation(target resources are `watchedResources`). Default to `false`.

Expand All @@ -58,7 +60,7 @@ resource_types:
type: docker-image
source:
repository: kudohn/concourse-k8s-resource
tag: 0.0.7
tag: 0.0.8
```
### `resources`
Expand Down Expand Up @@ -161,6 +163,32 @@ jobs:
undo: true
```

#### Deploy resources with server-dry-run

```yaml
jobs:
- name: deploy-app
plan:
- get: repo
- put: k8s
params:
paths:
- repo/test/kustomize/overlays/prod
server_dry_run: true
```
#### Diff Resources manifests

```yaml
jobs:
- name: deploy-app
plan:
- get: repo
- put: k8s
params:
paths:
- repo/test/kustomize/overlays/prod
diff: true
```
#### Delete Resources

```yaml
Expand Down
22 changes: 15 additions & 7 deletions cmd/out/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func main() {
if err := kubectl.RunCommand(factory, commandConfig); err != nil {
log.Fatalln("cannot run kubectl command", err)
}
if !request.Params.Delete {
if requireStatusCheck(request.Params) {
time.Sleep(5 * time.Second)
log.Println("check status for", request.Source.WatchResources)
if ok := k8s.CheckResourceStatus(clientset, request.Source.Namespace, request.Source.WatchResources, request.Params.StatusCheckTimeout); !ok {
Expand All @@ -66,24 +66,25 @@ func main() {
}
}

func requireStatusCheck(params models.OutParams) bool {
return !params.Delete && !params.ServerDryRun && !params.Diff
}

func createResponse(request models.OutRequest, clientset kubernetes.Interface) *models.OutResponse {

if request.Params.Delete {
// resources is deleted, so just return empty response
return &models.OutResponse{
Version: models.Version{},
Metadata: nil,
}
return emptyResponse()
}

// apply or undo
version, err := k8s.GetCurrentVersion(&request.Source, clientset)
if err != nil {
log.Fatalln(err)
return emptyResponse()
}
metadatas, err := k8s.GenerateMetadatas(&request.Source, clientset)
if err != nil {
log.Fatalln(err)
return emptyResponse()
}

response := models.OutResponse{
Expand All @@ -93,6 +94,13 @@ func createResponse(request models.OutRequest, clientset kubernetes.Interface) *
return &response
}

func emptyResponse() *models.OutResponse {
return &models.OutResponse{
Version: models.Version{},
Metadata: nil,
}
}

func toDiscoveryInterface(obj interface{}) discovery.DiscoveryInterface {
if discoveryIf, ok := obj.(discovery.DiscoveryInterface); ok {
return discoveryIf
Expand Down
18 changes: 9 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
module github.com/mamezou-tech/concourse-k8s-resource

go 1.13
go 1.14

require (
github.com/aws/aws-lambda-go v1.13.3 // indirect
github.com/spf13/cobra v0.0.5
github.com/emicklei/go-restful v2.9.5+incompatible
github.com/spf13/cobra v1.1.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.4.0
k8s.io/api v0.17.0
k8s.io/apimachinery v0.17.0
k8s.io/cli-runtime v0.17.0
k8s.io/client-go v0.17.0
k8s.io/kubectl v0.17.0
github.com/stretchr/testify v1.6.1
k8s.io/api v0.20.1
k8s.io/apimachinery v0.20.1
k8s.io/cli-runtime v0.20.1
k8s.io/client-go v0.20.1
k8s.io/kubectl v0.20.1
)
536 changes: 420 additions & 116 deletions go.sum

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions pkg/k8s/kubectl/apply_command_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ func (*applyCommandFactory) create(config *CommandConfig) (commands []*Command,
setFlag(command, "record", "true")
setFlag(command, "timeout", strconv.Itoa(int(config.Params.CommandTimeout))+"s")
setManifestPath(command, config.Params)
if config.Params.ServerDryRun {
setFlag(command, "dry-run", "server")
}

commands = append(commands, &Command{command, []string{}})
return
Expand Down
45 changes: 45 additions & 0 deletions pkg/k8s/kubectl/diff_command_factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package kubectl

import (
"github.com/emicklei/go-restful/log"
"github.com/spf13/cobra"
"k8s.io/client-go/util/exec"
"k8s.io/kubectl/pkg/cmd/apply"
"k8s.io/kubectl/pkg/cmd/diff"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
)

type diffCommandFactory struct{}

var _ CommandFactory = &diffCommandFactory{}

func (*diffCommandFactory) create(config *CommandConfig) (commands []*Command, err error) {
factory := createKubectlFactory(config)

options := diff.NewDiffOptions(config.Streams)
command := &cobra.Command{
Use: "diff",
DisableFlagsInUseLine: true,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckDiffErr(options.Complete(factory, cmd))
if err := options.Run(); err != nil {
// exit code == 1 -> there is difference(not error!)
if ee, ok := err.(exec.ExitError); ok && ee.ExitStatus() == 1 {
log.Printf("found difference!")
return
}
// exit with error code(>2)
log.Printf("ERR! %+v", err)
cmdutil.CheckDiffErr(err)
}
},
}
cmdutil.AddFilenameOptionFlags(command, &options.FilenameOptions, "contains the configuration to diff")
cmdutil.AddServerSideApplyFlags(command)
cmdutil.AddFieldManagerFlagVar(command, &options.FieldManager, apply.FieldManagerClientSideApply)

setManifestPath(command, config.Params)

commands = append(commands, &Command{command, []string{}})
return
}
2 changes: 2 additions & 0 deletions pkg/k8s/kubectl/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ func NewCommandFactory(params *models.OutParams) CommandFactory {
return &undoCommandFactory{}
case params.Delete:
return &deleteCommandFactory{}
case params.Diff:
return &diffCommandFactory{}
default:
return &applyCommandFactory{}
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/k8s/kubectl/undo_command_factory.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package kubectl

import (
"context"
"fmt"
"github.com/mamezou-tech/concourse-k8s-resource/pkg/k8s"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -24,7 +25,7 @@ func (*undoCommandFactory) create(config *CommandConfig) (commands []*Command, e
var args []string
switch {
case k8s.IsDeployment(resource.Kind):
d, err := config.Clientset.AppsV1().Deployments(config.Namespace).Get(resource.Name, metav1.GetOptions{})
d, err := config.Clientset.AppsV1().Deployments(config.Namespace).Get(context.TODO(), resource.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
Expand All @@ -40,11 +41,11 @@ func (*undoCommandFactory) create(config *CommandConfig) (commands []*Command, e
args = []string{fmt.Sprintf("%s/%s", "deployment", resource.Name)}

case k8s.IsStatefulSet(resource.Kind):
sts, err := config.Clientset.AppsV1().StatefulSets(config.Namespace).Get(resource.Name, metav1.GetOptions{})
sts, err := config.Clientset.AppsV1().StatefulSets(config.Namespace).Get(context.TODO(), resource.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
rev, err := config.Clientset.AppsV1().ControllerRevisions(config.Namespace).Get(sts.Status.CurrentRevision, metav1.GetOptions{})
rev, err := config.Clientset.AppsV1().ControllerRevisions(config.Namespace).Get(context.TODO(), sts.Status.CurrentRevision, metav1.GetOptions{})
if err != nil {
return nil, err
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/k8s/metadata_reader.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package k8s

import (
"context"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
Expand All @@ -19,7 +20,7 @@ type DeploymentReader struct {
var _ MetadataReader = &DeploymentReader{}

func NewDeploymentReader(clientset kubernetes.Interface, namespace string, name string) (*DeploymentReader, error) {
d, err := clientset.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{})
d, err := clientset.AppsV1().Deployments(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
return nil, err
}
Expand All @@ -42,11 +43,11 @@ type StatefulSetReader struct {
var _ MetadataReader = &StatefulSetReader{}

func NewStatefulSetReader(clientset kubernetes.Interface, namespace string, name string) (*StatefulSetReader, error) {
sts, err := clientset.AppsV1().StatefulSets(namespace).Get(name, metav1.GetOptions{})
sts, err := clientset.AppsV1().StatefulSets(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
return nil, err
}
rev, err := clientset.AppsV1().ControllerRevisions(namespace).Get(sts.Status.CurrentRevision, metav1.GetOptions{})
rev, err := clientset.AppsV1().ControllerRevisions(namespace).Get(context.TODO(), sts.Status.CurrentRevision, metav1.GetOptions{})
if err != nil {
return nil, err
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/k8s/status_checker.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package k8s

import (
"context"
"fmt"
"github.com/mamezou-tech/concourse-k8s-resource/pkg/models"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -77,7 +78,7 @@ func (c *statusChecker) check() error {
var current int32
switch {
case IsDeployment(c.resource.Kind):
d, err := c.clientset.AppsV1().Deployments(c.namespace).Get(c.resource.Name, metav1.GetOptions{})
d, err := c.clientset.AppsV1().Deployments(c.namespace).Get(context.TODO(), c.resource.Name, metav1.GetOptions{})
if err != nil {
return err
}
Expand All @@ -97,7 +98,7 @@ func (c *statusChecker) check() error {
return nil
}
case IsStatefulSet(c.resource.Kind):
sts, err := c.clientset.AppsV1().StatefulSets(c.namespace).Get(c.resource.Name, metav1.GetOptions{})
sts, err := c.clientset.AppsV1().StatefulSets(c.namespace).Get(context.TODO(), c.resource.Name, metav1.GetOptions{})
if err != nil {
return err
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/k8s/status_checker_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package k8s

import (
"context"
"github.com/mamezou-tech/concourse-k8s-resource/pkg/models"
"github.com/stretchr/testify/assert"
appv1 "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -68,9 +69,9 @@ func TestCheckResourceStatus(t *testing.T) {
time.AfterFunc(1*time.Second, func() {
t.Log("ready for pod...")
app1rs.Status.ReadyReplicas = 3
clientset.AppsV1().ReplicaSets("test").Update(&app1rs)
clientset.AppsV1().ReplicaSets("test").Update(context.TODO(), &app1rs, metav1.UpdateOptions{})
app2.Status.ReadyReplicas = 2
clientset.AppsV1().StatefulSets("test").Update(&app2)
clientset.AppsV1().StatefulSets("test").Update(context.TODO(), &app2, metav1.UpdateOptions{})
})

ok := CheckResourceStatus(clientset, "test", resources, 5)
Expand Down
6 changes: 5 additions & 1 deletion pkg/models/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,14 @@ type OutParams struct {
StatusCheckTimeout int32 `json:"status_check_timeout"`
// if true, delete resources
Delete bool `json:"delete"`
// if true, rollback previous deployment
// if true, rollback to previous deployment
Undo bool `json:"undo"`
// kubectl timeout seconds
CommandTimeout int32 `json:"command_timeout"`
// if true, execute as dry-run=server
ServerDryRun bool `json:"server_dry_run"`
// if true, run diff command instead of apply
Diff bool `json:"diff"`
}

// concourse metadata
Expand Down
10 changes: 8 additions & 2 deletions test/_internal.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
kubectl create ns concourse
helm repo add concourse https://concourse-charts.storage.googleapis.com/
helm upgrade --install concourse concourse/concourse --namespace concourse \
--set persistence.worker.storageClass=openebs-cstor-sparse \
--set postgresql.persistence.storageClass=openebs-cstor-sparse
--set persistence.worker.storageClass=openebs-hostpath \
--set postgresql.persistence.storageClass=openebs-hostpath

export POD_NAME=$(kubectl get pods --namespace concourse -l "app=concourse-web" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward --namespace concourse $POD_NAME 8080:8080
Expand Down Expand Up @@ -39,4 +39,10 @@ cat test/json/out_request_undo_kustomize.json | go run cmd/out/main.go
## delete
cat test/json/out_request_delete_plain.json | go run cmd/out/main.go
cat test/json/out_request_delete_kustomize.json | go run cmd/out/main.go
## dry-run
cat test/json/out_request_dryrun_plain.json | go run cmd/out/main.go
cat test/json/out_request_dryrun_kustomize.json | go run cmd/out/main.go
## diff
cat test/json/out_request_diff_plain.json | go run cmd/out/main.go
cat test/json/out_request_diff_kustomize.json | go run cmd/out/main.go
```
Loading

0 comments on commit 136dec8

Please sign in to comment.