func()

in pkg/apis/ndbcontroller/v1/validation.go [56:146]


func (nc *NdbCluster) HasValidSpec() (bool, field.ErrorList) {
	spec := nc.Spec

	var errList field.ErrorList
	specPath := field.NewPath("spec")
	mysqldPath := specPath.Child("mysqlNode")
	dataNodePath := specPath.Child("dataNode")
	managementNodePath := specPath.Child("managementNode")

	dataNodeCount := spec.DataNode.NodeCount
	mysqlServerCount := nc.GetMySQLServerMaxNodeCount()
	managementNodeCount := nc.GetManagementNodeCount()
	numOfFreeApiSlots := spec.FreeAPISlots + 1

	// check if number of data nodes is a multiple of redundancy
	if math.Mod(float64(dataNodeCount), float64(spec.RedundancyLevel)) != 0 {
		msg := fmt.Sprintf(
			"spec.dataNode.nodeCount should be a multiple of the spec.redundancyLevel(=%d)", spec.RedundancyLevel)
		errList = append(errList, field.Invalid(dataNodePath.Child("nodeCount"), dataNodeCount, msg))
	}

	// check if total number of nodes are not more than the allowed maximum
	total := managementNodeCount + dataNodeCount + mysqlServerCount + numOfFreeApiSlots
	if total > constants.MaxNumberOfNodes {
		invalidValue := fmt.Sprintf(
			"%d (= %d management, %d data, %d mysql nodes and %d free API nodes)",
			total, managementNodeCount, dataNodeCount, mysqlServerCount, numOfFreeApiSlots)
		msg := fmt.Sprintf(
			"Total number of MySQL Cluster nodes should not exceed the allowed maximum of %d", constants.MaxNumberOfNodes)
		errList = append(errList, field.Invalid(field.NewPath("Total Nodes"), invalidValue, msg))
	}

	// check if there are any disallowed config params in dataNode's Configuration.
	if err := validateConfigParams(nc.Spec.DataNode.Config, dataNodePath.Child("config")); err != nil {
		errList = append(errList, err...)
	}

	// check if there are any disallowed config params in managementNode Config.
	if nc.Spec.ManagementNode != nil {
		if err := validateConfigParams(nc.Spec.ManagementNode.Config, managementNodePath.Child("config")); err != nil {
			errList = append(errList, err...)
		}
	}

	// check if the MySQL root password secret name has the expected format
	var rootPasswordSecret string
	if spec.MysqlNode != nil {
		mysqldSpec := spec.MysqlNode

		// check if the MySQL root password secret name has the expected format
		rootPasswordSecret = mysqldSpec.RootPasswordSecretName
		if rootPasswordSecret != "" {
			errs := validation.IsDNS1123Subdomain(rootPasswordSecret)
			// append errors, if any, to errList
			for _, err := range errs {
				errList = append(errList,
					field.Invalid(mysqldPath.Child("rootPasswordSecretName"), rootPasswordSecret, err))
			}
		}

		// check if maxNodeCount is less than nodeCount
		if mysqldSpec.MaxNodeCount != 0 &&
			mysqldSpec.MaxNodeCount < mysqldSpec.NodeCount {
			msg := fmt.Sprintf(
				"spec.mysqlNode.maxNodeCount cannot be less than spec.mysqlNode.nodeCount(=%d)", mysqldSpec.NodeCount)
			errList = append(errList,
				field.Invalid(mysqldPath.Child("maxNodeCount"), mysqldSpec.MaxNodeCount, msg))
		}
	}

	// check if any passed my.cnf has proper format
	myCnfString := nc.GetMySQLCnf()
	if len(myCnfString) > 0 {
		myCnf, err := configparser.ParseString(myCnfString)
		if err != nil {
			// error parsing the cnf
			errList = append(errList,
				field.Invalid(mysqldPath.Child("myCnf"), myCnfString, err.Error()))
		} else {
			// accept only one mysqld section in the cnf
			if len(myCnf) != 1 ||
				myCnf.GetNumberOfSections("mysqld") != 1 {
				errList = append(errList,
					field.Invalid(mysqldPath.Child("myCnf"),
						myCnfString, "spec.mysqlNode.myCnf can have only one mysqld section"))
			}
		}
	}

	return errList == nil, errList
}