Skip to content

Commit

Permalink
internal/olm: get installed version from cluster instead of required …
Browse files Browse the repository at this point in the history
…CLI argument (operator-framework#1634)

* internal/olm: get installed version using Client.GetInstalledVersion() in Manager.Status() and Manager.Uninstall()

* cmd/operator-sdk/alpha/olm: remove --version from Status/Uninstall.
--version is only used with Install.

* hack/tests/alpha-olm-subcommands.sh: fix tests

*  CHANGELOG.md,doc/sdk-cli-reference.md: note --version removal from olm uninstall/status
  • Loading branch information
Eric Stroczynski authored Aug 15, 2019
1 parent b4e5306 commit 24f9e36
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 40 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

### Changed
- The Helm operator now uses the CR name for the release name for newly created CRs. Existing CRs will continue to use their existing UID-based release name. When a release name collision occurs (when CRs of different types share the same name), the second CR will fail to install with an error about a duplicate name. ([#1818](https://github.com/operator-framework/operator-sdk/pull/1818))
- Commands [`olm uninstall`](https://github.com/operator-framework/operator-sdk/blob/master/doc/sdk-cli-reference.md#uninstall) and [`olm status`](https://github.com/operator-framework/operator-sdk/blob/master/doc/sdk-cli-reference.md#status) no longer use a `--version` flag to specify OLM version. This information is now retrieved from the running cluster. ([#1634](https://github.com/operator-framework/operator-sdk/pull/1634))

### Deprecated

Expand Down
1 change: 1 addition & 0 deletions cmd/operator-sdk/alpha/olm/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func NewInstallCmd() *cobra.Command {
},
}

cmd.Flags().StringVar(&mgr.Version, "version", olm.DefaultVersion, "version of OLM resources to install")
mgr.AddToFlagSet(cmd.Flags())
return cmd
}
2 changes: 1 addition & 1 deletion cmd/operator-sdk/alpha/olm/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func NewStatusCmd() *cobra.Command {
Short: "Get the status of the Operator Lifecycle Manager installation in your cluster",
RunE: func(cmd *cobra.Command, args []string) error {
if err := mgr.Status(); err != nil {
log.Fatalf("Failed to get OLM status for version %q: %s", mgr.Version, err)
log.Fatalf("Failed to get OLM status: %s", err)
}
return nil
},
Expand Down
2 changes: 1 addition & 1 deletion cmd/operator-sdk/alpha/olm/uninstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func NewUninstallCmd() *cobra.Command {
Short: "Uninstall Operator Lifecycle Manager from your cluster",
RunE: func(cmd *cobra.Command, args []string) error {
if err := mgr.Uninstall(); err != nil {
log.Fatalf("Failed to uninstall OLM version %q: %s", mgr.Version, err)
log.Fatalf("Failed to uninstall OLM: %s", err)
}
return nil
},
Expand Down
24 changes: 7 additions & 17 deletions doc/sdk-cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,6 @@ $ operator-sdk up local --namespace "testing"

### Flags

* `--version` string - version of OLM resources to install, uninstall, or get status about (default: "latest")
* `--timeout` duration - time to wait for the command to complete before failing (default: "2m")

### Available commands
Expand All @@ -577,42 +576,33 @@ then creating all of the necessary resources and waiting for them to become
healthy. When the installation is complete, `olm install` outputs a status summary
of all of the resources that were installed.

##### Flags

* `--version` string - version of OLM resources to install, uninstall, or get status about (default: "latest")

#### uninstall - Uninstalls Operator Lifecycle Manager

##### Use

The `operator-sdk alpha olm uninstall` command uninstalls OLM from a Kubernetes
cluster based on the configured kubeconfig. It works by downloading OLM's
release manifests at a specific version (default: `latest`), checking to see if
release manifests at the version installed in the cluster, checking to see if
any of those resources exist (if none exist, it aborts with an error since OLM
is not installed), and then deletes each resource that is listed in the
downloaded release manifests. It waits until all resources have been fully
cleaned up before returning.

**NOTE**: It is important to use `--version` with the version number that
corresponds to the version that you installed with `olm install`. Not specifying
the version (or using an incorrect version) may cause some resources not be
cleaned up. This can occur if OLM changes its release manifest resources from
one version of OLM to the next.

#### status - Get status of the Operator Lifecycle Manager installation

##### Use

The `operator-sdk alpha olm status` command gets the status of the OLM
installation in a Kubernetes cluster based on the configured kubeconfig. It
works by downloading OLM's release manifests at a specific version (default:
`latest`), checking to see if any of those resources exist (if none exist, it
works by downloading OLM's release manifests at the version installed in the
cluster, checking to see if any of those resources exist (if none exist, it
aborts with an error since OLM is not installed), and printing a summary of the
status of each of those resources as they exist in the cluster.

**NOTE**: It is important to use `--version` with the version number that
corresponds to the version that you installed with `olm install`. Not specifying
the version (or using an incorrect version) may cause some resources to be
missing from the summary and others to be listed as "not found". This can occur
if OLM changes its release manifest resources from one version of OLM to the
next.

[utility_link]: https://github.com/operator-framework/operator-sdk/blob/89bf021063d18b6769bdc551ed08fc37027939d5/pkg/util/k8sutil/k8sutil.go#L140
[k8s-code-generator]: https://github.com/kubernetes/code-generator
[openapi-code-generator]: https://github.com/kubernetes/kube-openapi
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/Masterminds/sprig v0.0.0-20190301161902-9f8fceff796f // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/appscode/jsonpatch v0.0.0-20190108182946-7c0e3b262f30 // indirect
github.com/blang/semver v3.5.1+incompatible
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 // indirect
github.com/coreos/bbolt v1.3.3 // indirect
github.com/coreos/go-semver v0.2.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4=
Expand Down
31 changes: 15 additions & 16 deletions hack/tests/alpha-olm-subcommands.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,35 @@ set -ex

test_version() {
local version="$1"
# If version is "latest", run without --version flag
local ver_flag="--version=${version}"
if [[ "$version" == "latest" ]]; then
ver_flag=""
fi

# Status should fail with OLM not installed
commandoutput=$(operator-sdk alpha olm status --version=${version} 2>&1 || true)
echo $commandoutput | grep -F "Failed to get OLM status for version \\\"${version}\\\": no existing installation found"
commandoutput=$(operator-sdk alpha olm status 2>&1 || true)
echo $commandoutput | grep -F "Failed to get OLM status: no existing installation found"

# Uninstall should fail with OLM not installed
commandoutput=$(operator-sdk alpha olm uninstall --version=${version} 2>&1 || true)
echo $commandoutput | grep -F "Failed to uninstall OLM version \\\"${version}\\\": no existing installation found"
commandoutput=$(operator-sdk alpha olm uninstall 2>&1 || true)
echo $commandoutput | grep -F "Failed to uninstall OLM: no existing installation found"

# Install should succeed with nothing installed
commandoutput=$(operator-sdk alpha olm install --version=${version} 2>&1)
commandoutput=$(operator-sdk alpha olm install $ver_flag 2>&1)
echo $commandoutput | grep -F "Successfully installed OLM version \\\"${version}\\\""

# Install should fail with OLM Installed
commandoutput=$(operator-sdk alpha olm install --version=${version} 2>&1 || true)
commandoutput=$(operator-sdk alpha olm install $ver_flag 2>&1 || true)
echo $commandoutput | grep -F "Failed to install OLM version \\\"${version}\\\": detected existing OLM resources: OLM must be completely uninstalled before installation"

# Status should succeed with OLM installed
# If version is "latest", also run without --version flag
if [[ "$version" == "latest" ]]; then
commandoutput=$(operator-sdk alpha olm status 2>&1)
echo $commandoutput | grep -F "Successfully got OLM status for version \\\"${version}\\\""
fi

commandoutput=$(operator-sdk alpha olm status --version=${version} 2>&1)
echo $commandoutput | grep -F "Successfully got OLM status for version \\\"${version}\\\""
commandoutput=$(operator-sdk alpha olm status 2>&1)
echo $commandoutput | grep -F "Successfully got OLM status"

# Uninstall should succeed with OLM installed
commandoutput=$(operator-sdk alpha olm uninstall --version=${version} 2>&1)
echo $commandoutput | grep -F "Successfully uninstalled OLM version \\\"${version}\\\""
commandoutput=$(operator-sdk alpha olm uninstall 2>&1)
echo $commandoutput | grep -F "Successfully uninstalled OLM"
}

test_version "latest"
Expand Down
62 changes: 62 additions & 0 deletions internal/olm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,25 @@ import (
"io"
"io/ioutil"
"net/http"
"strings"
"time"

olmresourceclient "github.com/operator-framework/operator-sdk/internal/olm/client"

"github.com/blang/semver"
olmapiv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
Expand Down Expand Up @@ -146,6 +151,63 @@ func (c Client) UninstallVersion(ctx context.Context, version string) error {
return nil
}

func (c Client) GetInstalledVersion(ctx context.Context) (string, error) {
opts := client.InNamespace(olmNamespace)
csvs := &olmapiv1alpha1.ClusterServiceVersionList{}
if err := c.KubeClient.List(ctx, opts, csvs); err != nil {
if apierrors.IsNotFound(err) || meta.IsNoMatchError(err) {
return "", ErrOLMNotInstalled
}
return "", errors.Wrap(err, "failed to get OLM version from CSVs")
}
var pkgServerCSV *olmapiv1alpha1.ClusterServiceVersion
for _, csv := range csvs.Items {
name := csv.GetName()
// Check old and new name possibilities.
if name == pkgServerCSVNewName || strings.HasPrefix(name, pkgServerCSVOldNamePrefix) {
// There is more than one version of OLM installed in the cluster,
// so we can't resolve the version being used.
if pkgServerCSV != nil {
return "", errors.New("failed to get OLM version: more than one OLM version installed")
}
pkgServerCSV = &csv
}
}
if pkgServerCSV == nil {
return "", ErrOLMNotInstalled
}
return getOLMVersionFromPackageServerCSV(pkgServerCSV)
}

const (
// Versions pre-0.11 have a versioned name.
pkgServerCSVOldNamePrefix = "packageserver."
// Versions 0.11+ have a fixed name.
pkgServerCSVNewName = "packageserver"
pkgServerOLMVersionLabel = "olm.version"
)

func getOLMVersionFromPackageServerCSV(csv *olmapiv1alpha1.ClusterServiceVersion) (string, error) {
// Package server CSV's from OLM versions > 0.10.1 have a label containing
// the OLM version.
if labels := csv.GetLabels(); labels != nil {
if ver, ok := labels[pkgServerOLMVersionLabel]; ok {
return ver, nil
}
}
// Fall back to getting OLM version from package server CSV name. Versions
// of OLM <= 0.10.1 are not labelled with pkgServerOLMVersionLabel.
ver := strings.TrimPrefix(csv.GetName(), pkgServerCSVOldNamePrefix)
// OLM releases do not have a "v" prefix but CSV versions do.
ver = strings.TrimPrefix(ver, "v")
// Check if a valid semver. Ignore non-nil errors as they are not related
// to the reason OLM version can't be found.
if _, err := semver.Parse(ver); err == nil {
return ver, nil
}
return "", errors.Errorf("no OLM version found in %s CSV spec", csv.GetName())
}

func (c Client) GetStatus(ctx context.Context, version string) (*olmresourceclient.Status, error) {
resources, err := c.getResources(ctx, version)
if err != nil {
Expand Down
19 changes: 14 additions & 5 deletions internal/olm/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,16 @@ func (m *Manager) Uninstall() error {
ctx, cancel := context.WithTimeout(context.Background(), m.Timeout)
defer cancel()

if err := m.Client.UninstallVersion(ctx, m.Version); err != nil {
version, err := m.Client.GetInstalledVersion(ctx)
if err != nil {
return err
}

if err := m.Client.UninstallVersion(ctx, version); err != nil {
return err
}

log.Infof("Successfully uninstalled OLM version %q", m.Version)
log.Infof("Successfully uninstalled OLM version %q", version)
return nil
}

Expand All @@ -108,18 +113,22 @@ func (m *Manager) Status() error {
ctx, cancel := context.WithTimeout(context.Background(), m.Timeout)
defer cancel()

status, err := m.Client.GetStatus(ctx, m.Version)
version, err := m.Client.GetInstalledVersion(ctx)
if err != nil {
return err
}

status, err := m.Client.GetStatus(ctx, version)
if err != nil {
return err
}

log.Infof("Successfully got OLM status for version %q", m.Version)
log.Infof("Successfully got OLM status for version %q", version)
fmt.Print("\n")
fmt.Println(status)
return nil
}

func (m *Manager) AddToFlagSet(fs *pflag.FlagSet) {
fs.StringVar(&m.Version, "version", DefaultVersion, "version of OLM resources to install, uninstall, or get status about")
fs.DurationVar(&m.Timeout, "timeout", DefaultTimeout, "time to wait for the command to complete before failing")
}

0 comments on commit 24f9e36

Please sign in to comment.