...

Source file src/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/init_dryrun.go

Documentation: k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package apiclient
    18  
    19  import (
    20  	"github.com/pkg/errors"
    21  
    22  	v1 "k8s.io/api/core/v1"
    23  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/apimachinery/pkg/runtime"
    26  	"k8s.io/apimachinery/pkg/util/intstr"
    27  	core "k8s.io/client-go/testing"
    28  	netutils "k8s.io/utils/net"
    29  
    30  	"k8s.io/kubernetes/cmd/kubeadm/app/constants"
    31  )
    32  
    33  // InitDryRunGetter implements the DryRunGetter interface and can be used to GET/LIST values in the dryrun fake clientset
    34  // Need to handle these routes in a special manner:
    35  // - GET /default/services/kubernetes -- must return a valid Service
    36  // - GET /clusterrolebindings/system:nodes -- can safely return a NotFound error
    37  // - GET /nodes/<node-name> -- must return a valid Node
    38  // - ...all other, unknown GETs/LISTs will be logged
    39  type InitDryRunGetter struct {
    40  	controlPlaneName string
    41  	serviceSubnet    string
    42  }
    43  
    44  // InitDryRunGetter should implement the DryRunGetter interface
    45  var _ DryRunGetter = &InitDryRunGetter{}
    46  
    47  // NewInitDryRunGetter creates a new instance of the InitDryRunGetter struct
    48  func NewInitDryRunGetter(controlPlaneName string, serviceSubnet string) *InitDryRunGetter {
    49  	return &InitDryRunGetter{
    50  		controlPlaneName: controlPlaneName,
    51  		serviceSubnet:    serviceSubnet,
    52  	}
    53  }
    54  
    55  // HandleGetAction handles GET actions to the dryrun clientset this interface supports
    56  func (idr *InitDryRunGetter) HandleGetAction(action core.GetAction) (bool, runtime.Object, error) {
    57  	funcs := []func(core.GetAction) (bool, runtime.Object, error){
    58  		idr.handleKubernetesService,
    59  		idr.handleGetNode,
    60  		idr.handleSystemNodesClusterRoleBinding,
    61  	}
    62  	for _, f := range funcs {
    63  		handled, obj, err := f(action)
    64  		if handled {
    65  			return handled, obj, err
    66  		}
    67  	}
    68  
    69  	return false, nil, nil
    70  }
    71  
    72  // HandleListAction handles GET actions to the dryrun clientset this interface supports.
    73  // Currently there are no known LIST calls during kubeadm init this code has to take care of.
    74  func (idr *InitDryRunGetter) HandleListAction(action core.ListAction) (bool, runtime.Object, error) {
    75  	return false, nil, nil
    76  }
    77  
    78  // handleKubernetesService returns a faked Kubernetes service in order to be able to continue running kubeadm init.
    79  // The CoreDNS addon code GETs the Kubernetes service in order to extract the service subnet
    80  func (idr *InitDryRunGetter) handleKubernetesService(action core.GetAction) (bool, runtime.Object, error) {
    81  	if action.GetName() != "kubernetes" || action.GetNamespace() != metav1.NamespaceDefault || action.GetResource().Resource != "services" {
    82  		// We can't handle this event
    83  		return false, nil, nil
    84  	}
    85  
    86  	_, svcSubnet, err := netutils.ParseCIDRSloppy(idr.serviceSubnet)
    87  	if err != nil {
    88  		return true, nil, errors.Wrapf(err, "error parsing CIDR %q", idr.serviceSubnet)
    89  	}
    90  
    91  	internalAPIServerVirtualIP, err := netutils.GetIndexedIP(svcSubnet, 1)
    92  	if err != nil {
    93  		return true, nil, errors.Wrapf(err, "unable to get first IP address from the given CIDR (%s)", svcSubnet.String())
    94  	}
    95  
    96  	// The only used field of this Service object is the ClusterIP, which CoreDNS uses to calculate its own IP
    97  	return true, &v1.Service{
    98  		ObjectMeta: metav1.ObjectMeta{
    99  			Name:      "kubernetes",
   100  			Namespace: metav1.NamespaceDefault,
   101  			Labels: map[string]string{
   102  				"component": "apiserver",
   103  				"provider":  "kubernetes",
   104  			},
   105  		},
   106  		Spec: v1.ServiceSpec{
   107  			ClusterIP: internalAPIServerVirtualIP.String(),
   108  			Ports: []v1.ServicePort{
   109  				{
   110  					Name:       "https",
   111  					Port:       443,
   112  					TargetPort: intstr.FromInt32(6443),
   113  				},
   114  			},
   115  		},
   116  	}, nil
   117  }
   118  
   119  // handleGetNode returns a fake node object for the purpose of moving kubeadm init forwards.
   120  func (idr *InitDryRunGetter) handleGetNode(action core.GetAction) (bool, runtime.Object, error) {
   121  	if action.GetName() != idr.controlPlaneName || action.GetResource().Resource != "nodes" {
   122  		// We can't handle this event
   123  		return false, nil, nil
   124  	}
   125  
   126  	return true, &v1.Node{
   127  		ObjectMeta: metav1.ObjectMeta{
   128  			Name: idr.controlPlaneName,
   129  			Labels: map[string]string{
   130  				"kubernetes.io/hostname": idr.controlPlaneName,
   131  			},
   132  			Annotations: map[string]string{},
   133  		},
   134  	}, nil
   135  }
   136  
   137  // handleSystemNodesClusterRoleBinding handles the GET call to the system:nodes clusterrolebinding
   138  func (idr *InitDryRunGetter) handleSystemNodesClusterRoleBinding(action core.GetAction) (bool, runtime.Object, error) {
   139  	if action.GetName() != constants.NodesClusterRoleBinding || action.GetResource().Resource != "clusterrolebindings" {
   140  		// We can't handle this event
   141  		return false, nil, nil
   142  	}
   143  	// We can safely return a NotFound error here as the code will just proceed normally and don't care about modifying this clusterrolebinding
   144  	// This can only happen on an upgrade; and in that case the ClientBackedDryRunGetter impl will be used
   145  	return true, nil, apierrors.NewNotFound(action.GetResource().GroupResource(), "clusterrolebinding not found")
   146  }
   147  

View as plain text