github.com/openshift/installer@v1.4.17/pkg/asset/manifests/ingress.go (about)

     1  package manifests
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"path/filepath"
     7  
     8  	"github.com/pkg/errors"
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  	"sigs.k8s.io/yaml"
    11  
    12  	configv1 "github.com/openshift/api/config/v1"
    13  	operatorv1 "github.com/openshift/api/operator/v1"
    14  	"github.com/openshift/installer/pkg/asset"
    15  	"github.com/openshift/installer/pkg/asset/installconfig"
    16  	"github.com/openshift/installer/pkg/types"
    17  	"github.com/openshift/installer/pkg/types/aws"
    18  )
    19  
    20  var (
    21  	clusterIngressConfigFile     = filepath.Join(manifestDir, "cluster-ingress-02-config.yml")
    22  	defaultIngressControllerFile = filepath.Join(manifestDir, "cluster-ingress-default-ingresscontroller.yaml")
    23  )
    24  
    25  // Ingress generates the cluster-ingress-*.yml files.
    26  type Ingress struct {
    27  	FileList []*asset.File
    28  }
    29  
    30  var _ asset.WritableAsset = (*Ingress)(nil)
    31  
    32  // Name returns a human friendly name for the asset.
    33  func (*Ingress) Name() string {
    34  	return "Ingress Config"
    35  }
    36  
    37  // Dependencies returns all of the dependencies directly needed to generate
    38  // the asset.
    39  func (*Ingress) Dependencies() []asset.Asset {
    40  	return []asset.Asset{
    41  		&installconfig.InstallConfig{},
    42  	}
    43  }
    44  
    45  // Generate generates the ingress cluster config and default ingresscontroller.
    46  //
    47  // A cluster ingress config is always created.
    48  //
    49  // A default ingresscontroller is only created if the cluster is using an internal
    50  // publishing strategy. In this case, the default ingresscontroller is also set
    51  // to use the internal publishing strategy.
    52  func (ing *Ingress) Generate(_ context.Context, dependencies asset.Parents) error {
    53  	installConfig := &installconfig.InstallConfig{}
    54  	dependencies.Get(installConfig)
    55  
    56  	ing.FileList = []*asset.File{}
    57  
    58  	clusterConfig, err := ing.generateClusterConfig(installConfig.Config)
    59  	if err != nil {
    60  		return errors.Wrap(err, "failed to create cluster config")
    61  	}
    62  	ing.FileList = append(ing.FileList, &asset.File{
    63  		Filename: clusterIngressConfigFile,
    64  		Data:     clusterConfig,
    65  	})
    66  
    67  	defaultIngressController, err := ing.generateDefaultIngressController(installConfig.Config)
    68  	if err != nil {
    69  		return errors.Wrap(err, "failed to create default ingresscontroller")
    70  	}
    71  	if len(defaultIngressController) > 0 {
    72  		ing.FileList = append(ing.FileList, &asset.File{
    73  			Filename: defaultIngressControllerFile,
    74  			Data:     defaultIngressController,
    75  		})
    76  	}
    77  
    78  	return nil
    79  }
    80  
    81  func (ing *Ingress) generateClusterConfig(config *types.InstallConfig) ([]byte, error) {
    82  	controlPlaneTopology, _ := determineTopologies(config)
    83  
    84  	isSingleControlPlaneNode := controlPlaneTopology == configv1.SingleReplicaTopologyMode
    85  
    86  	defaultPlacement := configv1.DefaultPlacementWorkers
    87  	if config.Platform.None != nil && isSingleControlPlaneNode {
    88  		// A none-platform single control-plane node cluster doesn't need a
    89  		// load balancer, the API and ingress traffic for such cluster can be
    90  		// directed at the single node directly. We want to maintain that even
    91  		// when worker nodes are added to such cluster. We do that by asking
    92  		// the Cluster Ingress Operator to place the ingress pod on the single
    93  		// control plane node. This would ensure that the ingress pod won't
    94  		// ever be scheduled on the added workers, as that would create a
    95  		// requirement for a load-balancer. Even when a single control-plane
    96  		// node cluster is installed with one or more worker nodes since day 1,
    97  		// we still want control-plane ingress default placement, for the sake
    98  		// of consistency. Users can override this decision manually if they
    99  		// wish.
   100  		defaultPlacement = configv1.DefaultPlacementControlPlane
   101  	}
   102  
   103  	obj := &configv1.Ingress{
   104  		TypeMeta: metav1.TypeMeta{
   105  			APIVersion: configv1.GroupVersion.String(),
   106  			Kind:       "Ingress",
   107  		},
   108  		ObjectMeta: metav1.ObjectMeta{
   109  			Name: "cluster",
   110  			// not namespaced
   111  		},
   112  		Spec: configv1.IngressSpec{
   113  			Domain: fmt.Sprintf("apps.%s", config.ClusterDomain()),
   114  		},
   115  		Status: configv1.IngressStatus{
   116  			DefaultPlacement: defaultPlacement,
   117  		},
   118  	}
   119  
   120  	switch config.Platform.Name() {
   121  	case aws.Name:
   122  		lbType := configv1.Classic
   123  		if config.AWS.LBType == configv1.NLB {
   124  			lbType = configv1.NLB
   125  		}
   126  		obj.Spec.LoadBalancer = configv1.LoadBalancer{
   127  			Platform: configv1.IngressPlatformSpec{
   128  				AWS: &configv1.AWSIngressSpec{
   129  					Type: lbType,
   130  				},
   131  				Type: configv1.AWSPlatformType,
   132  			},
   133  		}
   134  	}
   135  	return yaml.Marshal(obj)
   136  }
   137  
   138  func (ing *Ingress) generateDefaultIngressController(config *types.InstallConfig) ([]byte, error) {
   139  	switch config.Publish {
   140  	case types.MixedPublishingStrategy:
   141  		if config.OperatorPublishingStrategy.Ingress != "Internal" {
   142  			break
   143  		}
   144  		fallthrough
   145  	case types.InternalPublishingStrategy:
   146  		obj := &operatorv1.IngressController{
   147  			TypeMeta: metav1.TypeMeta{
   148  				APIVersion: operatorv1.GroupVersion.String(),
   149  				Kind:       "IngressController",
   150  			},
   151  			ObjectMeta: metav1.ObjectMeta{
   152  				Namespace: "openshift-ingress-operator",
   153  				Name:      "default",
   154  			},
   155  			Spec: operatorv1.IngressControllerSpec{
   156  				EndpointPublishingStrategy: &operatorv1.EndpointPublishingStrategy{
   157  					Type: operatorv1.LoadBalancerServiceStrategyType,
   158  					LoadBalancer: &operatorv1.LoadBalancerStrategy{
   159  						Scope: operatorv1.InternalLoadBalancer,
   160  					},
   161  				},
   162  			},
   163  		}
   164  		return yaml.Marshal(obj)
   165  	}
   166  	return nil, nil
   167  }
   168  
   169  // Files returns the files generated by the asset.
   170  func (ing *Ingress) Files() []*asset.File {
   171  	return ing.FileList
   172  }
   173  
   174  // Load returns false since this asset is not written to disk by the installer.
   175  func (ing *Ingress) Load(asset.FileFetcher) (bool, error) {
   176  	return false, nil
   177  }