Merge pull request #2559 from RainbowMango/pr_update_kind

Update kind dependency to get ready for testing against kubernetes v1.25
This commit is contained in:
karmada-bot 2022-09-22 14:18:51 +08:00 committed by GitHub
commit 10990cd96c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 280 additions and 118 deletions

4
go.mod
View File

@ -41,7 +41,7 @@ require (
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
sigs.k8s.io/cluster-api v1.0.1
sigs.k8s.io/controller-runtime v0.12.2
sigs.k8s.io/kind v0.14.0
sigs.k8s.io/kind v0.15.0
sigs.k8s.io/mcs-api v0.1.0
sigs.k8s.io/structured-merge-diff/v4 v4.2.1
sigs.k8s.io/yaml v1.3.0
@ -163,7 +163,7 @@ require (
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/square/go-jose.v2 v2.2.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect

7
go.sum
View File

@ -1486,8 +1486,9 @@ gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
@ -1595,8 +1596,8 @@ sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WG
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y=
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
sigs.k8s.io/kind v0.8.1/go.mod h1:oNKTxUVPYkV9lWzY6CVMNluVq8cBsyq+UgPJdvA3uu4=
sigs.k8s.io/kind v0.14.0 h1:cNmI3jGBvp7UegEGbC5we8plDtCUmaNRL+bod7JoSCE=
sigs.k8s.io/kind v0.14.0/go.mod h1:UrFRPHG+2a5j0Q7qiR4gtJ4rEyn8TuMQwuOPf+m4oHg=
sigs.k8s.io/kind v0.15.0 h1:Fskj234L4hjQlsScCgeYvCBIRt06cjLzc7+kbr1u8Tg=
sigs.k8s.io/kind v0.15.0/go.mod h1:cKTqagdRyUQmihhBOd+7p43DpOPRn9rHsUC08K1Jbsk=
sigs.k8s.io/kustomize/api v0.8.11/go.mod h1:a77Ls36JdfCWojpUqR6m60pdGY1AYFix4AH83nJtY1g=
sigs.k8s.io/kustomize/api v0.11.4 h1:/0Mr3kfBBNcNPOW5Qwk/3eb8zkswCwnqQxxKtmrTkRo=
sigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI=

78
vendor/gopkg.in/yaml.v3/decode.go generated vendored
View File

@ -100,7 +100,10 @@ func (p *parser) peek() yaml_event_type_t {
if p.event.typ != yaml_NO_EVENT {
return p.event.typ
}
if !yaml_parser_parse(&p.parser, &p.event) {
// It's curious choice from the underlying API to generally return a
// positive result on success, but on this case return true in an error
// scenario. This was the source of bugs in the past (issue #666).
if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR {
p.fail()
}
return p.event.typ
@ -320,6 +323,8 @@ type decoder struct {
decodeCount int
aliasCount int
aliasDepth int
mergedFields map[interface{}]bool
}
var (
@ -808,6 +813,11 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
}
}
mergedFields := d.mergedFields
d.mergedFields = nil
var mergeNode *Node
mapIsNew := false
if out.IsNil() {
out.Set(reflect.MakeMap(outt))
@ -815,11 +825,18 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
}
for i := 0; i < l; i += 2 {
if isMerge(n.Content[i]) {
d.merge(n.Content[i+1], out)
mergeNode = n.Content[i+1]
continue
}
k := reflect.New(kt).Elem()
if d.unmarshal(n.Content[i], k) {
if mergedFields != nil {
ki := k.Interface()
if mergedFields[ki] {
continue
}
mergedFields[ki] = true
}
kkind := k.Kind()
if kkind == reflect.Interface {
kkind = k.Elem().Kind()
@ -833,6 +850,12 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
}
}
}
d.mergedFields = mergedFields
if mergeNode != nil {
d.merge(n, mergeNode, out)
}
d.stringMapType = stringMapType
d.generalMapType = generalMapType
return true
@ -844,7 +867,8 @@ func isStringMap(n *Node) bool {
}
l := len(n.Content)
for i := 0; i < l; i += 2 {
if n.Content[i].ShortTag() != strTag {
shortTag := n.Content[i].ShortTag()
if shortTag != strTag && shortTag != mergeTag {
return false
}
}
@ -861,7 +885,6 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
var elemType reflect.Type
if sinfo.InlineMap != -1 {
inlineMap = out.Field(sinfo.InlineMap)
inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
elemType = inlineMap.Type().Elem()
}
@ -870,6 +893,9 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
d.prepare(n, field)
}
mergedFields := d.mergedFields
d.mergedFields = nil
var mergeNode *Node
var doneFields []bool
if d.uniqueKeys {
doneFields = make([]bool, len(sinfo.FieldsList))
@ -879,13 +905,20 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
for i := 0; i < l; i += 2 {
ni := n.Content[i]
if isMerge(ni) {
d.merge(n.Content[i+1], out)
mergeNode = n.Content[i+1]
continue
}
if !d.unmarshal(ni, name) {
continue
}
if info, ok := sinfo.FieldsMap[name.String()]; ok {
sname := name.String()
if mergedFields != nil {
if mergedFields[sname] {
continue
}
mergedFields[sname] = true
}
if info, ok := sinfo.FieldsMap[sname]; ok {
if d.uniqueKeys {
if doneFields[info.Id] {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
@ -911,6 +944,11 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
}
}
d.mergedFields = mergedFields
if mergeNode != nil {
d.merge(n, mergeNode, out)
}
return true
}
@ -918,19 +956,29 @@ func failWantMap() {
failf("map merge requires map or sequence of maps as the value")
}
func (d *decoder) merge(n *Node, out reflect.Value) {
switch n.Kind {
func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) {
mergedFields := d.mergedFields
if mergedFields == nil {
d.mergedFields = make(map[interface{}]bool)
for i := 0; i < len(parent.Content); i += 2 {
k := reflect.New(ifaceType).Elem()
if d.unmarshal(parent.Content[i], k) {
d.mergedFields[k.Interface()] = true
}
}
}
switch merge.Kind {
case MappingNode:
d.unmarshal(n, out)
d.unmarshal(merge, out)
case AliasNode:
if n.Alias != nil && n.Alias.Kind != MappingNode {
if merge.Alias != nil && merge.Alias.Kind != MappingNode {
failWantMap()
}
d.unmarshal(n, out)
d.unmarshal(merge, out)
case SequenceNode:
// Step backwards as earlier nodes take precedence.
for i := len(n.Content) - 1; i >= 0; i-- {
ni := n.Content[i]
for i := 0; i < len(merge.Content); i++ {
ni := merge.Content[i]
if ni.Kind == AliasNode {
if ni.Alias != nil && ni.Alias.Kind != MappingNode {
failWantMap()
@ -943,6 +991,8 @@ func (d *decoder) merge(n *Node, out reflect.Value) {
default:
failWantMap()
}
d.mergedFields = mergedFields
}
func isMerge(n *Node) bool {

11
vendor/gopkg.in/yaml.v3/parserc.go generated vendored
View File

@ -687,6 +687,9 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
if token == nil {
return false
}
parser.marks = append(parser.marks, token.start_mark)
skip_token(parser)
}
@ -786,7 +789,7 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
}
token := peek_token(parser)
if token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
return
}
@ -813,6 +816,9 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
if token == nil {
return false
}
parser.marks = append(parser.marks, token.start_mark)
skip_token(parser)
}
@ -922,6 +928,9 @@ func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_ev
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
if token == nil {
return false
}
parser.marks = append(parser.marks, token.start_mark)
skip_token(parser)
}

4
vendor/modules.txt vendored
View File

@ -751,7 +751,7 @@ gopkg.in/square/go-jose.v2/json
# gopkg.in/yaml.v2 v2.4.0
## explicit; go 1.15
gopkg.in/yaml.v2
# gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
# gopkg.in/yaml.v3 v3.0.1
## explicit
gopkg.in/yaml.v3
# k8s.io/api v0.24.2
@ -1539,7 +1539,7 @@ sigs.k8s.io/controller-runtime/pkg/webhook/internal/metrics
## explicit; go 1.17
sigs.k8s.io/json
sigs.k8s.io/json/internal/golang/encoding/json
# sigs.k8s.io/kind v0.14.0
# sigs.k8s.io/kind v0.15.0
## explicit; go 1.14
sigs.k8s.io/kind/pkg/apis/config/defaults
sigs.k8s.io/kind/pkg/apis/config/v1alpha4

View File

@ -18,4 +18,4 @@ limitations under the License.
package defaults
// Image is the default for the Config.Image field, aka the default node image.
const Image = "kindest/node:v1.24.0@sha256:0866296e693efe1fed79d5e6c7af8df71fc73ae45e3679af05342239cdc5bc8e"
const Image = "kindest/node:v1.25.0@sha256:428aaa17ec82ccde0131cb2d1ca6547d13cf5fdabcc0bbecf749baa935387cbf"

View File

@ -18,33 +18,33 @@ package v1alpha4
// Cluster contains kind cluster configuration
type Cluster struct {
TypeMeta `yaml:",inline"`
TypeMeta `yaml:",inline" json:",inline"`
// The cluster name.
// Optional, this will be overridden by --name / KIND_CLUSTER_NAME
Name string `yaml:"name,omitempty"`
Name string `yaml:"name,omitempty" json:"name,omitempty"`
// Nodes contains the list of nodes defined in the `kind` Cluster
// If unset this will default to a single control-plane node
// Note that if more than one control plane is specified, an external
// control plane load balancer will be provisioned implicitly
Nodes []Node `yaml:"nodes,omitempty"`
Nodes []Node `yaml:"nodes,omitempty" json:"nodes,omitempty"`
/* Advanced fields */
// Networking contains cluster wide network settings
Networking Networking `yaml:"networking,omitempty"`
Networking Networking `yaml:"networking,omitempty" json:"networking,omitempty"`
// FeatureGates contains a map of Kubernetes feature gates to whether they
// are enabled. The feature gates specified here are passed to all Kubernetes components as flags or in config.
//
// https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/
FeatureGates map[string]bool `yaml:"featureGates,omitempty"`
FeatureGates map[string]bool `yaml:"featureGates,omitempty" json:"featureGates,omitempty"`
// RuntimeConfig Keys and values are translated into --runtime-config values for kube-apiserver, separated by commas.
//
// Use this to enable alpha APIs.
RuntimeConfig map[string]string `yaml:"runtimeConfig,omitempty"`
RuntimeConfig map[string]string `yaml:"runtimeConfig,omitempty" json:"runtimeConfig,omitempty"`
// KubeadmConfigPatches are applied to the generated kubeadm config as
// merge patches. The `kind` field must match the target object, and
@ -55,7 +55,7 @@ type Cluster struct {
// https://tools.ietf.org/html/rfc7386
//
// The cluster-level patches are applied before the node-level patches.
KubeadmConfigPatches []string `yaml:"kubeadmConfigPatches,omitempty"`
KubeadmConfigPatches []string `yaml:"kubeadmConfigPatches,omitempty" json:"kubeadmConfigPatches,omitempty"`
// KubeadmConfigPatchesJSON6902 are applied to the generated kubeadm config
// as JSON 6902 patches. The `kind` field must match the target object, and
@ -70,53 +70,53 @@ type Cluster struct {
// https://tools.ietf.org/html/rfc6902
//
// The cluster-level patches are applied before the node-level patches.
KubeadmConfigPatchesJSON6902 []PatchJSON6902 `yaml:"kubeadmConfigPatchesJSON6902,omitempty"`
KubeadmConfigPatchesJSON6902 []PatchJSON6902 `yaml:"kubeadmConfigPatchesJSON6902,omitempty" json:"kubeadmConfigPatchesJSON6902,omitempty"`
// ContainerdConfigPatches are applied to every node's containerd config
// in the order listed.
// These should be toml stringsto be applied as merge patches
ContainerdConfigPatches []string `yaml:"containerdConfigPatches,omitempty"`
ContainerdConfigPatches []string `yaml:"containerdConfigPatches,omitempty" json:"containerdConfigPatches,omitempty"`
// ContainerdConfigPatchesJSON6902 are applied to every node's containerd config
// in the order listed.
// These should be YAML or JSON formatting RFC 6902 JSON patches
ContainerdConfigPatchesJSON6902 []string `yaml:"containerdConfigPatchesJSON6902,omitempty"`
ContainerdConfigPatchesJSON6902 []string `yaml:"containerdConfigPatchesJSON6902,omitempty" json:"containerdConfigPatchesJSON6902,omitempty"`
}
// TypeMeta partially copies apimachinery/pkg/apis/meta/v1.TypeMeta
// No need for a direct dependence; the fields are stable.
type TypeMeta struct {
Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`
APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`
Kind string `yaml:"kind,omitempty" json:"kind,omitempty"`
APIVersion string `yaml:"apiVersion,omitempty" json:"apiVersion,omitempty"`
}
// Node contains settings for a node in the `kind` Cluster.
// A node in kind config represent a container that will be provisioned with all the components
// required for the assigned role in the Kubernetes cluster
type Node struct {
// Role defines the role of the node in the in the Kubernetes cluster
// Role defines the role of the node in the Kubernetes cluster
// created by kind
//
// Defaults to "control-plane"
Role NodeRole `yaml:"role,omitempty"`
Role NodeRole `yaml:"role,omitempty" json:"role,omitempty"`
// Image is the node image to use when creating this node
// If unset a default image will be used, see defaults.Image
Image string `yaml:"image,omitempty"`
Image string `yaml:"image,omitempty" json:"image,omitempty"`
// Labels are the labels with which the respective node will be labeled
Labels map[string]string `yaml:"labels,omitempty"`
Labels map[string]string `yaml:"labels,omitempty" json:"labels,omitempty"`
/* Advanced fields */
// TODO: cri-like types should be inline instead
// ExtraMounts describes additional mount points for the node container
// These may be used to bind a hostPath
ExtraMounts []Mount `yaml:"extraMounts,omitempty"`
ExtraMounts []Mount `yaml:"extraMounts,omitempty" json:"extraMounts,omitempty"`
// ExtraPortMappings describes additional port mappings for the node container
// binded to a host Port
ExtraPortMappings []PortMapping `yaml:"extraPortMappings,omitempty"`
ExtraPortMappings []PortMapping `yaml:"extraPortMappings,omitempty" json:"extraPortMappings,omitempty"`
// KubeadmConfigPatches are applied to the generated kubeadm config as
// merge patches. The `kind` field must match the target object, and
@ -128,7 +128,7 @@ type Node struct {
//
// The node-level patches will be applied after the cluster-level patches
// have been applied. (See Cluster.KubeadmConfigPatches)
KubeadmConfigPatches []string `yaml:"kubeadmConfigPatches,omitempty"`
KubeadmConfigPatches []string `yaml:"kubeadmConfigPatches,omitempty" json:"kubeadmConfigPatches,omitempty"`
// KubeadmConfigPatchesJSON6902 are applied to the generated kubeadm config
// as JSON 6902 patches. The `kind` field must match the target object, and
@ -144,7 +144,7 @@ type Node struct {
//
// The node-level patches will be applied after the cluster-level patches
// have been applied. (See Cluster.KubeadmConfigPatchesJSON6902)
KubeadmConfigPatchesJSON6902 []PatchJSON6902 `yaml:"kubeadmConfigPatchesJSON6902,omitempty"`
KubeadmConfigPatchesJSON6902 []PatchJSON6902 `yaml:"kubeadmConfigPatchesJSON6902,omitempty" json:"kubeadmConfigPatchesJSON6902,omitempty"`
}
// NodeRole defines possible role for nodes in a Kubernetes cluster managed by `kind`
@ -163,7 +163,7 @@ const (
// Networking contains cluster wide network settings
type Networking struct {
// IPFamily is the network cluster model, currently it can be ipv4 or ipv6
IPFamily ClusterIPFamily `yaml:"ipFamily,omitempty"`
IPFamily ClusterIPFamily `yaml:"ipFamily,omitempty" json:"ipFamily,omitempty"`
// APIServerPort is the listen port on the host for the Kubernetes API Server
// Defaults to a random port on the host obtained by kind
//
@ -171,24 +171,24 @@ type Networking struct {
// (docker, podman...) will be left to pick the port instead.
// This is potentially useful for remote hosts, BUT it means when the container
// is restarted it will be randomized. Leave this unset to allow kind to pick it.
APIServerPort int32 `yaml:"apiServerPort,omitempty"`
APIServerPort int32 `yaml:"apiServerPort,omitempty" json:"apiServerPort,omitempty"`
// APIServerAddress is the listen address on the host for the Kubernetes
// API Server. This should be an IP address.
//
// Defaults to 127.0.0.1
APIServerAddress string `yaml:"apiServerAddress,omitempty"`
APIServerAddress string `yaml:"apiServerAddress,omitempty" json:"apiServerAddress,omitempty"`
// PodSubnet is the CIDR used for pod IPs
// kind will select a default if unspecified
PodSubnet string `yaml:"podSubnet,omitempty"`
PodSubnet string `yaml:"podSubnet,omitempty" json:"podSubnet,omitempty"`
// ServiceSubnet is the CIDR used for services VIPs
// kind will select a default if unspecified for IPv6
ServiceSubnet string `yaml:"serviceSubnet,omitempty"`
ServiceSubnet string `yaml:"serviceSubnet,omitempty" json:"serviceSubnet,omitempty"`
// If DisableDefaultCNI is true, kind will not install the default CNI setup.
// Instead the user should install their own CNI after creating the cluster.
DisableDefaultCNI bool `yaml:"disableDefaultCNI,omitempty"`
DisableDefaultCNI bool `yaml:"disableDefaultCNI,omitempty" json:"disableDefaultCNI,omitempty"`
// KubeProxyMode defines if kube-proxy should operate in iptables or ipvs mode
// Defaults to 'iptables' mode
KubeProxyMode ProxyMode `yaml:"kubeProxyMode,omitempty"`
KubeProxyMode ProxyMode `yaml:"kubeProxyMode,omitempty" json:"kubeProxyMode,omitempty"`
}
// ClusterIPFamily defines cluster network IP family
@ -217,11 +217,11 @@ const (
// https://tools.ietf.org/html/rfc6902
type PatchJSON6902 struct {
// these fields specify the patch target resource
Group string `yaml:"group"`
Version string `yaml:"version"`
Kind string `yaml:"kind"`
Group string `yaml:"group" json:"group"`
Version string `yaml:"version" json:"version"`
Kind string `yaml:"kind" json:"kind"`
// Patch should contain the contents of the json patch as a string
Patch string `yaml:"patch"`
Patch string `yaml:"patch" json:"patch"`
}
/*
@ -236,36 +236,39 @@ https://github.com/kubernetes/kubernetes/blob/063e7ff358fdc8b0916e6f39beedc0d025
// names on disk as opposed to the int32 values, and the serialized field names
// have been made closer to core/v1 VolumeMount field names
// In yaml this looks like:
// containerPath: /foo
// hostPath: /bar
// readOnly: true
// selinuxRelabel: false
// propagation: None
//
// containerPath: /foo
// hostPath: /bar
// readOnly: true
// selinuxRelabel: false
// propagation: None
//
// Propagation may be one of: None, HostToContainer, Bidirectional
type Mount struct {
// Path of the mount within the container.
ContainerPath string `yaml:"containerPath,omitempty"`
ContainerPath string `yaml:"containerPath,omitempty" json:"containerPath,omitempty"`
// Path of the mount on the host. If the hostPath doesn't exist, then runtimes
// should report error. If the hostpath is a symbolic link, runtimes should
// follow the symlink and mount the real destination to container.
HostPath string `yaml:"hostPath,omitempty"`
HostPath string `yaml:"hostPath,omitempty" json:"hostPath,omitempty"`
// If set, the mount is read-only.
Readonly bool `yaml:"readOnly,omitempty"`
Readonly bool `yaml:"readOnly,omitempty" json:"readOnly,omitempty"`
// If set, the mount needs SELinux relabeling.
SelinuxRelabel bool `yaml:"selinuxRelabel,omitempty"`
SelinuxRelabel bool `yaml:"selinuxRelabel,omitempty" json:"selinuxRelabel,omitempty"`
// Requested propagation mode.
Propagation MountPropagation `yaml:"propagation,omitempty"`
Propagation MountPropagation `yaml:"propagation,omitempty" json:"propagation,omitempty"`
}
// PortMapping specifies a host port mapped into a container port.
// In yaml this looks like:
// containerPort: 80
// hostPort: 8000
// listenAddress: 127.0.0.1
// protocol: TCP
//
// containerPort: 80
// hostPort: 8000
// listenAddress: 127.0.0.1
// protocol: TCP
type PortMapping struct {
// Port within the container.
ContainerPort int32 `yaml:"containerPort,omitempty"`
ContainerPort int32 `yaml:"containerPort,omitempty" json:"containerPort,omitempty"`
// Port on the host.
//
// If unset, a random port will be selected.
@ -274,11 +277,11 @@ type PortMapping struct {
// (docker, podman...) will be left to pick the port instead.
// This is potentially useful for remote hosts, BUT it means when the container
// is restarted it will be randomized. Leave this unset to allow kind to pick it.
HostPort int32 `yaml:"hostPort,omitempty"`
HostPort int32 `yaml:"hostPort,omitempty" json:"hostPort,omitempty"`
// TODO: add protocol (tcp/udp) and port-ranges
ListenAddress string `yaml:"listenAddress,omitempty"`
ListenAddress string `yaml:"listenAddress,omitempty" json:"listenAddress,omitempty"`
// Protocol (TCP/UDP/SCTP)
Protocol PortMappingProtocol `yaml:"protocol,omitempty"`
Protocol PortMappingProtocol `yaml:"protocol,omitempty" json:"protocol,omitempty"`
}
// MountPropagation represents an "enum" for mount propagation options,

View File

@ -131,7 +131,7 @@ func waitForReady(node nodes.Node, until time.Time, selectorLabel string) bool {
})
}
// helper that calls `try()`` in a loop until the deadline `until`
// helper that calls `try() in a loop until the deadline `until`
// has passed or `try()`returns true, returns whether try ever returned true
func tryUntil(until time.Time, try func() bool) bool {
for until.After(time.Now()) {

View File

@ -75,14 +75,16 @@ type ConfigData struct {
// Labels are the labels, in the format "key1=val1,key2=val2", with which the respective node will be labeled
NodeLabels string
// DerivedConfigData is populated by Derive()
// These auto-generated fields are available to Config templates,
// but not meant to be set by hand
DerivedConfigData
// Provider is running with rootless mode, so kube-proxy needs to be configured
// not to fail on sysctl error.
// RootlessProvider is true if kind is running with rootless mode
RootlessProvider bool
// DisableLocalStorageCapacityIsolation is typically set true based on RootlessProvider
// based on the Kubernetes version, if true kubelet localStorageCapacityIsolation is set false
DisableLocalStorageCapacityIsolation bool
// DerivedConfigData contains fields computed from the other fields for use
// in the config templates and should only be populated by calling Derive()
DerivedConfigData
}
// DerivedConfigData fields are automatically derived by
@ -266,7 +268,7 @@ evictionHard:
imagefs.available: "0%"
{{if .FeatureGates}}featureGates:
{{ range $key := .SortedFeatureGateKeys }}
"{{ $key }}": {{$.FeatureGates $key }}
"{{ $key }}": {{index $.FeatureGates $key }}
{{end}}{{end}}
{{if ne .KubeProxyMode "None"}}
---
@ -537,6 +539,7 @@ evictionHard:
{{ range $key := .SortedFeatureGateKeys }}
"{{ $key }}": {{ index $.FeatureGates $key }}
{{end}}{{end}}
{{if .DisableLocalStorageCapacityIsolation}}localStorageCapacityIsolation: false{{end}}
{{if ne .KubeProxyMode "None"}}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
@ -585,7 +588,13 @@ func Config(data ConfigData) (config string, err error) {
// For avoiding err="failed to get rootfs info: failed to get device for dir \"/var/lib/kubelet\": could not find device with major: 0, minor: 41 in cached partitions map"
// https://github.com/kubernetes-sigs/kind/issues/2524
data.FeatureGates["LocalStorageCapacityIsolation"] = false
if ver.LessThan(version.MustParseSemantic("v1.25.0-alpha.3.440+0064010cddfa00")) {
// this feature gate was removed in v1.25 and replaced by an opt-out to disable
data.FeatureGates["LocalStorageCapacityIsolation"] = false
} else {
// added in v1.25 https://github.com/kubernetes/kubernetes/pull/111513
data.DisableLocalStorageCapacityIsolation = true
}
}
// assume the latest API version, then fallback if the k8s version is too low

View File

@ -31,7 +31,7 @@ const kubeconfigEnv = "KUBECONFIG"
paths returns the list of paths to be considered for kubeconfig files
where explicitPath is the value of --kubeconfig
Logic based on kubectl
# Logic based on kubectl
https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands

View File

@ -17,7 +17,7 @@ limitations under the License.
package loadbalancer
// Image defines the loadbalancer image:tag
const Image = "kindest/haproxy:v20220510-a42b3ea0"
const Image = "kindest/haproxy:v20220607-9a4d8d2a"
// ConfigPath defines the path to the config file in the image
const ConfigPath = "/usr/local/etc/haproxy/haproxy.cfg"

View File

@ -18,6 +18,7 @@ package podman
import (
"context"
"encoding/json"
"fmt"
"net"
"path/filepath"
@ -37,7 +38,16 @@ import (
func planCreation(cfg *config.Cluster, networkName string) (createContainerFuncs []func() error, err error) {
// these apply to all container creation
nodeNamer := common.MakeNodeNamer(cfg.Name)
genericArgs, err := commonArgs(cfg, networkName)
names := make([]string, len(cfg.Nodes))
for i, node := range cfg.Nodes {
name := nodeNamer(string(node.Role)) // name the node
names[i] = name
}
haveLoadbalancer := config.ClusterHasImplicitLoadBalancer(cfg)
if haveLoadbalancer {
names = append(names, nodeNamer(constants.ExternalLoadBalancerNodeRoleValue))
}
genericArgs, err := commonArgs(cfg, networkName, names)
if err != nil {
return nil, err
}
@ -58,7 +68,7 @@ func planCreation(cfg *config.Cluster, networkName string) (createContainerFuncs
apiServerAddress = "::1" // only the LB needs to be non-local
}
// plan loadbalancer node
name := nodeNamer(constants.ExternalLoadBalancerNodeRoleValue)
name := names[len(names)-1]
createContainerFuncs = append(createContainerFuncs, func() error {
args, err := runArgsForLoadBalancer(cfg, name, genericArgs)
if err != nil {
@ -69,9 +79,9 @@ func planCreation(cfg *config.Cluster, networkName string) (createContainerFuncs
}
// plan normal nodes
for _, node := range cfg.Nodes {
node := node.DeepCopy() // copy so we can modify
name := nodeNamer(string(node.Role)) // name the node
for i, node := range cfg.Nodes {
node := node.DeepCopy() // copy so we can modify
name := names[i]
// fixup relative paths, podman can only handle absolute paths
for i := range node.ExtraMounts {
@ -116,7 +126,7 @@ func planCreation(cfg *config.Cluster, networkName string) (createContainerFuncs
}
// commonArgs computes static arguments that apply to all containers
func commonArgs(cfg *config.Cluster, networkName string) ([]string, error) {
func commonArgs(cfg *config.Cluster, networkName string, nodeNames []string) ([]string, error) {
// standard arguments all nodes containers need, computed once
args := []string{
"--detach", // run the container detached
@ -134,7 +144,7 @@ func commonArgs(cfg *config.Cluster, networkName string) ([]string, error) {
}
// pass proxy environment variables
proxyEnv, err := getProxyEnv(cfg, networkName)
proxyEnv, err := getProxyEnv(cfg, networkName, nodeNames)
if err != nil {
return nil, errors.Wrap(err, "proxy setup error")
}
@ -241,7 +251,7 @@ func runArgsForLoadBalancer(cfg *config.Cluster, name string, args []string) ([]
return append(args, image), nil
}
func getProxyEnv(cfg *config.Cluster, networkName string) (map[string]string, error) {
func getProxyEnv(cfg *config.Cluster, networkName string, nodeNames []string) (map[string]string, error) {
envs := common.GetProxyEnvs(cfg)
// Specifically add the podman network subnets to NO_PROXY if we are using a proxy
if len(envs) > 0 {
@ -251,11 +261,13 @@ func getProxyEnv(cfg *config.Cluster, networkName string) (map[string]string, er
return nil, err
}
noProxyList := append(subnets, envs[common.NOProxy])
// Add pod and service dns names to no_proxy to allow in cluster
noProxyList = append(noProxyList, nodeNames...)
// Add pod,service and all the cluster nodes' dns names to no_proxy to allow in cluster
// Note: this is best effort based on the default CoreDNS spec
// https://github.com/kubernetes/dns/blob/master/docs/specification.md
// Any user created pod/service hostnames, namespaces, custom DNS services
// are expected to be no-proxied by the user explicitly.
noProxyList = append(noProxyList, ".svc", ".svc.cluster", ".svc.cluster.local")
noProxyJoined := strings.Join(noProxyList, ",")
envs[common.NOProxy] = noProxyJoined
@ -264,15 +276,54 @@ func getProxyEnv(cfg *config.Cluster, networkName string) (map[string]string, er
return envs, nil
}
type podmanNetworks []struct {
// v4+
Subnets []struct {
Subnet string `json:"subnet"`
Gateway string `json:"gateway"`
} `json:"subnets"`
// v3 and anything still using CNI/IPAM
Plugins []struct {
Ipam struct {
Ranges [][]struct {
Gateway string `json:"gateway"`
Subnet string `json:"subnet"`
} `json:"ranges"`
} `json:"ipam,omitempty"`
} `json:"plugins"`
}
func getSubnets(networkName string) ([]string, error) {
// TODO: unmarshall json and get rid of this complex query
format := `{{ range (index (index (index (index . "plugins") 0 ) "ipam" ) "ranges")}}{{ index ( index . 0 ) "subnet" }} {{end}}`
cmd := exec.Command("podman", "network", "inspect", "-f", format, networkName)
lines, err := exec.OutputLines(cmd)
cmd := exec.Command("podman", "network", "inspect", networkName)
out, err := exec.Output(cmd)
if err != nil {
return nil, errors.Wrap(err, "failed to get subnets")
}
return strings.Split(strings.TrimSpace(lines[0]), " "), nil
networks := podmanNetworks{}
jsonErr := json.Unmarshal([]byte(out), &networks)
if jsonErr != nil {
return nil, errors.Wrap(jsonErr, "failed to get subnets")
}
subnets := []string{}
for _, network := range networks {
if len(network.Subnets) > 0 {
for _, subnet := range network.Subnets {
subnets = append(subnets, subnet.Subnet)
}
}
if len(network.Plugins) > 0 {
for _, plugin := range network.Plugins {
for _, r := range plugin.Ipam.Ranges {
for _, rr := range r {
subnets = append(subnets, rr.Subnet)
}
}
}
}
}
return subnets, nil
}
// generateMountBindings converts the mount list to a list of args for podman

View File

@ -126,3 +126,31 @@ func ImageID(n nodes.Node, image string) (string, error) {
}
return crictlOut.Status.ID, nil
}
// ImageTags is used to perform a reverse lookup of the ImageID to list set of available
// RepoTags corresponding to the ImageID in question
func ImageTags(n nodes.Node, imageID string) (map[string]bool, error) {
var out bytes.Buffer
tags := make(map[string]bool, 0)
if err := n.Command("crictl", "inspecti", imageID).SetStdout(&out).Run(); err != nil {
return tags, err
}
crictlOut := struct {
Status struct {
RepoTags []string `json:"repoTags"`
} `json:"status"`
}{}
if err := json.Unmarshal(out.Bytes(), &crictlOut); err != nil {
return tags, err
}
for _, tag := range crictlOut.Status.RepoTags {
tags[tag] = true
}
return tags, nil
}
// ReTagImage is used to tag an ImageID with a custom tag specified by imageName parameter
func ReTagImage(n nodes.Node, imageID, imageName string) error {
var out bytes.Buffer
return n.Command("ctr", "--namespace=k8s.io", "images", "tag", "--force", imageID, imageName).SetStdout(&out).Run()
}

View File

@ -29,15 +29,19 @@ import (
// Version returns the kind CLI Semantic Version
func Version() string {
v := VersionCore
v := versionCore
// add pre-release version info if we have it
if VersionPreRelease != "" {
v += "-" + VersionPreRelease
if versionPreRelease != "" {
v += "-" + versionPreRelease
// If gitCommitCount was set, add to the pre-release version
if gitCommitCount != "" {
v += "." + gitCommitCount
}
// if commit was set, add the + <build>
// we only do this for pre-release versions
if GitCommit != "" {
if gitCommit != "" {
// NOTE: use 14 character short hash, like Kubernetes
v += "+" + truncate(GitCommit, 14)
v += "+" + truncate(gitCommit, 14)
}
}
return v
@ -49,16 +53,20 @@ func DisplayVersion() string {
return "kind v" + Version() + " " + runtime.Version() + " " + runtime.GOOS + "/" + runtime.GOARCH
}
// VersionCore is the core portion of the kind CLI version per Semantic Versioning 2.0.0
const VersionCore = "0.14.0"
// versionCore is the core portion of the kind CLI version per Semantic Versioning 2.0.0
const versionCore = "0.15.0"
// VersionPreRelease is the pre-release portion of the kind CLI version per
// versionPreRelease is the base pre-release portion of the kind CLI version per
// Semantic Versioning 2.0.0
const VersionPreRelease = ""
const versionPreRelease = ""
// GitCommit is the commit used to build the kind binary, if available.
// gitCommitCount count the commits since the last release.
// It is injected at build time.
var GitCommit = ""
var gitCommitCount = ""
// gitCommit is the commit used to build the kind binary, if available.
// It is injected at build time.
var gitCommit = ""
// NewCommand returns a new cobra.Command for version
func NewCommand(logger log.Logger, streams cmd.IOStreams) *cobra.Command {

View File

@ -194,11 +194,13 @@ type PatchJSON6902 struct {
// names on disk as opposed to the int32 values, and the serialized field names
// have been made closer to core/v1 VolumeMount field names
// In yaml this looks like:
// containerPath: /foo
// hostPath: /bar
// readOnly: true
// selinuxRelabel: false
// propagation: None
//
// containerPath: /foo
// hostPath: /bar
// readOnly: true
// selinuxRelabel: false
// propagation: None
//
// Propagation may be one of: None, HostToContainer, Bidirectional
type Mount struct {
// Path of the mount within the container.
@ -217,10 +219,11 @@ type Mount struct {
// PortMapping specifies a host port mapped into a container port.
// In yaml this looks like:
// containerPort: 80
// hostPort: 8000
// listenAddress: 127.0.0.1
// protocol: TCP
//
// containerPort: 80
// hostPort: 8000
// listenAddress: 127.0.0.1
// protocol: TCP
type PortMapping struct {
// Port within the container.
ContainerPort int32