istio.io/istio@v0.0.0-20240520182934-d79c90f27776/operator/pkg/controlplane/control_plane_test.go (about)

     1  // Copyright Istio 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 controlplane
    16  
    17  import (
    18  	"fmt"
    19  	"reflect"
    20  	"testing"
    21  
    22  	"istio.io/api/operator/v1alpha1"
    23  	"istio.io/istio/operator/pkg/component"
    24  	"istio.io/istio/operator/pkg/name"
    25  	"istio.io/istio/operator/pkg/translate"
    26  	"istio.io/istio/operator/pkg/util"
    27  )
    28  
    29  func TestOrderedKeys(t *testing.T) {
    30  	tests := []struct {
    31  		desc string
    32  		in   map[string]*v1alpha1.ExternalComponentSpec
    33  		want []string
    34  	}{
    35  		{
    36  			desc: "not-ordered",
    37  			in: map[string]*v1alpha1.ExternalComponentSpec{
    38  				"graphql":   nil,
    39  				"Abacus":    nil,
    40  				"Astrology": nil,
    41  				"gRPC":      nil,
    42  				"blackjack": nil,
    43  			},
    44  			want: []string{
    45  				"Abacus",
    46  				"Astrology",
    47  				"blackjack",
    48  				"gRPC",
    49  				"graphql",
    50  			},
    51  		},
    52  	}
    53  	for _, tt := range tests {
    54  		t.Run(tt.desc, func(t *testing.T) {
    55  			if got := orderedKeys(tt.in); !(reflect.DeepEqual(got, tt.want)) {
    56  				t.Errorf("%s: got %+v want %+v", tt.desc, got, tt.want)
    57  			}
    58  		})
    59  	}
    60  }
    61  
    62  func TestNewIstioOperator(t *testing.T) {
    63  	coreComponentOptions := &component.Options{
    64  		InstallSpec: &v1alpha1.IstioOperatorSpec{},
    65  		Translator:  &translate.Translator{},
    66  	}
    67  	tests := []struct {
    68  		desc              string
    69  		inInstallSpec     *v1alpha1.IstioOperatorSpec
    70  		inTranslator      *translate.Translator
    71  		wantIstioOperator *IstioControlPlane
    72  		wantErr           error
    73  	}{
    74  		{
    75  			desc:          "core-components",
    76  			inInstallSpec: &v1alpha1.IstioOperatorSpec{},
    77  			inTranslator: &translate.Translator{
    78  				ComponentMaps: map[name.ComponentName]*translate.ComponentMaps{
    79  					"Pilot": {
    80  						ResourceName: "test-resource",
    81  					},
    82  				},
    83  			},
    84  			wantErr: nil,
    85  			wantIstioOperator: &IstioControlPlane{
    86  				components: []component.IstioComponent{
    87  					&component.BaseComponent{
    88  						IstioComponentBase: &component.IstioComponentBase{
    89  							CommonComponentFields: &component.CommonComponentFields{
    90  								Options:       coreComponentOptions,
    91  								ComponentName: name.IstioBaseComponentName,
    92  							},
    93  						},
    94  					},
    95  					&component.PilotComponent{
    96  						IstioComponentBase: &component.IstioComponentBase{
    97  							CommonComponentFields: &component.CommonComponentFields{
    98  								Options:       coreComponentOptions,
    99  								ResourceName:  "test-resource",
   100  								ComponentName: name.PilotComponentName,
   101  							},
   102  						},
   103  					},
   104  					&component.CNIComponent{
   105  						IstioComponentBase: &component.IstioComponentBase{
   106  							CommonComponentFields: &component.CommonComponentFields{
   107  								ComponentName: name.CNIComponentName,
   108  								Options:       coreComponentOptions,
   109  							},
   110  						},
   111  					},
   112  					&component.IstiodRemoteComponent{
   113  						IstioComponentBase: &component.IstioComponentBase{
   114  							CommonComponentFields: &component.CommonComponentFields{
   115  								ComponentName: name.IstiodRemoteComponentName,
   116  								Options:       coreComponentOptions,
   117  							},
   118  						},
   119  					},
   120  					&component.ZtunnelComponent{
   121  						IstioComponentBase: &component.IstioComponentBase{
   122  							CommonComponentFields: &component.CommonComponentFields{
   123  								ComponentName: name.ZtunnelComponentName,
   124  								Options:       coreComponentOptions,
   125  							},
   126  						},
   127  					},
   128  				},
   129  			},
   130  		},
   131  	}
   132  	for _, tt := range tests {
   133  		t.Run(tt.desc, func(t *testing.T) {
   134  			gotOperator, err := NewIstioControlPlane(tt.inInstallSpec, tt.inTranslator, nil, nil)
   135  			if ((err != nil && tt.wantErr == nil) || (err == nil && tt.wantErr != nil)) || !gotOperator.componentsEqual(tt.wantIstioOperator.components) {
   136  				t.Errorf("%s: wanted components & err %+v %v, got components & err %+v %v",
   137  					tt.desc, tt.wantIstioOperator.components, tt.wantErr, gotOperator.components, err)
   138  			}
   139  		})
   140  	}
   141  }
   142  
   143  func TestIstioOperator_RenderManifest(t *testing.T) {
   144  	coreComponentOptions := &component.Options{
   145  		InstallSpec: &v1alpha1.IstioOperatorSpec{},
   146  		Translator:  &translate.Translator{},
   147  	}
   148  	tests := []struct {
   149  		desc          string
   150  		testOperator  *IstioControlPlane
   151  		wantManifests name.ManifestMap
   152  		wantErrs      util.Errors
   153  	}{
   154  		{
   155  			desc: "components-not-started-operator-started",
   156  			testOperator: &IstioControlPlane{
   157  				components: []component.IstioComponent{
   158  					&component.BaseComponent{
   159  						IstioComponentBase: &component.IstioComponentBase{
   160  							CommonComponentFields: &component.CommonComponentFields{
   161  								Options:       coreComponentOptions,
   162  								ComponentName: name.IstioBaseComponentName,
   163  							},
   164  						},
   165  					},
   166  					&component.PilotComponent{
   167  						IstioComponentBase: &component.IstioComponentBase{
   168  							CommonComponentFields: &component.CommonComponentFields{
   169  								Options: &component.Options{
   170  									InstallSpec: &v1alpha1.IstioOperatorSpec{},
   171  									Translator:  &translate.Translator{},
   172  								},
   173  								ResourceName:  "test-resource",
   174  								ComponentName: name.PilotComponentName,
   175  							},
   176  						},
   177  					},
   178  					&component.CNIComponent{
   179  						IstioComponentBase: &component.IstioComponentBase{
   180  							CommonComponentFields: &component.CommonComponentFields{
   181  								ComponentName: name.CNIComponentName,
   182  								Options:       coreComponentOptions,
   183  							},
   184  						},
   185  					},
   186  				},
   187  				started: true,
   188  			},
   189  			wantManifests: map[name.ComponentName][]string{},
   190  			wantErrs: util.Errors{
   191  				fmt.Errorf("component Base not started in RenderManifest"),
   192  				fmt.Errorf("component Pilot not started in RenderManifest"),
   193  				fmt.Errorf("component Cni not started in RenderManifest"),
   194  			},
   195  		},
   196  		{
   197  			desc: "operator-not-started",
   198  			testOperator: &IstioControlPlane{
   199  				components: []component.IstioComponent{
   200  					&component.BaseComponent{
   201  						IstioComponentBase: &component.IstioComponentBase{
   202  							CommonComponentFields: &component.CommonComponentFields{
   203  								Options:       coreComponentOptions,
   204  								ComponentName: name.IstioBaseComponentName,
   205  							},
   206  						},
   207  					},
   208  					&component.PilotComponent{
   209  						IstioComponentBase: &component.IstioComponentBase{
   210  							CommonComponentFields: &component.CommonComponentFields{
   211  								Options: &component.Options{
   212  									InstallSpec: &v1alpha1.IstioOperatorSpec{},
   213  									Translator:  &translate.Translator{},
   214  								},
   215  								ResourceName:  "test-resource",
   216  								ComponentName: name.PilotComponentName,
   217  							},
   218  						},
   219  					},
   220  					&component.CNIComponent{
   221  						IstioComponentBase: &component.IstioComponentBase{
   222  							CommonComponentFields: &component.CommonComponentFields{
   223  								ComponentName: name.CNIComponentName,
   224  								Options:       coreComponentOptions,
   225  							},
   226  						},
   227  					},
   228  				},
   229  				started: false,
   230  			},
   231  			wantManifests: map[name.ComponentName][]string{},
   232  			wantErrs: util.Errors{
   233  				fmt.Errorf("istioControlPlane must be Run before calling RenderManifest"),
   234  			},
   235  		},
   236  	}
   237  	for _, tt := range tests {
   238  		t.Run(tt.desc, func(t *testing.T) {
   239  			gotManifests, gotErrs := tt.testOperator.RenderManifest()
   240  			if !reflect.DeepEqual(gotManifests, tt.wantManifests) || !util.EqualErrors(gotErrs, tt.wantErrs) {
   241  				// reflect.DeepEqual returns false on size 0 maps
   242  				if !(len(gotManifests) == 0) && (len(tt.wantManifests) == 0) {
   243  					t.Errorf("%s: expected manifest map %+v errs %+v, got manifest map %+v errs %+v",
   244  						tt.desc, tt.wantManifests, tt.wantErrs, gotManifests, gotErrs)
   245  				}
   246  			}
   247  		})
   248  	}
   249  }