Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(upgrade): add support for UpgradeTask CR #11

Merged
merged 5 commits into from
Jul 2, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/upgrade/executor/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ type UpgradeOptions struct {
imageURLPrefix string
toVersionImageTag string
resourceKind string
name string
}

var (
options = &UpgradeOptions{
openebsNamespace: "openebs",
imageURLPrefix: "quay.io/openebs/",
imageURLPrefix: "",
}
)

Expand Down Expand Up @@ -68,6 +69,5 @@ func (u *UpgradeOptions) InitializeDefaults(cmd *cobra.Command) error {
if len(strings.TrimSpace(u.toVersionImageTag)) == 0 {
u.toVersionImageTag = u.toVersion
}

return nil
}
224 changes: 224 additions & 0 deletions cmd/upgrade/executor/resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
/*
Copyright 2020 The OpenEBS 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.
*/

package executor

import (
"os"
"strings"

"k8s.io/client-go/rest"
"k8s.io/klog"

apis "github.com/openebs/api/pkg/apis/openebs.io/v1alpha1"
openebsclientset "github.com/openebs/api/pkg/client/clientset/versioned"
"github.com/openebs/maya/pkg/util"
cmdUtil "github.com/openebs/upgrade/cmd/util"
upgrade "github.com/openebs/upgrade/pkg/upgrade"
"github.com/openebs/upgrade/pkg/version"
errors "github.com/pkg/errors"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)

var (
resourceUpgradeCmdHelpText = `
This command upgrades the resource mentioned in the UpgradeTask CR.
The name of the UpgradeTask CR is extracted from the ENV UPGRADE_TASK

Usage: upgrade resource
`
)

// ResourceOptions stores information required for upgradeTask upgrade
type ResourceOptions struct {
name string
}

// NewUpgradeResourceJob upgrade a resource from upgradeTask
func NewUpgradeResourceJob() *cobra.Command {
client, err := initClient()
util.CheckErr(err, util.Fatal)
cmd := &cobra.Command{
Use: "resource",
Short: "Upgrade a resource using the details specified in the UpgradeTask CR.",
Long: resourceUpgradeCmdHelpText,
Example: `upgrade resource`,
Run: func(cmd *cobra.Command, args []string) {
upgradeTaskLabel := cmdUtil.GetUpgradeTaskLabel()
openebsNamespace := cmdUtil.GetOpenEBSNamespace()
upgradeTaskList, err := client.OpenebsV1alpha1().UpgradeTasks(openebsNamespace).
List(metav1.ListOptions{
LabelSelector: upgradeTaskLabel,
})
util.CheckErr(err, util.Fatal)
if len(upgradeTaskList.Items) == 0 {
util.Fatal("No resource found for given label")
}
for _, cr := range upgradeTaskList.Items {
util.CheckErr(options.InitializeFromUpgradeTaskResource(cr), util.Fatal)
util.CheckErr(options.RunPreFlightChecks(cmd), util.Fatal)
util.CheckErr(options.RunResourceUpgradeChecks(cmd), util.Fatal)
util.CheckErr(options.InitializeDefaults(cmd), util.Fatal)
err := options.RunResourceUpgrade(cmd)
if err != nil {
utaskObj, err := client.OpenebsV1alpha1().UpgradeTasks(openebsNamespace).
Get(cr.Name, metav1.GetOptions{})
if err != nil {
util.Fatal(err.Error())
}
backoffLimit, err := getBackoffLimit(openebsNamespace)
if err != nil {
util.Fatal(err.Error())
}
utaskObj.Status.Retries = utaskObj.Status.Retries + 1
if utaskObj.Status.Retries == backoffLimit {
utaskObj.Status.Phase = apis.UpgradeError
utaskObj.Status.CompletedTime = metav1.Now()
}
_, err = client.OpenebsV1alpha1().UpgradeTasks(openebsNamespace).
Update(utaskObj)
if err != nil {
util.Fatal(err.Error())
}
} else {
utaskObj, err := client.OpenebsV1alpha1().UpgradeTasks(openebsNamespace).
Get(cr.Name, metav1.GetOptions{})
if err != nil {
util.Fatal(err.Error())
}
utaskObj.Status.Phase = apis.UpgradeSuccess
utaskObj.Status.CompletedTime = metav1.Now()
_, err = client.OpenebsV1alpha1().UpgradeTasks(openebsNamespace).
Update(utaskObj)
if err != nil {
util.Fatal(err.Error())
}
}
}
},
}
return cmd
}

