github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/verify-install/validators/mysql_podspec_validator_test.go (about)

     1  // Copyright (c) 2022, 2023, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  package validators
     4  
     5  import (
     6  	. "github.com/onsi/gomega"
     7  	"github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1alpha1"
     8  	"github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1beta1"
     9  	"github.com/verrazzano/verrazzano/tests/e2e/pkg/update"
    10  	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    11  	"k8s.io/client-go/rest"
    12  	"sigs.k8s.io/controller-runtime/pkg/client"
    13  )
    14  
    15  const (
    16  	// Used by this test to make an illegal edit, to ensure that the apply is rejected but still generate the
    17  	// warnings we're looking for
    18  	illegalEnvironmentName = "asfsdafsdafadsfdsafdsafdsafadsfadsfadsfadsfdsafadsfsdafdsafasdfasdfsadfasdfasdfdasfasdfasdfasadsfasdfdasfasdfdsafdsafasd"
    19  
    20  	podSpecJSON = `
    21  {
    22    "podSpec": {
    23      "affinity": {
    24        "podAffinity": {
    25          "preferredDuringSchedulingIgnoredDuringExecution": [
    26            {
    27              "weight": 200,
    28              "podAffinityTerm": {
    29                "labelSelector": {
    30                  "matchLabels": {
    31                    "app.kubernetes.io/instance": "mysql-innodbcluster-mysql-mysql-server",
    32                    "app.kubernetes.io/name": "mysql-innodbcluster-mysql-server"
    33                  }
    34                },
    35                "topologyKey": "kubernetes.io/hostname"
    36              }
    37            }
    38          ]
    39        }
    40      }
    41    }
    42  }`
    43  
    44  	warningSubstring = "Modifications to MySQL server pod specs do not trigger an automatic restart of the stateful set"
    45  )
    46  
    47  type warningInfo struct {
    48  	code  int
    49  	agent string
    50  	text  string
    51  }
    52  
    53  type mysqlPodSpecUpdater struct {
    54  	warnings []warningInfo
    55  }
    56  
    57  func (j *mysqlPodSpecUpdater) ModifyCRV1beta1(cr *v1beta1.Verrazzano) {
    58  	// Attempt to make an illegal edit to the Jaeger configuration to ensure its component validation is working properly
    59  	trueValue := true
    60  	if cr.Spec.Components.JaegerOperator == nil {
    61  		cr.Spec.Components.JaegerOperator = &v1beta1.JaegerOperatorComponent{}
    62  	}
    63  	// Include an illegal edit to prevent the edit from succeeding
    64  	cr.Spec.EnvironmentName = illegalEnvironmentName
    65  	if cr.Spec.Components.Keycloak == nil {
    66  		cr.Spec.Components.Keycloak = &v1beta1.KeycloakComponent{}
    67  	}
    68  	cr.Spec.Components.Keycloak.Enabled = &trueValue
    69  	illegalValuesObj := generateJSONValuesObj()
    70  	cr.Spec.Components.Keycloak.MySQL.InstallOverrides.ValueOverrides = append(
    71  		cr.Spec.Components.Keycloak.MySQL.InstallOverrides.ValueOverrides,
    72  		v1beta1.Overrides{Values: illegalValuesObj})
    73  }
    74  
    75  func (j *mysqlPodSpecUpdater) ModifyCR(cr *v1alpha1.Verrazzano) {
    76  	// Attempt to make an illegal edit to the Jaeger configuration to ensure its component validation is working properly
    77  	trueValue := true
    78  	if cr.Spec.Components.JaegerOperator == nil {
    79  		cr.Spec.Components.JaegerOperator = &v1alpha1.JaegerOperatorComponent{}
    80  	}
    81  	// Include an illegal edit to prevent the edit from succeeding
    82  	cr.Spec.EnvironmentName = illegalEnvironmentName
    83  	if cr.Spec.Components.Keycloak == nil {
    84  		cr.Spec.Components.Keycloak = &v1alpha1.KeycloakComponent{}
    85  	}
    86  	cr.Spec.Components.Keycloak.Enabled = &trueValue
    87  	illegalValuesObj := generateJSONValuesObj()
    88  	cr.Spec.Components.Keycloak.MySQL.InstallOverrides.ValueOverrides = append(
    89  		cr.Spec.Components.Keycloak.MySQL.InstallOverrides.ValueOverrides,
    90  		v1alpha1.Overrides{Values: illegalValuesObj})
    91  }
    92  
    93  func (j *mysqlPodSpecUpdater) HandleWarningHeader(code int, agent string, text string) {
    94  	j.warnings = append(j.warnings, warningInfo{code: code, agent: agent, text: text})
    95  }
    96  
    97  var _ update.CRModifier = &mysqlPodSpecUpdater{}
    98  var _ update.CRModifierV1beta1 = &mysqlPodSpecUpdater{}
    99  var _ rest.WarningHandler = &mysqlPodSpecUpdater{}
   100  
   101  func generateJSONValuesObj() *apiextensionsv1.JSON {
   102  	illegalOverride := podSpecJSON
   103  	illegalValuesObj := &apiextensionsv1.JSON{
   104  		Raw: []byte(illegalOverride),
   105  	}
   106  	return illegalValuesObj
   107  }
   108  
   109  // runValidatorTestV1Beta1 Attempt to generate the MySQL values webhook warning, with an illegal edit so the overall edit is rejected
   110  func runMySQLPodspecEditWarningTestV1Beta1() {
   111  	updater := &mysqlPodSpecUpdater{}
   112  	checkExpectations(update.UpdateCRV1beta1(updater, client.DryRunAll), updater)
   113  }
   114  
   115  // runValidatorTestV1Alpha1 Attempt to use an illegal overrides value on the Jaeger operator configuration using the v1alpha1 API
   116  func runMySQLPodspecEditWarningTestV1Alpha1() {
   117  	updater := &mysqlPodSpecUpdater{}
   118  	checkExpectations(update.UpdateCR(updater, client.DryRunAll), updater)
   119  }
   120  
   121  func checkExpectations(err error, updater *mysqlPodSpecUpdater) {
   122  	Eventually(func() []string {
   123  		t.Logs.Infof("Verifies that an update to the MySQL overrides containing a podSpec value issues a warning to " +
   124  			"the user; also makes an illegal edit to avoid mutating the system but also generate the warning")
   125  		if err == nil {
   126  			t.Logs.Info("Did not get an error on illegal update")
   127  			return []string{}
   128  		}
   129  		if err != nil {
   130  			t.Logs.Infof("Update error: %s", err.Error())
   131  		}
   132  		var warningText []string
   133  		for _, warning := range updater.warnings {
   134  			warningText = append(warningText, warning.text)
   135  			t.Logs.Infof("Warning: %v", warning)
   136  		}
   137  		return warningText
   138  	}, waitTimeout, pollingInterval).Should(ContainElements(ContainSubstring(warningSubstring)))
   139  }