Skip to content

Commit

Permalink
initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
Dong Ying Bo committed Apr 7, 2020
1 parent 112f217 commit c1e1bad
Show file tree
Hide file tree
Showing 10 changed files with 1,055 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.vscode
main
k8s-volume-utils
43 changes: 42 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,43 @@
# k8s-volume-utils
simple utils for k8s pv/pvc
A simple tool to reuse PV. It can rename a PVC or move a PVC from one namespace to another namespace. After that we can resue bound PV without data lost

# Usage:
```
k8s-volume-utils pvc
It is used to rename a PVC object in kubernetes cluster.
It will delete original PVC and create new PVC referring to same PV.
New PVC can be in another namespace.
k8s-volume-utils pv
It can help to reuse a pv
Usage:
k8s-volume-utils [command]
Available Commands:
help Help about any command
pv help to reuse a pv
pvc rename PVC object in kubernetes clusterd
```
# Example
1. create two namespaces for test
`oc new-project pvc`
`oc new-project pvc1`
`oc project pvc `
2. create a statefulset and it will create a PV.
- Edit sts-pvc-test.yaml to update its `storageClassName` to available one on your cluster.
- `oc create -f sts-pvc-test.yaml`
- `oc get po www-pvc-test-0 -w ` to wait pod running. Then
```
$ oc exec pvc-test-0 cat /usr/share/nginx/html/a.txt
a
```
We can see there is data in PV.
3. delete the statefulset by `oc delete -f sts-pvc-test.yaml`. Now we have a pvc `www-pvc-test-0` to be reused by other service.
4. move pvc to namespace pvc1 by `go run main.go pvc www-pvc-test-0 "" pvc1`
`oc get pvc -n pvc1` to check PVC `www-pvc-test-0` is moved to namespace pvc1.
5. create another statefulset to reuse the same PV.
- Edit sts-pvc-test.yaml
Change `"echo a > /usr/share/nginx/html/a.txt;sleep 3600"` to `"echo b > /usr/share/nginx/html/b.txt;sleep 3600"`
- `oc -n pvc1 create -f sts-pvc-test.yaml`
- when pod `pvc-test-0 ` is running in namespace `pvc1`. Run `oc exec pvc-test-0 cat /usr/share/nginx/html/a.txt -n pvc1` to check data is not lost.
67 changes: 67 additions & 0 deletions cmd/pv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
Copyright © 2020 NAME HERE <EMAIL ADDRESS>
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.
*/
package cmd

import (
"os"

"github.com/IBM/k8s-volume-utils/pkg/kubeutils"
"github.com/spf13/cobra"
"k8s.io/klog"
)

// pvCmd represents the pv command
var pvCmd = &cobra.Command{
Use: "pv",
Short: "help to reuse a pv",
Long: `
k8s-volume-utils pv retain "pvName": change pv reclaim policy to retain
k8s-volume-utils pv resue "pvName": change pv status to available so that it is ready to be bound to pvc
`,
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
if args[0] == "retain" {
err := kubeutils.RetainPV(args[1])
if err != nil {
os.Exit(1)
}
} else if args[0] == "reuse" {
err := kubeutils.ReusePV(args[1])
if err != nil {
os.Exit(1)
}

} else {
klog.Error("invalid argument. should be retain or reuse")
os.Exit(1)
}
},
}