// InitializeFromUpgradeTaskResource will populate the UpgradeOptions from given UpgradeTask
func (u *UpgradeOptions) InitializeFromUpgradeTaskResource(
upgradeTaskCRObj apis.UpgradeTask) error {

if len(strings.TrimSpace(u.openebsNamespace)) == 0 {
return errors.Errorf("Cannot execute upgrade job: namespace is missing")
}
if len(strings.TrimSpace(upgradeTaskCRObj.Spec.FromVersion)) != 0 {
u.fromVersion = upgradeTaskCRObj.Spec.FromVersion
}

if len(strings.TrimSpace(upgradeTaskCRObj.Spec.ToVersion)) != 0 {
u.toVersion = upgradeTaskCRObj.Spec.ToVersion
}

if len(strings.TrimSpace(upgradeTaskCRObj.Spec.ImagePrefix)) != 0 {
u.imageURLPrefix = upgradeTaskCRObj.Spec.ImagePrefix
}

if len(strings.TrimSpace(upgradeTaskCRObj.Spec.ImageTag)) != 0 {
u.toVersionImageTag = upgradeTaskCRObj.Spec.ImageTag
}

switch {
case upgradeTaskCRObj.Spec.ResourceSpec.CStorPoolInstance != nil:
u.resourceKind = "cstorpoolinstance"
u.name = upgradeTaskCRObj.Spec.ResourceSpec.CStorPoolInstance.CSPIName

case upgradeTaskCRObj.Spec.ResourceSpec.CStorPoolCluster != nil:
u.resourceKind = "cstorpoolcluster"
u.name = upgradeTaskCRObj.Spec.ResourceSpec.CStorPoolCluster.CSPCName

case upgradeTaskCRObj.Spec.ResourceSpec.CStorVolume != nil:
u.resourceKind = "cstorVolume"
u.name = upgradeTaskCRObj.Spec.ResourceSpec.CStorVolume.PVName
}

return nil
}

// RunResourceUpgradeChecks will ensure the sanity of the upgradeTask upgrade options
func (u *UpgradeOptions) RunResourceUpgradeChecks(cmd *cobra.Command) error {
if len(strings.TrimSpace(u.name)) == 0 {
return errors.Errorf("Cannot execute upgrade job: resource name is missing")
}

return nil
}

// RunResourceUpgrade upgrades the given upgradeTask
func (u *UpgradeOptions) RunResourceUpgrade(cmd *cobra.Command) error {
if version.IsCurrentVersionValid(u.fromVersion) && version.IsDesiredVersionValid(u.toVersion) {
klog.Infof("Upgrading to %s", u.toVersion)
err := upgrade.Exec(u.fromVersion, u.toVersion,
u.resourceKind,
u.name,
u.openebsNamespace,
u.imageURLPrefix,
u.toVersionImageTag)
if err != nil {
return errors.Wrapf(err, "Failed to upgrade %v %v", u.resourceKind, u.name)
}
} else {
return errors.Errorf("Invalid from version %s or to version %s", u.fromVersion, u.toVersion)
}
return nil
}

func initClient() (openebsclientset.Interface, error) {
cfg, err := rest.InClusterConfig()
if err != nil {
return nil, errors.Wrap(err, "error building kubeconfig")
}
client, err := openebsclientset.NewForConfig(cfg)
if err != nil {
return nil, errors.Wrap(err, "error building openebs clientset")
}
return client, nil
}

