// Convert_build_DockerStrategyOptions_To_v1_DockerStrategyOptions is an autogenerated conversion function.
18719
func Convert_build_DockerStrategyOptions_To_v1_DockerStrategyOptions(in *build.DockerStrategyOptions, out *v1.DockerStrategyOptions, s conversion.Scope) error {
	return autoConvert_build_DockerStrategyOptions_To_v1_DockerStrategyOptions(in, out, s)
}
909144
func Convert_build_BuildSpec_To_v1_BuildSpec(in *build.BuildSpec, out *v1.BuildSpec, s conversion.Scope) error {
	return autoConvert_build_BuildSpec_To_v1_BuildSpec(in, out, s)
}
812099
func Convert_v1beta1_DaemonSetUpdateStrategy_To_apps_DaemonSetUpdateStrategy(in *v1beta1.DaemonSetUpdateStrategy, out *apps.DaemonSetUpdateStrategy, s conversion.Scope) error {
	return autoConvert_v1beta1_DaemonSetUpdateStrategy_To_apps_DaemonSetUpdateStrategy(in, out, s)
}
58665
func Convert_v1_BuildConfigList_To_build_BuildConfigList(in *v1.BuildConfigList, out *build.BuildConfigList, s conversion.Scope) error {
	return autoConvert_v1_BuildConfigList_To_build_BuildConfigList(in, out, s)
}
624486
func Convert_v1_BuildStrategy_To_build_BuildStrategy(in *v1.BuildStrategy, out *build.BuildStrategy, s conversion.Scope) error {
	return autoConvert_v1_BuildStrategy_To_build_BuildStrategy(in, out, s)
}
784878
func Convert_config_ProviderConfiguration_To_v1_ProviderConfiguration(in *config.ProviderConfiguration, out *ProviderConfiguration, s conversion.Scope) error {
	return autoConvert_config_ProviderConfiguration_To_v1_ProviderConfiguration(in, out, s)
}
1158447
func Convert_security_RunAsUserStrategyOptions_To_v1_RunAsUserStrategyOptions(in *security.RunAsUserStrategyOptions, out *v1.RunAsUserStrategyOptions, s conversion.Scope) error {
	return autoConvert_security_RunAsUserStrategyOptions_To_v1_RunAsUserStrategyOptions(in, out, s)
}
569188
func Convert_v1_BuildLogOptions_To_build_BuildLogOptions(in *v1.BuildLogOptions, out *build.BuildLogOptions, s conversion.Scope) error {
	return autoConvert_v1_BuildLogOptions_To_build_BuildLogOptions(in, out, s)
}
513137
func Convert_v1_RunAsUserStrategyOptions_To_security_RunAsUserStrategyOptions(in *v1.RunAsUserStrategyOptions, out *security.RunAsUserStrategyOptions, s conversion.Scope) error {
	return autoConvert_v1_RunAsUserStrategyOptions_To_security_RunAsUserStrategyOptions(in, out, s)
}
55243
func Convert_v1_SourceStrategyDefaultsConfig_To_config_SourceStrategyDefaultsConfig(in *v1.SourceStrategyDefaultsConfig, out *config.SourceStrategyDefaultsConfig, s conversion.Scope) error {
	return autoConvert_v1_SourceStrategyDefaultsConfig_To_config_SourceStrategyDefaultsConfig(in, out, s)
}
638920
func Convert_v1_BuildConfigStatus_To_build_BuildConfigStatus(in *v1.BuildConfigStatus, out *build.BuildConfigStatus, s conversion.Scope) error {
	return autoConvert_v1_BuildConfigStatus_To_build_BuildConfigStatus(in, out, s)
}
1337861
func Convert_apps_DeploymentStrategy_To_v1_DeploymentStrategy(in *apps.DeploymentStrategy, out *v1.DeploymentStrategy, s conversion.Scope) error {
	return autoConvert_apps_DeploymentStrategy_To_v1_DeploymentStrategy(in, out, s)
}
76904
func Convert_v1_SELinuxContextStrategyOptions_To_security_SELinuxContextStrategyOptions(in *v1.SELinuxContextStrategyOptions, out *security.SELinuxContextStrategyOptions, s conversion.Scope) error {
	return autoConvert_v1_SELinuxContextStrategyOptions_To_security_SELinuxContextStrategyOptions(in, out, s)
}
1130848
func Convert_v1_JenkinsPipelineBuildStrategy_To_build_JenkinsPipelineBuildStrategy(in *v1.JenkinsPipelineBuildStrategy, out *build.JenkinsPipelineBuildStrategy, s conversion.Scope) error {
	return autoConvert_v1_JenkinsPipelineBuildStrategy_To_build_JenkinsPipelineBuildStrategy(in, out, s)
}
1136776
func Convert_v1_ProxyConfig_To_build_ProxyConfig(in *v1.ProxyConfig, out *build.ProxyConfig, s conversion.Scope) error {
	return autoConvert_v1_ProxyConfig_To_build_ProxyConfig(in, out, s)
}
872527
func Convert_security_FSGroupStrategyOptions_To_v1_FSGroupStrategyOptions(in *security.FSGroupStrategyOptions, out *v1.FSGroupStrategyOptions, s conversion.Scope) error {
	return autoConvert_security_FSGroupStrategyOptions_To_v1_FSGroupStrategyOptions(in, out, s)
}
39664
func (b *KubeAPIServerOptionsBuilder) BuildOptions(o interface{}) error {
	clusterSpec := o.(*kops.ClusterSpec)
	if clusterSpec.KubeAPIServer == nil {
		clusterSpec.KubeAPIServer = &kops.KubeAPIServerConfig{}
	}
	c := clusterSpec.KubeAPIServer

	if c.APIServerCount == nil {
		count := b.buildAPIServerCount(clusterSpec)
		if count == 0 {
			return fmt.Errorf("no instance groups found")
		}
		c.APIServerCount = fi.Int32(int32(count))
	}

	// @question: should the question every be able to set this?
	if c.StorageBackend == nil {
		// @note: we can use the first version as we enforce both running the same versions.
		// albeit feels a little weird to do this
		sem, err := semver.Parse(strings.TrimPrefix(clusterSpec.EtcdClusters[0].Version, "v"))
		if err != nil {
			return err
		}
		c.StorageBackend = fi.String(fmt.Sprintf("etcd%d", sem.Major))
	}

	if c.KubeletPreferredAddressTypes == nil {
		if b.IsKubernetesGTE("1.5") {
			// We prioritize the internal IP above the hostname
			c.KubeletPreferredAddressTypes = []string{
				string(v1.NodeInternalIP),
				string(v1.NodeHostName),
				string(v1.NodeExternalIP),
			}

			if b.IsKubernetesLT("1.7") {
				// NodeLegacyHostIP was removed in 1.7; we add it to prior versions with lowest precedence
				c.KubeletPreferredAddressTypes = append(c.KubeletPreferredAddressTypes, "LegacyHostIP")
			}
		}
	}

	if clusterSpec.Authentication != nil {
		if clusterSpec.Authentication.Kopeio != nil {
			c.AuthenticationTokenWebhookConfigFile = fi.String("/etc/kubernetes/authn.config")
		}
	}

	if clusterSpec.Authorization == nil || clusterSpec.Authorization.IsEmpty() {
		// Do nothing - use the default as defined by the apiserver
		// (this won't happen anyway because of our default logic)
	} else if clusterSpec.Authorization.AlwaysAllow != nil {
		clusterSpec.KubeAPIServer.AuthorizationMode = fi.String("AlwaysAllow")
	} else if clusterSpec.Authorization.RBAC != nil {
		var modes []string

		if b.IsKubernetesGTE("1.10") {
			if fi.BoolValue(clusterSpec.KubeAPIServer.EnableBootstrapAuthToken) {
				// Enable the Node authorizer, used for special per-node RBAC policies
				modes = append(modes, "Node")
			}
		}
		modes = append(modes, "RBAC")

		clusterSpec.KubeAPIServer.AuthorizationMode = fi.String(strings.Join(modes, ","))
	}

	if clusterSpec.KubeAPIServer.EtcdQuorumRead == nil {
		if b.IsKubernetesGTE("1.9") {
			// 1.9 changed etcd-quorum-reads default to true
			// There's a balance between some bugs which are attributed to not having etcd-quorum-reads,
			// and the poor implementation of quorum-reads in etcd2.

			etcdHA := false
			etcdV2 := true
			for _, c := range clusterSpec.EtcdClusters {
				if len(c.Members) > 1 {
					etcdHA = true
				}
				if c.Version != "" && !strings.HasPrefix(c.Version, "2.") {
					etcdV2 = false
				}
			}

			if !etcdV2 {
				// etcd3 quorum reads are cheap.  Stick with default (which is to enable quorum reads)
				clusterSpec.KubeAPIServer.EtcdQuorumRead = nil
			} else {
				// etcd2 quorum reads go through raft => write to disk => expensive
				if !etcdHA {
					// Turn off quorum reads - they still go through raft, but don't serve any purpose in non-HA clusters.
					clusterSpec.KubeAPIServer.EtcdQuorumRead = fi.Bool(false)
				} else {
					// The problematic case.  We risk exposing more bugs, but against that we have to balance performance.
					// For now we turn off quorum reads - it's a bad enough performance regression
					// We'll likely make this default to true once we can set IOPS on the etcd volume and can easily upgrade to etcd3
					clusterSpec.KubeAPIServer.EtcdQuorumRead = fi.Bool(false)
				}
			}
		}
	}

	if err := b.configureAggregation(clusterSpec); err != nil {
		return nil
	}

	image, err := Image("kube-apiserver", clusterSpec, b.AssetBuilder)
	if err != nil {
		return err
	}
	c.Image = image

	switch kops.CloudProviderID(clusterSpec.CloudProvider) {
	case kops.CloudProviderAWS:
		c.CloudProvider = "aws"
	case kops.CloudProviderGCE:
		c.CloudProvider = "gce"
	case kops.CloudProviderDO:
		c.CloudProvider = "external"
	case kops.CloudProviderVSphere:
		c.CloudProvider = "vsphere"
	case kops.CloudProviderBareMetal:
		// for baremetal, we don't specify a cloudprovider to apiserver
	case kops.CloudProviderOpenstack:
		c.CloudProvider = "openstack"
	case kops.CloudProviderALI:
		c.CloudProvider = "alicloud"
	default:
		return fmt.Errorf("unknown cloudprovider %q", clusterSpec.CloudProvider)
	}

	if clusterSpec.ExternalCloudControllerManager != nil {
		c.CloudProvider = "external"
	}

	c.LogLevel = 2
	c.SecurePort = 443

	if b.IsKubernetesGTE("1.10") {
		c.BindAddress = "0.0.0.0"
		c.InsecureBindAddress = "127.0.0.1"
	} else {
		c.Address = "127.0.0.1"
	}

	c.AllowPrivileged = fi.Bool(true)
	c.ServiceClusterIPRange = clusterSpec.ServiceClusterIPRange
	c.EtcdServers = []string{"http://127.0.0.1:4001"}
	c.EtcdServersOverrides = []string{"/events#http://127.0.0.1:4002"}

	// TODO: We can probably rewrite these more clearly in descending order
	if b.IsKubernetesGTE("1.3") && b.IsKubernetesLT("1.4") {
		c.AdmissionControl = []string{
			"NamespaceLifecycle",
			"LimitRanger",
			"ServiceAccount",
			"PersistentVolumeLabel",
			"ResourceQuota",
		}
	}
	if b.IsKubernetesGTE("1.4") && b.IsKubernetesLT("1.5") {
		c.AdmissionControl = []string{
			"NamespaceLifecycle",
			"LimitRanger",
			"ServiceAccount",
			"PersistentVolumeLabel",
			"DefaultStorageClass",
			"ResourceQuota",
		}
	}
	if b.IsKubernetesGTE("1.5") && b.IsKubernetesLT("1.6") {
		c.AdmissionControl = []string{
			"NamespaceLifecycle",
			"LimitRanger",
			"ServiceAccount",
			"PersistentVolumeLabel",
			"DefaultStorageClass",
			"ResourceQuota",
		}
	}
	if b.IsKubernetesGTE("1.6") && b.IsKubernetesLT("1.7") {
		c.AdmissionControl = []string{
			"NamespaceLifecycle",
			"LimitRanger",
			"ServiceAccount",
			"PersistentVolumeLabel",
			"DefaultStorageClass",
			"DefaultTolerationSeconds",
			"ResourceQuota",
		}
	}
	if b.IsKubernetesGTE("1.7") && b.IsKubernetesLT("1.9") {
		c.AdmissionControl = []string{
			"Initializers",
			"NamespaceLifecycle",
			"LimitRanger",
			"ServiceAccount",
			"PersistentVolumeLabel",
			"DefaultStorageClass",
			"DefaultTolerationSeconds",
			"NodeRestriction",
			"ResourceQuota",
		}
	}
	if b.IsKubernetesGTE("1.9") && b.IsKubernetesLT("1.10") {
		c.AdmissionControl = []string{
			"Initializers",
			"NamespaceLifecycle",
			"LimitRanger",
			"ServiceAccount",
			"PersistentVolumeLabel",
			"DefaultStorageClass",
			"DefaultTolerationSeconds",
			"MutatingAdmissionWebhook",
			"ValidatingAdmissionWebhook",
			"NodeRestriction",
			"ResourceQuota",
		}
	}
	// Based on recommendations from:
	// https://kubernetes.io/docs/admin/admission-controllers/#is-there-a-recommended-set-of-admission-controllers-to-use
	if b.IsKubernetesGTE("1.10") && b.IsKubernetesLT("1.12") {
		c.EnableAdmissionPlugins = []string{
			"Initializers",
			"NamespaceLifecycle",
			"LimitRanger",
			"ServiceAccount",
			"PersistentVolumeLabel",
			"DefaultStorageClass",
			"DefaultTolerationSeconds",
			"MutatingAdmissionWebhook",
			"ValidatingAdmissionWebhook",
			"NodeRestriction",
			"ResourceQuota",
		}
	}
	// Based on recommendations from:
	// https://kubernetes.io/docs/admin/admission-controllers/#is-there-a-recommended-set-of-admission-controllers-to-use
	if b.IsKubernetesGTE("1.12") {
		c.EnableAdmissionPlugins = []string{
			"NamespaceLifecycle",
			"LimitRanger",
			"ServiceAccount",
			"PersistentVolumeLabel",
			"DefaultStorageClass",
			"DefaultTolerationSeconds",
			"MutatingAdmissionWebhook",
			"ValidatingAdmissionWebhook",
			"NodeRestriction",
			"ResourceQuota",
		}
	}

	// We make sure to disable AnonymousAuth from when it was introduced
	if b.IsKubernetesGTE("1.5") {
		c.AnonymousAuth = fi.Bool(false)
	}

	// FIXME : Disable the insecure port when kubernetes issue #43784 is fixed
	c.InsecurePort = 8080

	return nil
}