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

internal/olm: get installed version from cluster instead of required CLI argument #1634

Merged
merged 12 commits into from
Aug 15, 2019
Merged
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
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
55 changes: 53 additions & 2 deletions internal/olm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"io"
"io/ioutil"
"net/http"
"strings"
"sync"
"text/tabwriter"
"time"
Expand All @@ -35,6 +36,7 @@ import (
log "github.com/sirupsen/logrus"
appsv1 "k8s.io/api/apps/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand All @@ -57,6 +59,8 @@ var (
packageServerKey = types.NamespacedName{Namespace: olmNamespace, Name: "packageserver"}
)

var ErrOLMNotInstalled = errors.New("no existing installation found")

type Client struct {
KubeClient client.Client
HTTPClient http.Client
Expand Down Expand Up @@ -154,7 +158,7 @@ func (c Client) UninstallVersion(ctx context.Context, version string) error {

status := c.getStatus(ctx, resources)
if !status.HasExistingResources() {
return errors.New("no existing installation found")
return ErrOLMNotInstalled
}

log.Infof("Uninstalling resources for version %q", version)
Expand All @@ -164,6 +168,53 @@ 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 {
if strings.HasPrefix(csv.GetName(), packageServerCSVNamePrefix) {
// 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), nil
}

const (
packageServerCSVNamePrefix = "packageserver."
packageServerOLMVersionLabel = "olm.version"
)

func getOLMVersionFromPackageServerCSV(csv *olmapiv1alpha1.ClusterServiceVersion) string {
// 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[packageServerOLMVersionLabel]; ok {
return ver
}
}
// Fall back to getting OLM version from package server CSV name. Versions
// of OLM <= 0.10.1 are not labelled with packageServerOLMVersionLabel.
ver := strings.TrimPrefix(csv.GetName(), packageServerCSVNamePrefix)
// OLM releases do not have a "v" prefix but CSV versions often do.
ver = strings.TrimPrefix(ver, "v")
return ver
}

func (c Client) GetStatus(ctx context.Context, version string) (*Status, error) {
resources, err := c.getResources(ctx, version)
if err != nil {
Expand All @@ -172,7 +223,7 @@ func (c Client) GetStatus(ctx context.Context, version string) (*Status, error)

status := c.getStatus(ctx, resources)
if !status.HasExistingResources() {
return nil, errors.New("no existing installation found")
return nil, ErrOLMNotInstalled
}
return &status, 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 %s", 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")
}