@@ -3,6 +3,8 @@ package e2e
33import (
44 "encoding/json"
55 "fmt"
6+ "strings"
7+ "sync"
68 "testing"
79
810 "github.com/coreos/go-semver/semver"
@@ -196,7 +198,7 @@ var (
196198 Selector : & metav1.LabelSelector {
197199 MatchLabels : map [string ]string {"app" : "nginx" },
198200 },
199- Replicas : & doubleInstance ,
201+ Replicas : & singleInstance ,
200202 Template : corev1.PodTemplateSpec {
201203 ObjectMeta : metav1.ObjectMeta {
202204 Labels : map [string ]string {"app" : "nginx" },
@@ -612,3 +614,149 @@ func TestSusbcriptionWithStartingCSV(t *testing.T) {
612614 require .NoError (t , err )
613615}
614616
617+ func TestSubscriptionUpdatesMultipleIntermediates (t * testing.T ) {
618+ defer cleaner .NotifyTestComplete (t , true )
619+
620+ crdPlural := genName ("ins" )
621+ crdName := crdPlural + ".cluster.com"
622+
623+ crd := apiextensions.CustomResourceDefinition {
624+ ObjectMeta : metav1.ObjectMeta {
625+ Name : crdName ,
626+ },
627+ Spec : apiextensions.CustomResourceDefinitionSpec {
628+ Group : "cluster.com" ,
629+ Version : "v1alpha1" ,
630+ Names : apiextensions.CustomResourceDefinitionNames {
631+ Plural : crdPlural ,
632+ Singular : crdPlural ,
633+ Kind : crdPlural ,
634+ ListKind : "list" + crdPlural ,
635+ },
636+ Scope : "Namespaced" ,
637+ },
638+ }
639+
640+ // Create CSV
641+ packageName := genName ("nginx-" )
642+ stableChannel := "stable"
643+
644+ namedStrategy := newNginxInstallStrategy (genName ("dep-" ), nil , nil )
645+ csvA := newCSV ("nginx-a" , testNamespace , "" , * semver .New ("0.1.0" ), []apiextensions.CustomResourceDefinition {crd }, nil , namedStrategy )
646+ csvB := newCSV ("nginx-b" , testNamespace , "nginx-a" , * semver .New ("0.2.0" ), []apiextensions.CustomResourceDefinition {crd }, nil , namedStrategy )
647+ csvC := newCSV ("nginx-c" , testNamespace , "nginx-b" , * semver .New ("0.3.0" ), []apiextensions.CustomResourceDefinition {crd }, nil , namedStrategy )
648+
649+ // Create PackageManifests
650+ manifests := []registry.PackageManifest {
651+ {
652+ PackageName : packageName ,
653+ Channels : []registry.PackageChannel {
654+ {Name : stableChannel , CurrentCSVName : csvA .GetName ()},
655+ },
656+ DefaultChannelName : stableChannel ,
657+ },
658+ }
659+
660+ // Create the CatalogSource with just one version
661+ c := newKubeClient (t )
662+ crc := newCRClient (t )
663+ catalogSourceName := genName ("mock-nginx-" )
664+ _ , cleanupCatalogSource := createInternalCatalogSource (t , c , crc , catalogSourceName , testNamespace , manifests , []apiextensions.CustomResourceDefinition {crd }, []v1alpha1.ClusterServiceVersion {csvA })
665+ defer cleanupCatalogSource ()
666+
667+ // Attempt to get the catalog source before creating install plan
668+ _ , err := fetchCatalogSource (t , crc , catalogSourceName , testNamespace , catalogSourceRegistryPodSynced )
669+ require .NoError (t , err )
670+
671+ subscriptionName := genName ("sub-nginx-" )
672+ cleanupSubscription := createSubscriptionForCatalog (t , crc , testNamespace , subscriptionName , catalogSourceName , packageName , stableChannel , csvA .GetName (), v1alpha1 .ApprovalAutomatic )
673+ defer cleanupSubscription ()
674+
675+ subscription , err := fetchSubscription (t , crc , testNamespace , subscriptionName , subscriptionHasInstallPlanChecker )
676+ require .NoError (t , err )
677+ require .NotNil (t , subscription )
678+
679+ // Wait for csvA to be installed
680+ _ , err = awaitCSV (t , crc , testNamespace , csvA .GetName (), csvSucceededChecker )
681+ require .NoError (t , err )
682+
683+ // Set up async watches that will fail the test if csvB doesn't get created in between csvA and csvC
684+ var wg sync.WaitGroup
685+ go func (t * testing.T ) {
686+ wg .Add (1 )
687+ defer wg .Done ()
688+ _ , err := awaitCSV (t , crc , testNamespace , csvB .GetName (), csvAnyChecker )
689+ require .NoError (t , err )
690+ }(t )
691+ // Update the catalog to include multiple updates
692+ packages := []registry.PackageManifest {
693+ {
694+ PackageName : packageName ,
695+ Channels : []registry.PackageChannel {
696+ {Name : stableChannel , CurrentCSVName : csvC .GetName ()},
697+ },
698+ DefaultChannelName : stableChannel ,
699+ },
700+ }
701+
702+ updateInternalCatalog (t , c , crc , catalogSourceName , testNamespace , []apiextensions.CustomResourceDefinition {crd }, []v1alpha1.ClusterServiceVersion {csvA , csvB , csvC }, packages )
703+
704+ // wait for checks on intermediate csvs to succeed
705+ wg .Wait ()
706+
707+ // Wait for csvC to be installed
708+ _ , err = awaitCSV (t , crc , testNamespace , csvC .GetName (), csvSucceededChecker )
709+ require .NoError (t , err )
710+
711+ // Should eventually GC the CSVs
712+ err = waitForCSVToDelete (t , crc , csvA .Name )
713+ require .NoError (t , err )
714+ err = waitForCSVToDelete (t , crc , csvB .Name )
715+ require .NoError (t , err )
716+
717+ // TODO: check installplans, subscription status, etc
718+ }
719+
720+ func updateInternalCatalog (t * testing.T , c operatorclient.ClientInterface , crc versioned.Interface , catalogSourceName , namespace string , crds []apiextensions.CustomResourceDefinition , csvs []v1alpha1.ClusterServiceVersion , packages []registry.PackageManifest ) {
721+ fetchedInitialCatalog , err := fetchCatalogSource (t , crc , catalogSourceName , namespace , catalogSourceRegistryPodSynced )
722+ require .NoError (t , err )
723+
724+ // Get initial configmap
725+ configMap , err := c .KubernetesInterface ().CoreV1 ().ConfigMaps (testNamespace ).Get (fetchedInitialCatalog .Spec .ConfigMap , metav1.GetOptions {})
726+ require .NoError (t , err )
727+
728+ // Update package to point to new csv
729+ manifestsRaw , err := yaml .Marshal (packages )
730+ require .NoError (t , err )
731+ configMap .Data [registry .ConfigMapPackageName ] = string (manifestsRaw )
732+
733+ // Update raw CRDs
734+ var crdsRaw []byte
735+ crdStrings := []string {}
736+ for _ , crd := range crds {
737+ crdStrings = append (crdStrings , serializeCRD (t , crd ))
738+ }
739+ crdsRaw , err = yaml .Marshal (crdStrings )
740+ require .NoError (t , err )
741+ configMap .Data [registry .ConfigMapCRDName ] = strings .Replace (string (crdsRaw ), "- |\n " , "- " , - 1 )
742+
743+ // Update raw CSVs
744+ csvsRaw , err := yaml .Marshal (csvs )
745+ require .NoError (t , err )
746+ configMap .Data [registry .ConfigMapCSVName ] = string (csvsRaw )
747+
748+ // Update configmap
749+ _ , err = c .KubernetesInterface ().CoreV1 ().ConfigMaps (testNamespace ).Update (configMap )
750+ require .NoError (t , err )
751+
752+ // wait for catalog to update
753+ _ , err = fetchCatalogSource (t , crc , catalogSourceName , testNamespace , func (catalog * v1alpha1.CatalogSource ) bool {
754+ if catalog .Status .LastSync != fetchedInitialCatalog .Status .LastSync && catalog .Status .ConfigMapResource .ResourceVersion != fetchedInitialCatalog .Status .ConfigMapResource .ResourceVersion {
755+ fmt .Println ("catalog updated" )
756+ return true
757+ }
758+ fmt .Println ("waiting for catalog pod to be available" )
759+ return false
760+ })
761+ require .NoError (t , err )
762+ }
0 commit comments