func init() {
rootCmd.AddCommand(pvCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// pvCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// pvCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
75 changes: 75 additions & 0 deletions cmd/pvc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//
// Copyright 2020 IBM Corporation
//
// 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.
//

package cmd

import (
"os"

"github.com/IBM/k8s-volume-utils/pkg/kubeutils"
"github.com/spf13/cobra"
)

// pvcCmd represents the pvc command
var pvcCmd = &cobra.Command{
Use: "pvc",
Short: "rename PVC object in kubernetes clusterd",
Long: `
Examples:
k8s-volume-utils pvc "name" "targetName" "targetNamespace", "namespace"
k8s-volume-utils pvc "name" "targetName" "targetNamespace"
k8s-volume-utils pvc "name" "targetName"
Paramethers:
name: pvc name to be renamed
targetName: pvc name to be renamed to
targetNamespace: namespace of new pvc
namespace: namespace of the source pvc
`,
Args: cobra.RangeArgs(2, 4),
Run: func(cmd *cobra.Command, args []string) {
var err error
if len(args) == 4 {
err = kubeutils.RenamePVC(args[0], args[1], args[2], args[3])

}
if len(args) == 3 {
err = kubeutils.RenamePVC(args[0], args[1], args[2], "")

}
if len(args) == 2 {
err = kubeutils.RenamePVC(args[0], args[1], "", "")

}
if err != nil {
os.Exit(1)
}
},
}

func init() {
rootCmd.AddCommand(pvcCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// pvcCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// pvcCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
81 changes: 81 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//
// Copyright 2020 IBM Corporation
//
// 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.
//

package cmd

import (
"flag"
"fmt"
"os"

"github.com/IBM/k8s-volume-utils/pkg/kubeutils"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/klog"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "k8s-volume-utils",
Short: "it is used to rename PVC object or help to reuse pv",
Long: `
k8s-volume-utils pvc
It is used to rename a PVC object in kubernetes cluster.
It will delete original PVC and create new PVC referring to same PV.
New PVC can be in another namespace.
k8s-volume-utils pv
It can help to reuse a pv
`,
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
klog.InitFlags(nil)
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func init() {
flags := rootCmd.PersistentFlags()

kubeConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag()
kubeConfigFlags.AddFlags(flags)
matchVersionKubeConfigFlags := cmdutil.NewMatchVersionFlags(kubeConfigFlags)
matchVersionKubeConfigFlags.AddFlags(rootCmd.PersistentFlags())

rootCmd.PersistentFlags().AddGoFlagSet(flag.CommandLine)

f := cmdutil.NewFactory(matchVersionKubeConfigFlags)
var namespace string
var err error
namespace, _, err = f.ToRawKubeConfigLoader().Namespace()
if err != nil {
klog.Errorf("fail to get default namespace: %s", err.Error())
}

client, e := f.KubernetesClientSet()
if e != nil {
klog.Errorf("fail to get kubeclient: %s", e.Error())
}
kubeutils.InitKube(client, namespace)
klog.Infof("kubeclient initialized. default namespace: %s", namespace)
}
50 changes: 50 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module github.com/IBM/k8s-volume-utils

go 1.13

require (
github.com/evanphx/json-patch v4.5.0+incompatible // indirect
github.com/googleapis/gnostic v0.3.1 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/onsi/ginkgo v1.11.0 // indirect
github.com/onsi/gomega v1.8.1 // indirect
github.com/pkg/errors v0.8.1 // indirect
github.com/spf13/cobra v0.0.7
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 // indirect
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.2.7 // indirect
k8s.io/api v0.18.0
k8s.io/apimachinery v0.18.0
k8s.io/cli-runtime v0.0.0
k8s.io/client-go v0.18.0
k8s.io/klog v1.0.0
k8s.io/kubectl v0.0.0
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f // indirect
)

// Pinned to kubernetes-1.16.2
replace (
k8s.io/api => k8s.io/api v0.0.0-20191016110408-35e52d86657a
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20191016113550-5357c4baaf65
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8
k8s.io/apiserver => k8s.io/apiserver v0.0.0-20191016112112-5190913f932d
k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20191016114015-74ad18325ed5
k8s.io/client-go => k8s.io/client-go v0.0.0-20191016111102-bec269661e48
k8s.io/cloud-provider => k8s.io/cloud-provider v0.0.0-20191016115326-20453efc2458
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.0.0-20191016115129-c07a134afb42
k8s.io/code-generator => k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894
k8s.io/component-base => k8s.io/component-base v0.0.0-20191016111319-039242c015a9
k8s.io/cri-api => k8s.io/cri-api v0.0.0-20190828162817-608eb1dad4ac
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.0.0-20191016115521-756ffa5af0bd
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.0.0-20191016112429-9587704a8ad4
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.0.0-20191016114939-2b2b218dc1df
k8s.io/kube-proxy => k8s.io/kube-proxy v0.0.0-20191016114407-2e83b6f20229
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.0.0-20191016114748-65049c67a58b
k8s.io/kubectl => k8s.io/kubectl v0.0.0-20191016120415-2ed914427d51
k8s.io/kubelet => k8s.io/kubelet v0.0.0-20191016114556-7841ed97f1b2
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.0.0-20191016115753-cf0698c3a16b
k8s.io/metrics => k8s.io/metrics v0.0.0-20191016113814-3b1a734dba6e
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.0.0-20191016112829-06bb3c9d77c9
)
Loading

0 comments on commit c1e1bad

Please sign in to comment.