func getBackoffLimit(openebsNamespace string) (int, error) {
cfg, err := rest.InClusterConfig()
if err != nil {
return 0, errors.Wrap(err, "error building kubeconfig")
}
client, err := kubernetes.NewForConfig(cfg)
if err != nil {
return 0, errors.Wrap(err, "error building openebs clientset")
}
podName := os.Getenv("POD_NAME")
podObj, err := client.CoreV1().Pods(openebsNamespace).
Get(podName, metav1.GetOptions{})
if err != nil {
return 0, errors.Wrapf(err, "failed to get backoff limit")
}
jobObj, err := client.BatchV1().Jobs(openebsNamespace).
Get(podObj.OwnerReferences[0].Name, metav1.GetOptions{})
if err != nil {
return 0, errors.Wrapf(err, "failed to get backoff limit")
}
// if backoffLimit not present it returns the default as 6
if jobObj.Spec.BackoffLimit == nil {
return 6, nil
}
backoffLimit := int(*jobObj.Spec.BackoffLimit)
return backoffLimit, nil
}
1 change: 1 addition & 0 deletions cmd/upgrade/executor/setup_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func NewJob() *cobra.Command {
cmd.AddCommand(
NewUpgradeCStorCSPCJob(),
NewUpgradeCStorVolumeJob(),
NewUpgradeResourceJob(),
)

cmd.PersistentFlags().StringVarP(&options.fromVersion,
Expand Down
7 changes: 7 additions & 0 deletions cmd/util/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,17 @@ import (

const (
openebsNamespaceEnv = "OPENEBS_NAMESPACE"
upgradeTaskLabel = "UPGRADE_TASK_LABEL"
)

// GetOpenEBSNamespace gets the openebs namespace set to
// the OPENEBS_NAMESPACE env
func GetOpenEBSNamespace() string {
return os.Getenv(openebsNamespaceEnv)
}

// GetUpgradeTaskLabel gets the upgradeTask label set to
// the UPGRADE_TASK_LABEL env
func GetUpgradeTaskLabel() string {
return os.Getenv(upgradeTaskLabel)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.13
require (
github.com/hashicorp/go-version v1.2.0
github.com/kubernetes-csi/external-snapshotter/v2 v2.1.1
github.com/openebs/api v1.10.0-RC1.0.20200602151240-2b7d2bdbe1ef
github.com/openebs/api v1.11.1-0.20200625121525-4ef7efa4b876
github.com/openebs/maya v0.0.0-20200602143918-71415115098d
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.0.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/openebs/api v1.10.0-RC1.0.20200602151240-2b7d2bdbe1ef h1:p66ZTG26pNr7TIxOMLmXvJcKjmIxIa+xsQ5Xw0hhJA4=
github.com/openebs/api v1.10.0-RC1.0.20200602151240-2b7d2bdbe1ef/go.mod h1:TASujm6H1LGdx43MN7Dab1xdAqR7MVU8bsS74Ywop5w=
github.com/openebs/api v1.11.1-0.20200625121525-4ef7efa4b876 h1:c6HE7cROx9mC+yJ8h9SO8J1PPAxEatbpw+vH9TpSWj0=
github.com/openebs/api v1.11.1-0.20200625121525-4ef7efa4b876/go.mod h1:TASujm6H1LGdx43MN7Dab1xdAqR7MVU8bsS74Ywop5w=
github.com/openebs/maya v0.0.0-20200602143918-71415115098d h1:o8RIc8RzeZkUlzYM+Sg07wRdekIHytCTMaAhFl8Yams=
github.com/openebs/maya v0.0.0-20200602143918-71415115098d/go.mod h1:QQY9cOHKQwZ73qbv6O//UYUBLNV2S0MRDIfG7t5KOCk=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
Expand Down
37 changes: 35 additions & 2 deletions pkg/upgrade/upgrader/cstor_cspc.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ package upgrader
import (
"time"

apis "github.com/openebs/api/pkg/apis/cstor/v1"
cstor "github.com/openebs/api/pkg/apis/cstor/v1"
apis "github.com/openebs/api/pkg/apis/openebs.io/v1alpha1"
shubham14bajpai marked this conversation as resolved.
Show resolved Hide resolved
"github.com/openebs/upgrade/pkg/upgrade/patch"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog"
Expand Down Expand Up @@ -93,7 +94,7 @@ func getCSPCPatchData(obj *CSPCPatch) error {
return err
}

func transformCSPC(c *apis.CStorPoolCluster, res *ResourcePatch) error {
func transformCSPC(c *cstor.CStorPoolCluster, res *ResourcePatch) error {
c.VersionDetails.Desired = res.To
return nil
}
Expand Down Expand Up @@ -135,8 +136,40 @@ func (obj *CSPCPatch) Upgrade() error {
)
err = dependant.Upgrade()
if err != nil {
utaskObj, uerr := obj.OpenebsClientset.OpenebsV1alpha1().
UpgradeTasks(obj.OpenebsNamespace).
Get("upgrade-cstor-cspi-"+cspiObj.Name, metav1.GetOptions{})
if uerr != nil && isUpgradeTaskJob {
return uerr
}
backoffLimit, uerr := getBackoffLimit(obj.OpenebsNamespace, obj.Client)
if uerr != nil && isUpgradeTaskJob {
return uerr
}
utaskObj.Status.Retries = utaskObj.Status.Retries + 1
if utaskObj.Status.Retries == backoffLimit {
utaskObj.Status.Phase = apis.UpgradeError
utaskObj.Status.CompletedTime = metav1.Now()
}
_, uerr = obj.OpenebsClientset.OpenebsV1alpha1().UpgradeTasks(obj.OpenebsNamespace).
Update(utaskObj)
if uerr != nil && isUpgradeTaskJob {
return uerr
}
return err
}
utaskObj, uerr := obj.OpenebsClientset.OpenebsV1alpha1().UpgradeTasks(obj.OpenebsNamespace).
Get("upgrade-cstor-cspi-"+cspiObj.Name, metav1.GetOptions{})
if uerr != nil && isUpgradeTaskJob {
return uerr
}
utaskObj.Status.Phase = apis.UpgradeSuccess
utaskObj.Status.CompletedTime = metav1.Now()
_, uerr = obj.OpenebsClientset.OpenebsV1alpha1().UpgradeTasks(obj.OpenebsNamespace).
Update(utaskObj)
if uerr != nil && isUpgradeTaskJob {
return uerr
}
}
err = obj.CSPCUpgrade()
if err != nil {
Expand Down
Loading