// BuildUnstructured validates for Kubernetes objects and returns unstructured infos.
423106
func (c *Client) BuildUnstructured(namespace string, reader io.Reader) (Result, error) {
	var result Result

	result, err := c.NewBuilder().
		Unstructured().
		ContinueOnError().
		NamespaceParam(namespace).
		DefaultNamespace().
		Schema(c.validator()).
		Stream(reader, "").
		Flatten().
		Do().Infos()
	return result, scrubValidationError(err)
}
605294
func (g *Generator) buildNestedDescriptors(descs []*Descriptor) {
	for _, desc := range descs {
		if len(desc.NestedType) != 0 {
			for _, nest := range descs {
				if nest.parent == desc {
					desc.nested = append(desc.nested, nest)
				}
			}
			if len(desc.nested) != len(desc.NestedType) {
				g.Fail("internal error: nesting failure for", desc.GetName())
			}
		}
	}
}
1283889
func (p *PrintingKubeClient) Build(ns string, reader io.Reader) (kube.Result, error) {
	return []*resource.Info{}, nil
}
1191830
func (x *DocumentManifest) UnmarshalJSON(data []byte) (err error) {
	x2 := documentManifest{}
	if err = json.Unmarshal(data, &x2); err == nil {
		if x2.Contained != nil {
			for i := range x2.Contained {
				x2.Contained[i] = MapToResource(x2.Contained[i], true)
			}
		}
		*x = DocumentManifest(x2)
		return x.checkResourceType()
	}
	return
}
625666
func (b *SysctlBuilder) Build(c *fi.ModelBuilderContext) error {
	var sysctls []string

	// Common settings
	{
		sysctls = append(sysctls,
			"# Kubernetes Settings",
			"")

		// A higher vm.max_map_count is great for elasticsearch, mongo, or other mmap users
		// See https://github.com/kubernetes/kops/issues/1340
		sysctls = append(sysctls, "vm.max_map_count = 262144",
			"")

		// See https://github.com/kubernetes/kubernetes/pull/38001
		sysctls = append(sysctls,
			"kernel.softlockup_panic = 1",
			"kernel.softlockup_all_cpu_backtrace = 1",
			"")

		// See https://github.com/kubernetes/kops/issues/6342
		portRange := b.Cluster.Spec.KubeAPIServer.ServiceNodePortRange
		if portRange == "" {
			portRange = "30000-32767" // Default kube-apiserver ServiceNodePortRange
		}
		sysctls = append(sysctls, "net.ipv4.ip_local_reserved_ports = "+portRange,
			"")

		// See https://github.com/kubernetes/kube-deploy/issues/261
		sysctls = append(sysctls,
			"# Increase the number of connections",
			"net.core.somaxconn = 32768",
			"",

			"# Maximum Socket Receive Buffer",
			"net.core.rmem_max = 16777216",
			"",

			"# Default Socket Send Buffer",
			"net.core.wmem_max = 16777216",
			"",

			"# Increase the maximum total buffer-space allocatable",
			"net.ipv4.tcp_wmem = 4096 12582912 16777216",
			"net.ipv4.tcp_rmem = 4096 12582912 16777216",
			"",

			"# Increase the number of outstanding syn requests allowed",
			"net.ipv4.tcp_max_syn_backlog = 8096",
			"",

			"# For persistent HTTP connections",
			"net.ipv4.tcp_slow_start_after_idle = 0",
			"",

			"# Increase the tcp-time-wait buckets pool size to prevent simple DOS attacks",
			"net.ipv4.tcp_tw_reuse = 1",
			"",

			// We can't change the local_port_range without changing the NodePort range
			//"# Allowed local port range",
			//"net.ipv4.ip_local_port_range = 10240 65535",
			//"",

			"# Max number of packets that can be queued on interface input",
			"# If kernel is receiving packets faster than can be processed",
			"# this queue increases",
			"net.core.netdev_max_backlog = 16384",
			"",

			"# Increase size of file handles and inode cache",
			"fs.file-max = 2097152",
			"",

			"# Max number of inotify instances and watches for a user",
			"# Since dockerd runs as a single user, the default instances value of 128 per user is too low",
			"# e.g. uses of inotify: nginx ingress controller, kubectl logs -f",
			"fs.inotify.max_user_instances = 8192",
			"fs.inotify.max_user_watches = 524288",
			"",
		)
	}

	if b.Cluster.Spec.CloudProvider == string(kops.CloudProviderAWS) {
		sysctls = append(sysctls,
			"# AWS settings",
			"",
			"# Issue #23395",
			"net.ipv4.neigh.default.gc_thresh1=0",
			"")
	}

	sysctls = append(sysctls,
		"# Prevent docker from changing iptables: https://github.com/kubernetes/kubernetes/issues/40182",
		"net.ipv4.ip_forward=1",
		"")

	c.AddTask(&nodetasks.File{
		Path:            "/etc/sysctl.d/99-k8s-general.conf",
		Contents:        fi.NewStringResource(strings.Join(sysctls, "\n")),
		Type:            nodetasks.FileType_File,
		OnChangeExecute: [][]string{{"sysctl", "--system"}},
	})

	return nil
}
360098
func UnmarshalBuilder(b io.Reader) (*Builder, error) {
	var nodeType lowring.Node
	j := &builderJSON{}
	jsonDecoder := json.NewDecoder(b)
	if err := jsonDecoder.Decode(j); err != nil {
		return nil, err
	}
	b = io.MultiReader(jsonDecoder.Buffered(), b)
	// These byte reads are to get past any trailing whitespace, newlines, etc.
	// the JSON encoder may or may not have written. When marshalling we
	// preface the raw ring data with a 0 byte.
	b0 := []byte{0}
	for {
		if n, err := b.Read(b0); err != nil {
			return nil, err
		} else if n == 0 {
			b0[0] = 1
		}
		if b0[0] == 0 {
			break
		}
	}
	if j.MarshalVersion != 0 {
		return nil, fmt.Errorf("unable to interpret data with MarshalVersion %d", j.MarshalVersion)
	}
	if j.NodeType != int(unsafe.Sizeof(nodeType))*8 {
		return nil, fmt.Errorf("builder data does not match compiled builder format. NodeType is %d bits in the data and %d bits compiled.", j.NodeType, int(unsafe.Sizeof(nodeType))*8)
	}
	rv := &Builder{
		ring:     &lowring.Ring{},
		nodes:    make([]*BuilderNode, len(j.Nodes)),
		groups:   make([]*BuilderGroup, len(j.Groups)),
		randIntn: rand.New(rand.NewSource(0)).Intn,
	}
	rv.ring.NodeToCapacity = make([]int, len(j.Nodes))
	rv.ring.NodeToGroup = make([]int, len(j.Nodes))
	rv.ring.GroupToGroup = make([]int, len(j.Groups))
	rv.ring.MaxPartitionCount = j.MaxPartitionCount
	rv.ring.Rebalanced = time.Unix(0, j.Rebalanced)
	rv.ring.ReassignmentWait = uint16(j.ReassignmentWait)
	rv.ring.MaxReplicaReassignableCount = int8(j.MaxReplicaReassignableCount)
	for i, jn := range j.Nodes {
		rv.nodes[i] = &BuilderNode{builder: rv, index: i, info: jn.Info}
		rv.ring.NodeToCapacity[i] = jn.Capacity
		rv.ring.NodeToGroup[i] = jn.Group
	}
	for i, jg := range j.Groups {
		rv.groups[i] = &BuilderGroup{builder: rv, index: i, info: jg.Info}
		rv.ring.GroupToGroup[i] = jg.Parent
	}
	rv.ring.ReplicaToPartitionToNode = make([][]lowring.Node, j.ReplicaCount)
	for replica := 0; replica < j.ReplicaCount; replica++ {
		rv.ring.ReplicaToPartitionToNode[replica] = make([]lowring.Node, j.PartitionCount)
		if err := binary.Read(b, binary.LittleEndian, rv.ring.ReplicaToPartitionToNode[replica]); err != nil {
			return nil, err
		}
	}
	rv.ring.ReplicaToPartitionToWait = make([][]uint16, j.ReplicaCount)
	for replica := 0; replica < j.ReplicaCount; replica++ {
		rv.ring.ReplicaToPartitionToWait[replica] = make([]uint16, j.PartitionCount)
		if err := binary.Read(b, binary.LittleEndian, rv.ring.ReplicaToPartitionToWait[replica]); err != nil {
			return nil, err
		}
	}
	return rv, nil
}
322446
func (b *Builder) Build() (abbrev, aranges, frame, info, line, pubnames, ranges, str, loc []byte, err error) {
	b.TagClose()

	if len(b.tagStack) > 0 {
		err = fmt.Errorf("unbalanced TagOpen/TagClose %d", len(b.tagStack))
		return
	}

	abbrev = b.makeAbbrevTable()
	info = b.info.Bytes()
	binary.LittleEndian.PutUint32(info, uint32(len(info)-4))
	loc = b.loc.Bytes()

	return
}
1190722
func (ub *urlBuilder) Build() string {

	if strings.Count(ub.MetricDefinition, "/") > 1 {
		rn := strings.Split(ub.ResourceName, "/")
		lastIndex := strings.LastIndex(ub.MetricDefinition, "/")
		service := ub.MetricDefinition[lastIndex+1:]
		md := ub.MetricDefinition[0:lastIndex]
		return fmt.Sprintf("resourceGroups/%s/providers/%s/%s/%s/%s/providers/microsoft.insights/metrics", ub.ResourceGroup, md, rn[0], service, rn[1])
	}

	return fmt.Sprintf("resourceGroups/%s/providers/%s/%s/providers/microsoft.insights/metrics", ub.ResourceGroup, ub.MetricDefinition, ub.ResourceName)
}
829068
func (b *PackagesBuilder) Build(c *fi.ModelBuilderContext) error {
	// kubelet needs:
	//   conntrack  - kops #5671
	//   ebtables - kops #1711
	//   ethtool - kops #1830
	if b.Distribution.IsDebianFamily() {
		c.AddTask(&nodetasks.Package{Name: "conntrack"})
		c.AddTask(&nodetasks.Package{Name: "ebtables"})
		c.AddTask(&nodetasks.Package{Name: "ethtool"})
	} else if b.Distribution.IsRHELFamily() {
		c.AddTask(&nodetasks.Package{Name: "conntrack-tools"})
		c.AddTask(&nodetasks.Package{Name: "ebtables"})
		c.AddTask(&nodetasks.Package{Name: "ethtool"})
		c.AddTask(&nodetasks.Package{Name: "socat"})
	} else {
		// Hopefully it's already installed
		glog.Infof("ebtables package not known for distro %q", b.Distribution)
	}

	return nil
}
1077414
func BuildSelfhostedComponentLabels(component string) map[string]string {
	return map[string]string{
		"k8s-app": kubeadmconstants.AddSelfHostedPrefix(component),
	}
}
1051512
func NewAssetBuilder(cluster *kops.Cluster, phase string) *AssetBuilder {
	a := &AssetBuilder{
		AssetsLocation: cluster.Spec.Assets,
		Phase:          phase,
	}

	version, err := util.ParseKubernetesVersion(cluster.Spec.KubernetesVersion)
	if err != nil {
		// This should have already been validated
		glog.Fatalf("unexpected error from ParseKubernetesVersion %s: %v", cluster.Spec.KubernetesVersion, err)
	}
	a.KubernetesVersion = *version

	return a
}
771454
func (f *FileAssetsBuilder) Build(c *fi.ModelBuilderContext) error {
	// used to keep track of previous file, so a instanceGroup can override a cluster wide one
	tracker := make(map[string]bool, 0)

	// ensure the default path exists
	c.EnsureTask(&nodetasks.File{
		Path: f.FileAssetsDefaultPath(),
		Type: nodetasks.FileType_Directory,
		Mode: s("0755"),
	})

	// do we have any instanceGroup file assets
	if f.InstanceGroup.Spec.FileAssets != nil {
		if err := f.buildFileAssets(c, f.InstanceGroup.Spec.FileAssets, tracker); err != nil {
			return err
		}
	}
	if f.Cluster.Spec.FileAssets != nil {
		if err := f.buildFileAssets(c, f.Cluster.Spec.FileAssets, tracker); err != nil {
			return err
		}
	}

	return nil
}
1280158
func (b *NetworkBuilder) Build(c *fi.ModelBuilderContext) error {
	var assetNames []string

	// @TODO need to clean up this code, it isn't the easiest to read
	networking := b.Cluster.Spec.Networking
	if networking == nil || networking.Classic != nil {
	} else if networking.Kubenet != nil {
		assetNames = append(assetNames, "bridge", "host-local", "loopback")
	} else if networking.External != nil {
		// external is based on kubenet
		assetNames = append(assetNames, "bridge", "host-local", "loopback")

	} else if networking.CNI != nil || networking.Weave != nil || networking.Flannel != nil || networking.Calico != nil || networking.Canal != nil || networking.Kuberouter != nil || networking.Romana != nil || networking.AmazonVPC != nil || networking.Cilium != nil {
		assetNames = append(assetNames, "bridge", "host-local", "loopback", "ptp")
		// Do we need tuning?

		if b.IsKubernetesGTE("1.9") {
			assetNames = append(assetNames, "portmap")
		}

		// TODO: Only when using flannel ?
		assetNames = append(assetNames, "flannel")
	} else if networking.Kopeio != nil {
		// TODO combine with External
		// Kopeio is based on kubenet / external
		assetNames = append(assetNames, "bridge", "host-local", "loopback")
	} else if networking.LyftVPC != nil {
		assetNames = append(assetNames, "cni-ipvlan-vpc-k8s-ipam", "cni-ipvlan-vpc-k8s-ipvlan", "cni-ipvlan-vpc-k8s-tool", "cni-ipvlan-vpc-k8s-unnumbered-ptp", "loopback")
	} else {
		return fmt.Errorf("no networking mode set")
	}

	for _, assetName := range assetNames {
		if err := b.addCNIBinAsset(c, assetName); err != nil {
			return err
		}
	}

	return nil
}
300948
func (b *KubeRouterBuilder) Build(c *fi.ModelBuilderContext) error {
	{
		kubeconfig, err := b.BuildPKIKubeconfig("kube-router")
		if err != nil {
			return err
		}

		c.AddTask(&nodetasks.File{
			Path:     "/var/lib/kube-router/kubeconfig",
			Contents: fi.NewStringResource(kubeconfig),
			Type:     nodetasks.FileType_File,
			Mode:     s("0400"),
		})
	}

	return nil
}
381180
func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {

	// We specify the KeysetFormatV1Alpha2 format, to upgrade from the legacy representation (separate files)
	// to the newer keyset.yaml representation.
	format := string(fi.KeysetFormatV1Alpha2)

	// TODO: Only create the CA via this task
	defaultCA := &fitasks.Keypair{
		Name:      fi.String(fi.CertificateId_CA),
		Lifecycle: b.Lifecycle,
		Subject:   "cn=kubernetes",
		Type:      "ca",
		Format:    format,
	}
	c.AddTask(defaultCA)

	{
		// @check of bootstrap tokens are enable if so, disable the creation of the kubelet certificate - we also
		// block at the IAM level for AWS cluster for pre-existing clusters.
		if !b.UseBootstrapTokens() {
			c.AddTask(&fitasks.Keypair{
				Name:      fi.String("kubelet"),
				Lifecycle: b.Lifecycle,
				Subject:   "o=" + user.NodesGroup + ",cn=kubelet",
				Type:      "client",
				Signer:    defaultCA,
				Format:    format,
			})
		}
	}
	{
		// Generate a kubelet client certificate for api to speak securely to kubelets. This change was first
		// introduced in https://github.com/kubernetes/kops/pull/2831 where server.cert/key were used. With kubernetes >= 1.7
		// the certificate usage is being checked (obviously the above was server not client certificate) and so now fails
		c.AddTask(&fitasks.Keypair{
			Name:      fi.String("kubelet-api"),
			Lifecycle: b.Lifecycle,
			Subject:   "cn=kubelet-api",
			Type:      "client",
			Signer:    defaultCA,
			Format:    format,
		})
	}
	{
		t := &fitasks.Keypair{
			Name:      fi.String("kube-scheduler"),
			Lifecycle: b.Lifecycle,
			Subject:   "cn=" + user.KubeScheduler,
			Type:      "client",
			Signer:    defaultCA,
			Format:    format,
		}
		c.AddTask(t)
	}

	{
		t := &fitasks.Keypair{
			Name:      fi.String("kube-proxy"),
			Lifecycle: b.Lifecycle,
			Subject:   "cn=" + user.KubeProxy,
			Type:      "client",
			Signer:    defaultCA,
			Format:    format,
		}
		c.AddTask(t)
	}

	{
		t := &fitasks.Keypair{
			Name:      fi.String("kube-controller-manager"),
			Lifecycle: b.Lifecycle,
			Subject:   "cn=" + user.KubeControllerManager,
			Type:      "client",
			Signer:    defaultCA,
			Format:    format,
		}
		c.AddTask(t)
	}

	if b.UseEtcdManager() {
		// We generate keypairs in the etcdmanager task itself
	} else if b.UseEtcdTLS() {
		// check if we need to generate certificates for etcd peers certificates from a different CA?
		// @question i think we should use another KeyStore for this, perhaps registering a EtcdKeyStore given
		// that mutual tls used to verify between the peers we don't want certificates for kubernetes able to act as a peer.
		// For clients assuming we are using etcdv3 is can switch on user authentication and map the common names for auth.
		servingNames := []string{fmt.Sprintf("*.internal.%s", b.ClusterName()), "localhost", "127.0.0.1"}
		// @question should wildcard's be here instead of generating per node. If we ever provide the
		// ability to resize the master, this will become a blocker
		c.AddTask(&fitasks.Keypair{
			AlternateNames: servingNames,
			Lifecycle:      b.Lifecycle,
			Name:           fi.String("etcd"),
			Subject:        "cn=etcd",
			// TODO: Can this be "server" now that we're not using it for peer connectivity?
			Type:   "clientServer",
			Signer: defaultCA,
			Format: format,
		})

		// For peer authentication, the same cert is used both as a client
		// cert and as a server cert (which is unusual).  Moreover, etcd
		// 3.2 introduces some breaking changes to certificate validation
		// where it tries to match any IP or DNS names to the client IP
		// (including reverse DNS lookups!)  We _could_ include a wildcard
		// reverse DNS name e.g. *.ec2.internal for EC2, but it seems
		// better just to list the names that we expect peer connectivity
		// to happen on.
		var peerNames []string
		for _, etcdCluster := range b.Cluster.Spec.EtcdClusters {
			prefix := "etcd-" + etcdCluster.Name + "-"
			if prefix == "etcd-main-" {
				prefix = "etcd-"
			}
			for _, m := range etcdCluster.Members {
				peerNames = append(peerNames, prefix+m.Name+".internal."+b.ClusterName())
			}
		}
		c.AddTask(&fitasks.Keypair{
			AlternateNames: peerNames,

			Lifecycle: b.Lifecycle,
			Name:      fi.String("etcd-peer"),
			Subject:   "cn=etcd-peer",
			Type:      "clientServer",
			Signer:    defaultCA,
			Format:    format,
		})

		c.AddTask(&fitasks.Keypair{
			Name:      fi.String("etcd-client"),
			Lifecycle: b.Lifecycle,
			Subject:   "cn=etcd-client",
			Type:      "client",
			Signer:    defaultCA,
			Format:    format,
		})

		// @check if calico or Cilium is enabled as the CNI provider
		if b.KopsModelContext.Cluster.Spec.Networking.Calico != nil || b.KopsModelContext.Cluster.Spec.Networking.Cilium != nil {
			c.AddTask(&fitasks.Keypair{
				Name:      fi.String("calico-client"),
				Lifecycle: b.Lifecycle,
				Subject:   "cn=calico-client",
				Type:      "client",
				Signer:    defaultCA,
				Format:    format,
			})
		}
	}

	if b.KopsModelContext.Cluster.Spec.Networking.Kuberouter != nil {
		t := &fitasks.Keypair{
			Name:    fi.String("kube-router"),
			Subject: "cn=" + "system:kube-router",
			Type:    "client",
			Signer:  defaultCA,
			Format:  format,
		}
		c.AddTask(t)
	}

	{
		t := &fitasks.Keypair{
			Name:      fi.String("kubecfg"),
			Lifecycle: b.Lifecycle,
			Subject:   "o=" + user.SystemPrivilegedGroup + ",cn=kubecfg",
			Type:      "client",
			Signer:    defaultCA,
			Format:    format,
		}
		c.AddTask(t)
	}

	{
		t := &fitasks.Keypair{
			Name:      fi.String("apiserver-proxy-client"),
			Lifecycle: b.Lifecycle,
			Subject:   "cn=apiserver-proxy-client",
			Type:      "client",
			Signer:    defaultCA,
			Format:    format,
		}
		c.AddTask(t)
	}

	{
		aggregatorCA := &fitasks.Keypair{
			Name:      fi.String("apiserver-aggregator-ca"),
			Lifecycle: b.Lifecycle,
			Subject:   "cn=apiserver-aggregator-ca",
			Type:      "ca",
			Format:    format,
		}
		c.AddTask(aggregatorCA)

		aggregator := &fitasks.Keypair{
			Name:      fi.String("apiserver-aggregator"),
			Lifecycle: b.Lifecycle,
			// Must match RequestheaderAllowedNames
			Subject: "cn=aggregator",
			Type:    "client",
			Signer:  aggregatorCA,
			Format:  format,
		}
		c.AddTask(aggregator)
	}

	{
		// Used by e.g. protokube
		t := &fitasks.Keypair{
			Name:      fi.String("kops"),
			Lifecycle: b.Lifecycle,
			Subject:   "o=" + user.SystemPrivilegedGroup + ",cn=kops",
			Type:      "client",
			Signer:    defaultCA,
			Format:    format,
		}
		c.AddTask(t)
	}

	{
		// A few names used from inside the cluster, which all resolve the same based on our default suffixes
		alternateNames := []string{
			"kubernetes",
			"kubernetes.default",
			"kubernetes.default.svc",
			"kubernetes.default.svc." + b.Cluster.Spec.ClusterDNSDomain,
		}

		// Names specified in the cluster spec
		alternateNames = append(alternateNames, b.Cluster.Spec.MasterPublicName)
		alternateNames = append(alternateNames, b.Cluster.Spec.MasterInternalName)
		alternateNames = append(alternateNames, b.Cluster.Spec.AdditionalSANs...)

		// Referencing it by internal IP should work also
		{
			ip, err := b.WellKnownServiceIP(1)
			if err != nil {
				return err
			}
			alternateNames = append(alternateNames, ip.String())
		}

		// We also want to be able to reference it locally via https://127.0.0.1
		alternateNames = append(alternateNames, "127.0.0.1")

		t := &fitasks.Keypair{
			Name:           fi.String("master"),
			Lifecycle:      b.Lifecycle,
			Subject:        "cn=kubernetes-master",
			Type:           "server",
			AlternateNames: alternateNames,
			Signer:         defaultCA,
			Format:         format,
		}
		c.AddTask(t)
	}

	if b.Cluster.Spec.Authentication != nil {
		if b.KopsModelContext.Cluster.Spec.Authentication.Aws != nil {
			alternateNames := []string{
				"localhost",
				"127.0.0.1",
			}

			t := &fitasks.Keypair{
				Name:           fi.String("aws-iam-authenticator"),
				Subject:        "cn=aws-iam-authenticator",
				Type:           "server",
				AlternateNames: alternateNames,
				Signer:         defaultCA,
				Format:         format,
			}
			c.AddTask(t)
		}
	}

	// @TODO this is VERY presumptuous, i'm going on the basis we can make it configurable in the future.
	// But I'm conscious not to do too much work on bootstrap tokens as it might overlay further down the
	// line with the machines api
	if b.UseBootstrapTokens() {
		serviceName := "node-authorizer-internal"

		alternateNames := []string{
			"127.0.0.1",
			"localhost",
			serviceName,
			strings.Join([]string{serviceName, b.Cluster.Name}, "."),
			strings.Join([]string{serviceName, b.Cluster.Spec.DNSZone}, "."),
		}

		// @note: the certificate used by the node authorizers
		c.AddTask(&fitasks.Keypair{
			Name:           fi.String("node-authorizer"),
			Subject:        "cn=node-authorizaer",
			Type:           "server",
			AlternateNames: alternateNames,
			Signer:         defaultCA,
			Format:         format,
		})

		// @note: we use this for mutual tls between node and authorizer
		c.AddTask(&fitasks.Keypair{
			Name:    fi.String("node-authorizer-client"),
			Subject: "cn=node-authorizer-client",
			Type:    "client",
			Signer:  defaultCA,
			Format:  format,
		})
	}

	// Create auth tokens (though this is deprecated)
	for _, x := range tokens.GetKubernetesAuthTokens_Deprecated() {
		c.AddTask(&fitasks.Secret{Name: fi.String(x), Lifecycle: b.Lifecycle})
	}

	{
		mirrorPath, err := vfs.Context.BuildVfsPath(b.Cluster.Spec.SecretStore)
		if err != nil {
			return err
		}

		t := &fitasks.MirrorSecrets{
			Name:       fi.String("mirror-secrets"),
			MirrorPath: mirrorPath,
		}
		c.AddTask(t)
	}

	{
		mirrorPath, err := vfs.Context.BuildVfsPath(b.Cluster.Spec.KeyStore)
		if err != nil {
			return err
		}

		// Keypair used by the kubelet
		t := &fitasks.MirrorKeystore{
			Name:       fi.String("mirror-keystore"),
			MirrorPath: mirrorPath,
		}
		c.AddTask(t)
	}

	return nil
}
703670
func EnsureBuildNode(g osgraph.MutableUniqueGraph, build *buildv1.Build) *BuildNode {
	return osgraph.EnsureUnique(g,
		BuildNodeName(build),
		func(node osgraph.Node) graph.Node {
			return &BuildNode{node, build}
		},
	).(*BuildNode)
}
929057
func (b *KubeletBuilder) buildSystemdEnvironmentFile(kubeletConfig *kops.KubeletConfigSpec) (*nodetasks.File, error) {
	// @step: ensure the masters do not get a bootstrap configuration
	if b.UseBootstrapTokens() && b.IsMaster {
		kubeletConfig.BootstrapKubeconfig = ""
	}

	if kubeletConfig.ExperimentalAllowedUnsafeSysctls != nil {
		// The ExperimentalAllowedUnsafeSysctls flag was renamed in k/k #63717
		if b.IsKubernetesGTE("1.11") {
			glog.V(1).Info("ExperimentalAllowedUnsafeSysctls was renamed in k8s 1.11+, please use AllowedUnsafeSysctls instead.")
			kubeletConfig.AllowedUnsafeSysctls = append(kubeletConfig.ExperimentalAllowedUnsafeSysctls, kubeletConfig.AllowedUnsafeSysctls...)
			kubeletConfig.ExperimentalAllowedUnsafeSysctls = nil
		}
	}

	// TODO: Dump the separate file for flags - just complexity!
	flags, err := flagbuilder.BuildFlags(kubeletConfig)
	if err != nil {
		return nil, fmt.Errorf("error building kubelet flags: %v", err)
	}

	// Add cloud config file if needed
	// We build this flag differently because it depends on CloudConfig, and to expose it directly
	// would be a degree of freedom we don't have (we'd have to write the config to different files)
	// We can always add this later if it is needed.
	if b.Cluster.Spec.CloudConfig != nil {
		flags += " --cloud-config=" + CloudConfigFilePath
	}

	if b.UsesCNI() {
		flags += " --cni-bin-dir=" + b.CNIBinDir()
		flags += " --cni-conf-dir=" + b.CNIConfDir()
	}

	if b.UsesSecondaryIP() {
		sess := session.Must(session.NewSession())
		metadata := ec2metadata.New(sess)
		localIpv4, err := metadata.GetMetadata("local-ipv4")
		if err != nil {
			return nil, fmt.Errorf("error fetching the local-ipv4 address from the ec2 meta-data: %v", err)
		}
		flags += " --node-ip=" + localIpv4
	}

	if b.Cluster.Spec.Networking != nil && b.Cluster.Spec.Networking.Kubenet != nil {
		// Kubenet is neither CNI nor not-CNI, so we need to pass it `--cni-bin-dir` also
		if b.IsKubernetesGTE("1.9") {
			// Flag renamed in #53564
			flags += " --cni-bin-dir=" + b.CNIBinDir()
		} else {
			flags += " --network-plugin-dir=" + b.CNIBinDir()
		}
	}

	if b.usesContainerizedMounter() {
		// We don't want to expose this in the model while it is experimental, but it is needed on COS
		flags += " --experimental-mounter-path=" + path.Join(containerizedMounterHome, "mounter")
	}

	sysconfig := "DAEMON_ARGS=\"" + flags + "\"\n"
	// Makes kubelet read /root/.docker/config.json properly
	sysconfig = sysconfig + "HOME=\"/root" + "\"\n"

	t := &nodetasks.File{
		Path:     "/etc/sysconfig/kubelet",
		Contents: fi.NewStringResource(sysconfig),
		Type:     nodetasks.FileType_File,
	}

	return t, nil
}