github.com/fabianvf/ocp-release-operator-sdk@v0.0.0-20190426141702-57620ee2f090/internal/pkg/scaffold/olm-catalog/csv_test.go (about)

     1  // Copyright 2018 The Operator-SDK Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package catalog
    16  
    17  import (
    18  	"bytes"
    19  	"io"
    20  	"io/ioutil"
    21  	"os"
    22  	"path/filepath"
    23  	"testing"
    24  
    25  	"github.com/operator-framework/operator-sdk/internal/pkg/scaffold"
    26  	"github.com/operator-framework/operator-sdk/internal/pkg/scaffold/input"
    27  	"github.com/operator-framework/operator-sdk/internal/util/diffutil"
    28  	"github.com/operator-framework/operator-sdk/internal/util/fileutil"
    29  
    30  	"github.com/coreos/go-semver/semver"
    31  	"github.com/ghodss/yaml"
    32  	olmapiv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
    33  	olminstall "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
    34  	"github.com/spf13/afero"
    35  )
    36  
    37  const testDataDir = "testdata"
    38  
    39  var testDeployDir = filepath.Join(testDataDir, scaffold.DeployDir)
    40  
    41  func TestCSVNew(t *testing.T) {
    42  	buf := &bytes.Buffer{}
    43  	s := &scaffold.Scaffold{
    44  		GetWriter: func(_ string, _ os.FileMode) (io.Writer, error) {
    45  			return buf, nil
    46  		},
    47  	}
    48  	csvVer := "0.1.0"
    49  	projectName := "app-operator"
    50  
    51  	sc := &CSV{CSVVersion: csvVer, pathPrefix: testDataDir}
    52  	err := s.Execute(&input.Config{ProjectName: projectName}, sc)
    53  	if err != nil {
    54  		t.Fatalf("Failed to execute the scaffold: (%v)", err)
    55  	}
    56  
    57  	// Get the expected CSV manifest from test data dir.
    58  	csvExpBytes, err := afero.ReadFile(s.Fs, sc.getCSVPath(csvVer))
    59  	if err != nil {
    60  		t.Fatal(err)
    61  	}
    62  	csvExp := string(csvExpBytes)
    63  	if csvExp != buf.String() {
    64  		diffs := diffutil.Diff(csvExp, buf.String())
    65  		t.Errorf("Expected vs actual differs.\n%v", diffs)
    66  	}
    67  }
    68  
    69  func writeOSPathToFS(fromFs, toFs afero.Fs, root string) error {
    70  	if _, err := fromFs.Stat(root); err != nil {
    71  		return err
    72  	}
    73  	return afero.Walk(fromFs, root, func(path string, info os.FileInfo, err error) error {
    74  		if err != nil || info == nil {
    75  			return err
    76  		}
    77  		if !info.IsDir() {
    78  			b, err := afero.ReadFile(fromFs, path)
    79  			if err != nil {
    80  				return err
    81  			}
    82  			return afero.WriteFile(toFs, path, b, fileutil.DefaultFileMode)
    83  		}
    84  		return nil
    85  	})
    86  }
    87  
    88  func TestCSVFromOld(t *testing.T) {
    89  	s := &scaffold.Scaffold{Fs: afero.NewMemMapFs()}
    90  	projectName := "app-operator"
    91  	oldCSVVer, newCSVVer := "0.1.0", "0.2.0"
    92  
    93  	// Write all files in testdata/deploy to fs so manifests are present when
    94  	// writing a new CSV.
    95  	if err := writeOSPathToFS(afero.NewOsFs(), s.Fs, testDeployDir); err != nil {
    96  		t.Fatalf("Failed to write %s to in-memory test fs: (%v)", testDeployDir, err)
    97  	}
    98  
    99  	sc := &CSV{
   100  		CSVVersion:  newCSVVer,
   101  		FromVersion: oldCSVVer,
   102  		pathPrefix:  testDataDir,
   103  	}
   104  	err := s.Execute(&input.Config{ProjectName: projectName}, sc)
   105  	if err != nil {
   106  		t.Fatalf("Failed to execute the scaffold: (%v)", err)
   107  	}
   108  
   109  	// Check if a new file was written at the expected path.
   110  	newCSVPath := sc.getCSVPath(newCSVVer)
   111  	newCSV, newExists, err := getCSVFromFSIfExists(s.Fs, newCSVPath)
   112  	if err != nil {
   113  		t.Fatalf("Failed to get new CSV %s: (%v)", newCSVPath, err)
   114  	}
   115  	if !newExists {
   116  		t.Fatalf("New CSV does not exist at %s", newCSVPath)
   117  	}
   118  
   119  	expName := getCSVName(projectName, newCSVVer)
   120  	if newCSV.ObjectMeta.Name != expName {
   121  		t.Errorf("Expected CSV metadata.name %s, got %s", expName, newCSV.ObjectMeta.Name)
   122  	}
   123  	expReplaces := getCSVName(projectName, oldCSVVer)
   124  	if newCSV.Spec.Replaces != expReplaces {
   125  		t.Errorf("Expected CSV spec.replaces %s, got %s", expReplaces, newCSV.Spec.Replaces)
   126  	}
   127  }
   128  
   129  func TestUpdateVersion(t *testing.T) {
   130  	projectName := "app-operator"
   131  	oldCSVVer, newCSVVer := "0.1.0", "0.2.0"
   132  	sc := &CSV{
   133  		Input:      input.Input{ProjectName: projectName},
   134  		CSVVersion: newCSVVer,
   135  		pathPrefix: testDataDir,
   136  	}
   137  	csvExpBytes, err := ioutil.ReadFile(sc.getCSVPath(oldCSVVer))
   138  	if err != nil {
   139  		t.Fatal(err)
   140  	}
   141  	csv := &olmapiv1alpha1.ClusterServiceVersion{}
   142  	if err := yaml.Unmarshal(csvExpBytes, csv); err != nil {
   143  		t.Fatal(err)
   144  	}
   145  
   146  	if err := sc.updateCSVVersions(csv); err != nil {
   147  		t.Fatalf("Failed to update csv with version %s: (%v)", newCSVVer, err)
   148  	}
   149  
   150  	wantedSemver := semver.New(newCSVVer)
   151  	if !csv.Spec.Version.Equal(*wantedSemver) {
   152  		t.Errorf("Wanted csv version %v, got %v", *wantedSemver, csv.Spec.Version)
   153  	}
   154  	wantedName := getCSVName(projectName, newCSVVer)
   155  	if csv.ObjectMeta.Name != wantedName {
   156  		t.Errorf("Wanted csv name %s, got %s", wantedName, csv.ObjectMeta.Name)
   157  	}
   158  
   159  	var resolver *olminstall.StrategyResolver
   160  	stratInterface, err := resolver.UnmarshalStrategy(csv.Spec.InstallStrategy)
   161  	if err != nil {
   162  		t.Fatal(err)
   163  	}
   164  	strat, ok := stratInterface.(*olminstall.StrategyDetailsDeployment)
   165  	if !ok {
   166  		t.Fatalf("Strategy of type %T was not StrategyDetailsDeployment", stratInterface)
   167  	}
   168  	csvPodImage := strat.DeploymentSpecs[0].Spec.Template.Spec.Containers[0].Image
   169  	// updateCSVVersions should not update podspec image.
   170  	wantedImage := "quay.io/example-inc/operator:v0.1.0"
   171  	if csvPodImage != wantedImage {
   172  		t.Errorf("Podspec image changed from %s to %s", wantedImage, csvPodImage)
   173  	}
   174  
   175  	wantedReplaces := getCSVName(projectName, "0.1.0")
   176  	if csv.Spec.Replaces != wantedReplaces {
   177  		t.Errorf("Wanted csv replaces %s, got %s", wantedReplaces, csv.Spec.Replaces)
   178  	}
   179  }
   180  
   181  func TestGetDisplayName(t *testing.T) {
   182  	cases := []struct {
   183  		input, wanted string
   184  	}{
   185  		{"Appoperator", "Appoperator"},
   186  		{"appoperator", "Appoperator"},
   187  		{"appoperatoR", "Appoperato R"},
   188  		{"AppOperator", "App Operator"},
   189  		{"appOperator", "App Operator"},
   190  		{"app-operator", "App Operator"},
   191  		{"app-_operator", "App Operator"},
   192  		{"App-operator", "App Operator"},
   193  		{"app-_Operator", "App Operator"},
   194  		{"app--Operator", "App Operator"},
   195  		{"app--_Operator", "App Operator"},
   196  		{"APP", "APP"},
   197  		{"another-AppOperator_againTwiceThrice More", "Another App Operator Again Twice Thrice More"},
   198  	}
   199  
   200  	for _, c := range cases {
   201  		dn := getDisplayName(c.input)
   202  		if dn != c.wanted {
   203  			t.Errorf("Wanted %s, got %s", c.wanted, dn)
   204  		}
   205  	}
   206  }