Skip to content
This repository has been archived by the owner on Oct 10, 2023. It is now read-only.

Commit

Permalink
Add reconcilliation wait for repository operations and package update
Browse files Browse the repository at this point in the history
Signed-off-by: Marjan Alavi <malavi@vmware.com>
  • Loading branch information
maralavi committed Sep 28, 2021
1 parent 5b764f3 commit 5158c6c
Show file tree
Hide file tree
Showing 22 changed files with 358 additions and 171 deletions.
5 changes: 2 additions & 3 deletions cmd/cli/plugin/package/package_install.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,11 @@ func packageInstall(_ *cobra.Command, args []string) error {
Err: make(chan error),
Done: make(chan struct{}),
}
go pkgClient.InstallPackage(packageInstallOp, pp, false)
go pkgClient.InstallPackage(packageInstallOp, pp, tkgpackagedatamodel.OperationTypeInstall)

initialMsg := fmt.Sprintf("Installing package '%s'", packageInstallOp.PackageName)
if err := displayProgress(initialMsg, pp); err != nil {
if err.Error() == tkgpackagedatamodel.ErrPackageAlreadyInstalled {
log.Warningf("package install '%s' already exists in namespace '%s'", packageInstallOp.PkgInstallName, packageInstallOp.Namespace)
if isNonCriticalErrorMessage(err.Error(), packageInstallOp.PkgInstallName, packageInstallOp.Namespace) {
return nil
}
return err
Expand Down
24 changes: 22 additions & 2 deletions cmd/cli/plugin/package/package_installed_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ func packageUninstall(_ *cobra.Command, args []string) error {

initialMsg := fmt.Sprintf("Uninstalling package '%s' from namespace '%s'", packageInstalledOp.PkgInstallName, packageInstalledOp.Namespace)
if err := displayProgress(initialMsg, pp); err != nil {
if err.Error() == tkgpackagedatamodel.ErrPackageNotInstalled {
log.Warningf(fmt.Sprintf("package '%s' is not installed in namespace '%s'. Deleted previously installed resources", packageInstalledOp.PkgInstallName, packageInstalledOp.Namespace))
if isNonCriticalErrorMessage(err.Error(), packageInstalledOp.PkgInstallName, packageInstalledOp.Namespace) {
return nil
}
return err
Expand All @@ -67,3 +66,24 @@ func packageUninstall(_ *cobra.Command, args []string) error {
log.Infof("\n %s", fmt.Sprintf("Uninstalled package '%s' from namespace '%s'", packageInstalledOp.PkgInstallName, packageInstalledOp.Namespace))
return nil
}

func isNonCriticalErrorMessage(errMsg string, options ...string) bool {
switch errMsg {
case tkgpackagedatamodel.ErrPackageAlreadyInstalled:
log.Warningf("\npackage install '%s' already exists in namespace '%s'", options[0], options[1])
return true
case tkgpackagedatamodel.ErrPackageNotInstalled:
log.Warningf("\npackage '%s' is not installed in namespace '%s'. Deleted previously installed resources", options[0], options[1])
return true
case tkgpackagedatamodel.ErrRepoNameAlreadyExists:
log.Warningf("\npackage repository name '%s' already exists in namespace '%s'", options[0], options[1])
return true
case tkgpackagedatamodel.ErrRepoURLAlreadyExists:
log.Warningf("\npackage repository URL '%s' already exists in namespace '%s'", options[2], options[1])
return true
case tkgpackagedatamodel.ErrRepoNotExists:
log.Warningf("\npackage repository '%s' does not exist in namespace '%s'", options[0], options[1])
return true
}
return false
}
2 changes: 1 addition & 1 deletion cmd/cli/plugin/package/package_installed_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func packageUpdate(_ *cobra.Command, args []string) error {
if err := displayProgress(initialMsg, pp); err != nil {
return err
}
log.Infof("\n %s", fmt.Sprintf("Updated package install '%s' in namespace '%s'", packageInstalledOp.PkgInstallName, packageInstalledOp.Namespace))

log.Infof("\n %s", fmt.Sprintf("Updated package install '%s' in namespace '%s'", packageInstalledOp.PkgInstallName, packageInstalledOp.Namespace))
return nil
}
21 changes: 14 additions & 7 deletions cmd/cli/plugin/package/repository_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (

"github.com/spf13/cobra"

"github.com/vmware-tanzu/tanzu-framework/pkg/v1/cli/component"
"github.com/vmware-tanzu/tanzu-framework/pkg/v1/tkg/log"
"github.com/vmware-tanzu/tanzu-framework/pkg/v1/tkg/tkgpackageclient"
"github.com/vmware-tanzu/tanzu-framework/pkg/v1/tkg/tkgpackagedatamodel"
)

var repositoryAddCmd = &cobra.Command{
Expand All @@ -26,6 +26,9 @@ var repositoryAddCmd = &cobra.Command{
func init() {
repositoryAddCmd.Flags().StringVarP(&repoOp.RepositoryURL, "url", "", "", "OCI registry url for package repository bundle")
repositoryAddCmd.Flags().BoolVarP(&repoOp.CreateNamespace, "create-namespace", "", false, "Create namespace if the target namespace does not exist, optional")
repositoryAddCmd.Flags().BoolVarP(&repoOp.Wait, "wait", "", true, "Wait for the package repository reconciliation to complete, optional. To disable wait, specify --wait=false")
repositoryAddCmd.Flags().DurationVarP(&repoOp.PollInterval, "poll-interval", "", tkgpackagedatamodel.DefaultPollInterval, "Time interval between subsequent polls of package repository reconciliation status, optional")
repositoryAddCmd.Flags().DurationVarP(&repoOp.PollTimeout, "poll-timeout", "", tkgpackagedatamodel.DefaultPollTimeout, "Timeout value for polls of package repository reconciliation status, optional")
repositoryAddCmd.MarkFlagRequired("url") //nolint
repositoryCmd.AddCommand(repositoryAddCmd)
}
Expand All @@ -38,17 +41,21 @@ func repositoryAdd(cmd *cobra.Command, args []string) error {
return err
}

_, err = component.NewOutputWriterWithSpinner(cmd.OutOrStdout(), outputFormat,
fmt.Sprintf("Adding package repository '%s'...", repoOp.RepositoryName), true)
if err != nil {
return err
pp := &tkgpackagedatamodel.PackageProgress{
ProgressMsg: make(chan string, 10),
Err: make(chan error),
Done: make(chan struct{}),
}
go pkgClient.AddRepository(repoOp, pp, tkgpackagedatamodel.OperationTypeInstall)

if err := pkgClient.AddRepository(repoOp); err != nil {
initialMsg := fmt.Sprintf("Adding package repository '%s'", repoOp.RepositoryName)
if err := displayProgress(initialMsg, pp); err != nil {
if isNonCriticalErrorMessage(err.Error(), repoOp.RepositoryName, repoOp.Namespace, repoOp.RepositoryURL) {
return nil
}
return err
}

log.Infof("\n Added package repository '%s'", repoOp.RepositoryName)

return nil
}
27 changes: 15 additions & 12 deletions cmd/cli/plugin/package/repository_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/vmware-tanzu/tanzu-framework/pkg/v1/cli/component"
"github.com/vmware-tanzu/tanzu-framework/pkg/v1/tkg/log"
"github.com/vmware-tanzu/tanzu-framework/pkg/v1/tkg/tkgpackageclient"
"github.com/vmware-tanzu/tanzu-framework/pkg/v1/tkg/tkgpackagedatamodel"
)

var repositoryDeleteCmd = &cobra.Command{
Expand All @@ -26,6 +26,9 @@ var repositoryDeleteCmd = &cobra.Command{

func init() {
repositoryDeleteCmd.Flags().BoolVarP(&repoOp.IsForceDelete, "force", "f", false, "Force deletion of the package repository, optional")
repositoryDeleteCmd.Flags().BoolVarP(&repoOp.Wait, "wait", "", true, "Wait for the package repository reconciliation to complete, optional. To disable wait, specify --wait=false")
repositoryDeleteCmd.Flags().DurationVarP(&repoOp.PollInterval, "poll-interval", "", tkgpackagedatamodel.DefaultPollInterval, "Time interval between subsequent polls of package repository reconciliation status, optional")
repositoryDeleteCmd.Flags().DurationVarP(&repoOp.PollTimeout, "poll-timeout", "", tkgpackagedatamodel.DefaultPollTimeout, "Timeout value for polls of package repository reconciliation status, optional")
repositoryCmd.AddCommand(repositoryDeleteCmd)
}

Expand All @@ -41,22 +44,22 @@ func repositoryDelete(cmd *cobra.Command, args []string) error {
return err
}

_, err = component.NewOutputWriterWithSpinner(cmd.OutOrStdout(), outputFormat,
fmt.Sprintf("Deleting package repository '%s'...", repoOp.RepositoryName), true)
if err != nil {
return err
pp := &tkgpackagedatamodel.PackageProgress{
ProgressMsg: make(chan string, 10),
Err: make(chan error),
Done: make(chan struct{}),
}

found, err := pkgClient.DeleteRepository(repoOp)
if !found {
log.Warningf("\n package repository '%s' does not exist in namespace '%s'", repoOp.RepositoryName, repoOp.Namespace)
return nil
}
if err != nil {
go pkgClient.DeleteRepository(repoOp, pp)

initialMsg := fmt.Sprintf("Deleting package repository '%s'", repoOp.RepositoryName)
if err := displayProgress(initialMsg, pp); err != nil {
if isNonCriticalErrorMessage(err.Error(), repoOp.RepositoryName, repoOp.Namespace) {
return nil
}
return err
}

log.Infof("\n Deleted package repository '%s' from namespace '%s'", repoOp.RepositoryName, repoOp.Namespace)

return nil
}
18 changes: 11 additions & 7 deletions cmd/cli/plugin/package/repository_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (

"github.com/spf13/cobra"

"github.com/vmware-tanzu/tanzu-framework/pkg/v1/cli/component"
"github.com/vmware-tanzu/tanzu-framework/pkg/v1/tkg/log"
"github.com/vmware-tanzu/tanzu-framework/pkg/v1/tkg/tkgpackageclient"
"github.com/vmware-tanzu/tanzu-framework/pkg/v1/tkg/tkgpackagedatamodel"
)

var repositoryUpdateCmd = &cobra.Command{
Expand All @@ -27,6 +27,9 @@ func init() {
repositoryUpdateCmd.Flags().StringVarP(&repoOp.RepositoryURL, "url", "", "", "OCI registry url for package repository bundle")
repositoryUpdateCmd.Flags().BoolVarP(&repoOp.CreateRepository, "create", "", false, "Creates the package repository if it does not exist, optional")
repositoryUpdateCmd.Flags().BoolVarP(&repoOp.CreateNamespace, "create-namespace", "", false, "Create namespace if the target namespace does not exist, optional")
repositoryUpdateCmd.Flags().BoolVarP(&repoOp.Wait, "wait", "", true, "Wait for the package repository reconciliation to complete, optional. To disable wait, specify --wait=false")
repositoryUpdateCmd.Flags().DurationVarP(&repoOp.PollInterval, "poll-interval", "", tkgpackagedatamodel.DefaultPollInterval, "Time interval between subsequent polls of package repository reconciliation status, optional")
repositoryUpdateCmd.Flags().DurationVarP(&repoOp.PollTimeout, "poll-timeout", "", tkgpackagedatamodel.DefaultPollTimeout, "Timeout value for polls of package repository reconciliation status, optional")
repositoryUpdateCmd.MarkFlagRequired("url") //nolint
repositoryCmd.AddCommand(repositoryUpdateCmd)
}
Expand All @@ -39,17 +42,18 @@ func repositoryUpdate(cmd *cobra.Command, args []string) error {
return err
}

_, err = component.NewOutputWriterWithSpinner(cmd.OutOrStdout(), outputFormat,
fmt.Sprintf("Updating package repository '%s'...", repoOp.RepositoryName), true)
if err != nil {
return err
pp := &tkgpackagedatamodel.PackageProgress{
ProgressMsg: make(chan string, 10),
Err: make(chan error),
Done: make(chan struct{}),
}
go pkgClient.UpdateRepository(repoOp, pp)

if err := pkgClient.UpdateRepository(repoOp); err != nil {
initialMsg := fmt.Sprintf("Updating package repository '%s'", repoOp.RepositoryName)
if err := displayProgress(initialMsg, pp); err != nil {
return err
}

log.Infof("\n Updated package repository '%s' in namespace '%s'", repoOp.RepositoryName, repoOp.Namespace)

return nil
}
14 changes: 13 additions & 1 deletion cmd/cli/plugin/package/test/lib/package_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ func (p *packagePlugin) AddRepository(o *tkgpackagedatamodel.RepositoryOptions)
if o.CreateNamespace {
cmd += fmt.Sprintf(" --create-namespace")
}
if !o.Wait {
cmd += fmt.Sprintf(" --wait=true")
}
cmd = p.addKubeconfig(cmd)
cmd = p.addGlobalOptions(cmd)
result.Stdout, result.Stderr, result.Error = clitest.Exec(cmd)
Expand Down Expand Up @@ -154,6 +157,9 @@ func (p *packagePlugin) UpdateRepository(o *tkgpackagedatamodel.RepositoryOption
if o.CreateRepository {
cmd += fmt.Sprintf(" --create")
}
if !o.Wait {
cmd += fmt.Sprintf(" --wait=true")
}
cmd = p.addKubeconfig(cmd)
cmd = p.addGlobalOptions(cmd)
result.Stdout, result.Stderr, result.Error = clitest.Exec(cmd)
Expand All @@ -169,6 +175,9 @@ func (p *packagePlugin) DeleteRepository(o *tkgpackagedatamodel.RepositoryOption
if o.IsForceDelete {
cmd += fmt.Sprintf(" --force")
}
if !o.Wait {
cmd += fmt.Sprintf(" --wait=true")
}
cmd = p.addKubeconfig(cmd)
cmd = p.addGlobalOptions(cmd)
result.Stdout, result.Stderr, result.Error = clitest.Exec(cmd)
Expand Down Expand Up @@ -253,7 +262,7 @@ func (p *packagePlugin) CreateInstalledPackage(o *tkgpackagedatamodel.PackageOpt
cmd += fmt.Sprintf(" --service-account-name %s", o.ServiceAccountName)
}
if !o.Wait {
cmd += fmt.Sprintf(" --wait=false")
cmd += fmt.Sprintf(" --wait=true")
}
if o.PollInterval != 0 {
cmd += fmt.Sprintf(" --poll-interval %s", o.PollInterval)
Expand Down Expand Up @@ -295,6 +304,9 @@ func (p *packagePlugin) UpdateInstalledPackage(o *tkgpackagedatamodel.PackageOpt
if o.ValuesFile != "" {
cmd += fmt.Sprintf(" --values-file %s", o.ValuesFile)
}
if !o.Wait {
cmd += fmt.Sprintf(" --wait=true")
}
cmd = p.addKubeconfig(cmd)
cmd = p.addGlobalOptions(cmd)
result.Stdout, result.Stderr, result.Error = clitest.Exec(cmd)
Expand Down
8 changes: 4 additions & 4 deletions pkg/v1/tkg/tkgpackageclient/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ import (
// TKGPackageClient is the TKG package client interface
type TKGPackageClient interface {
AddImagePullSecret(o *tkgpackagedatamodel.ImagePullSecretOptions) error
AddRepository(o *tkgpackagedatamodel.RepositoryOptions) error
AddRepository(o *tkgpackagedatamodel.RepositoryOptions, packageProgress *tkgpackagedatamodel.PackageProgress, operationType tkgpackagedatamodel.OperationType)
DeleteImagePullSecret(o *tkgpackagedatamodel.ImagePullSecretOptions) (bool, error)
DeleteRepository(o *tkgpackagedatamodel.RepositoryOptions) (bool, error)
DeleteRepository(o *tkgpackagedatamodel.RepositoryOptions, packageProgress *tkgpackagedatamodel.PackageProgress)
GetPackageInstall(o *tkgpackagedatamodel.PackageOptions) (*kappipkg.PackageInstall, error)
GetPackage(o *tkgpackagedatamodel.PackageOptions) (*kapppkg.PackageMetadata, *kapppkg.Package, error)
GetRepository(o *tkgpackagedatamodel.RepositoryOptions) (*kappipkg.PackageRepository, error)
InstallPackage(o *tkgpackagedatamodel.PackageOptions, packageProgress *tkgpackagedatamodel.PackageProgress, update bool)
InstallPackage(o *tkgpackagedatamodel.PackageOptions, packageProgress *tkgpackagedatamodel.PackageProgress, operationType tkgpackagedatamodel.OperationType)
ListImagePullSecrets(o *tkgpackagedatamodel.ImagePullSecretOptions) (*corev1.SecretList, error)
ListPackageInstalls(o *tkgpackagedatamodel.PackageOptions) (*kappipkg.PackageInstallList, error)
ListPackageMetadata(o *tkgpackagedatamodel.PackageAvailableOptions) (*kapppkg.PackageMetadataList, error)
Expand All @@ -32,5 +32,5 @@ type TKGPackageClient interface {
ListSecretExports(o *tkgpackagedatamodel.ImagePullSecretOptions) (*secretgen.SecretExportList, error)
UninstallPackage(o *tkgpackagedatamodel.PackageOptions, packageProgress *tkgpackagedatamodel.PackageProgress)
UpdatePackage(o *tkgpackagedatamodel.PackageOptions, packageProgress *tkgpackagedatamodel.PackageProgress)
UpdateRepository(o *tkgpackagedatamodel.RepositoryOptions) error
UpdateRepository(o *tkgpackagedatamodel.RepositoryOptions, progress *tkgpackagedatamodel.PackageProgress)
}
43 changes: 8 additions & 35 deletions pkg/v1/tkg/tkgpackageclient/package_install.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ import (
rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
crtclient "sigs.k8s.io/controller-runtime/pkg/client"

kappctrl "github.com/vmware-tanzu/carvel-kapp-controller/pkg/apis/kappctrl/v1alpha1"
kappipkg "github.com/vmware-tanzu/carvel-kapp-controller/pkg/apis/packaging/v1alpha1"
versions "github.com/vmware-tanzu/carvel-vendir/pkg/vendir/versions/v1alpha1"

Expand All @@ -26,12 +24,13 @@ import (
)

const (
msgRunPackageInstalledDelete = "\n\nPlease consider using 'tanzu package installed delete' to delete the already created associated resources\n"
msgRunPackageInstalledUpdate = "\n\nPlease consider using 'tanzu package installed update' to update the installed package with correct settings\n"
msgRunPackageInstalledDelete = "\n\nPlease consider using 'tanzu package installed delete' to delete the already created associated resources\n"
msgRunPackageInstalledUpdate = "\n\nPlease consider using 'tanzu package installed update' to update the installed package with correct settings\n"
msgRunPackageRepositoryUpdate = "\n\nPlease consider using 'tanzu package repository update' to update the package repository with correct settings\n"
)

// InstallPackage installs the PackageInstall and its associated resources in the cluster
func (p *pkgClient) InstallPackage(o *tkgpackagedatamodel.PackageOptions, progress *tkgpackagedatamodel.PackageProgress, update bool) { //nolint:gocyclo
func (p *pkgClient) InstallPackage(o *tkgpackagedatamodel.PackageOptions, progress *tkgpackagedatamodel.PackageProgress, operationType tkgpackagedatamodel.OperationType) { //nolint:gocyclo
var (
pkgInstall *kappipkg.PackageInstall
err error
Expand All @@ -40,7 +39,7 @@ func (p *pkgClient) InstallPackage(o *tkgpackagedatamodel.PackageOptions, progre
)

defer func() {
packageInstallProgressCleanup(err, progress, update)
installProgressCleanup(err, progress, operationType)
}()

if pkgInstall, err = p.kappClient.GetPackageInstall(o.PkgInstallName, o.Namespace); err != nil {
Expand Down Expand Up @@ -121,18 +120,18 @@ func (p *pkgClient) InstallPackage(o *tkgpackagedatamodel.PackageOptions, progre
}

if o.Wait {
if err = p.waitForPackageInstallation(o, progress.ProgressMsg); err != nil {
if err = p.waitForResourceInstallation(o.PkgInstallName, o.Namespace, o.PollInterval, o.PollTimeout, progress.ProgressMsg, tkgpackagedatamodel.ResourceTypePackageInstall); err != nil {
log.Warning(msgRunPackageInstalledUpdate)
return
}
}
}

func packageInstallProgressCleanup(err error, progress *tkgpackagedatamodel.PackageProgress, update bool) {
func installProgressCleanup(err error, progress *tkgpackagedatamodel.PackageProgress, operationType tkgpackagedatamodel.OperationType) {
if err != nil {
progress.Err <- err
}
if !update {
if operationType == tkgpackagedatamodel.OperationTypeInstall {
close(progress.ProgressMsg)
close(progress.Done)
}
Expand Down Expand Up @@ -276,29 +275,3 @@ func (p *pkgClient) createServiceAccount(o *tkgpackagedatamodel.PackageOptions)

return true, nil
}

// waitForPackageInstallation waits until the package get installed successfully or a failure happen
func (p *pkgClient) waitForPackageInstallation(o *tkgpackagedatamodel.PackageOptions, progress chan string) error {
if err := wait.Poll(o.PollInterval, o.PollTimeout, func() (done bool, err error) {
pkg, err := p.kappClient.GetPackageInstall(o.PkgInstallName, o.Namespace)
if err != nil {
return false, err
}
for _, cond := range pkg.Status.Conditions {
if progress != nil {
progress <- fmt.Sprintf("Package install status: %s", cond.Type)
}
switch cond.Type {
case kappctrl.ReconcileSucceeded:
return true, nil
case kappctrl.ReconcileFailed:
return false, fmt.Errorf("package reconciliation failed: %s", pkg.Status.UsefulErrorMessage)
}
}
return false, nil
}); err != nil {
return err
}

return nil
}
3 changes: 1 addition & 2 deletions pkg/v1/tkg/tkgpackageclient/package_install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ var _ = Describe("Install Package", func() {
}
options = opts
progress *tkgpackagedatamodel.PackageProgress
update bool
)

JustBeforeEach(func() {
Expand All @@ -104,7 +103,7 @@ var _ = Describe("Install Package", func() {
Done: make(chan struct{}),
}
ctl = &pkgClient{kappClient: kappCtl}
go ctl.InstallPackage(&options, progress, update)
go ctl.InstallPackage(&options, progress, tkgpackagedatamodel.OperationTypeInstall)
err = testReceive(progress)
})

Expand Down
Loading

0 comments on commit 5158c6c

Please sign in to comment.