github.com/openshift/installer@v1.4.17/pkg/agent/ocp.go (about)

     1  package agent
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/pkg/errors"
     7  	"github.com/sirupsen/logrus"
     8  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
     9  	"k8s.io/client-go/rest"
    10  	"k8s.io/client-go/tools/clientcmd"
    11  
    12  	configv1 "github.com/openshift/api/config/v1"
    13  	configclient "github.com/openshift/client-go/config/clientset/versioned"
    14  	routeclient "github.com/openshift/client-go/route/clientset/versioned"
    15  	cov1helpers "github.com/openshift/library-go/pkg/config/clusteroperator/v1helpers"
    16  	"github.com/openshift/library-go/pkg/route/routeapihelpers"
    17  )
    18  
    19  // ClusterOpenShiftAPIClient Kube client using the OpenShift clientset instead of the Kubernetes clientset
    20  type ClusterOpenShiftAPIClient struct {
    21  	ConfigClient *configclient.Clientset
    22  	RouteClient  *routeclient.Clientset
    23  	ctx          context.Context
    24  	config       *rest.Config
    25  	configPath   string
    26  	cvResVersion string
    27  }
    28  
    29  const (
    30  	// Need to keep these updated if they change
    31  	consoleNamespace = "openshift-console"
    32  	consoleRouteName = "console"
    33  )
    34  
    35  // NewClusterOpenShiftAPIClient Create a kube client with OCP understanding
    36  func NewClusterOpenShiftAPIClient(ctx context.Context, kubeconfigPath string) (*ClusterOpenShiftAPIClient, error) {
    37  	ocpClient := &ClusterOpenShiftAPIClient{}
    38  
    39  	var kubeconfig *rest.Config
    40  	var err error
    41  	if kubeconfigPath != "" {
    42  		kubeconfig, err = clientcmd.BuildConfigFromFlags("", kubeconfigPath)
    43  	} else {
    44  		kubeconfig, err = rest.InClusterConfig()
    45  	}
    46  	if err != nil {
    47  		return nil, errors.Wrap(err, "creating kubeconfig for ocp config client")
    48  	}
    49  
    50  	configClient, err := configclient.NewForConfig(kubeconfig)
    51  	if err != nil {
    52  		return nil, errors.Wrap(err, "creating an ocp config client")
    53  	}
    54  
    55  	routeClient, err := routeclient.NewForConfig(kubeconfig)
    56  	if err != nil {
    57  		return nil, errors.Wrap(err, "creating an ocp route client")
    58  	}
    59  
    60  	ocpClient.ConfigClient = configClient
    61  	ocpClient.RouteClient = routeClient
    62  	ocpClient.ctx = ctx
    63  	ocpClient.config = kubeconfig
    64  	ocpClient.configPath = kubeconfigPath
    65  
    66  	return ocpClient, nil
    67  }
    68  
    69  // AreClusterOperatorsInitialized Waits for all Openshift cluster operators to initialize
    70  func (ocp *ClusterOpenShiftAPIClient) AreClusterOperatorsInitialized() (bool, error) {
    71  
    72  	var lastError string
    73  	failing := configv1.ClusterStatusConditionType("Failing")
    74  
    75  	version, err := ocp.ConfigClient.ConfigV1().ClusterVersions().Get(ocp.ctx, "version", metav1.GetOptions{})
    76  	if err != nil {
    77  		return false, errors.Wrap(err, "Getting ClusterVersion object")
    78  	}
    79  
    80  	if cov1helpers.IsStatusConditionTrue(version.Status.Conditions, configv1.OperatorAvailable) &&
    81  		cov1helpers.IsStatusConditionFalse(version.Status.Conditions, failing) &&
    82  		cov1helpers.IsStatusConditionFalse(version.Status.Conditions, configv1.OperatorProgressing) {
    83  		return true, nil
    84  	}
    85  
    86  	if cov1helpers.IsStatusConditionTrue(version.Status.Conditions, failing) {
    87  		lastError = cov1helpers.FindStatusCondition(version.Status.Conditions, failing).Message
    88  	} else if cov1helpers.IsStatusConditionTrue(version.Status.Conditions, configv1.OperatorProgressing) {
    89  		lastError = cov1helpers.FindStatusCondition(version.Status.Conditions, configv1.OperatorProgressing).Message
    90  	}
    91  	if version.ResourceVersion != ocp.cvResVersion {
    92  		logrus.Debugf("Still waiting for the cluster to initialize: %s", lastError)
    93  		ocp.cvResVersion = version.ResourceVersion
    94  	}
    95  
    96  	return false, nil
    97  }
    98  
    99  // IsConsoleRouteAvailable Check if the OCP console route is created
   100  func (ocp *ClusterOpenShiftAPIClient) IsConsoleRouteAvailable() (bool, error) {
   101  	route, err := ocp.RouteClient.RouteV1().Routes(consoleNamespace).Get(ocp.ctx, consoleRouteName, metav1.GetOptions{})
   102  	if err == nil {
   103  		logrus.Debugf("Route found in openshift-console namespace: %s", consoleRouteName)
   104  		if _, _, err2 := routeapihelpers.IngressURI(route, ""); err2 == nil {
   105  			logrus.Debug("OpenShift console route is admitted")
   106  			return true, nil
   107  		} else if err2 != nil {
   108  			err = err2
   109  		}
   110  	}
   111  	return false, errors.Wrap(err, "Waiting for openshift-console route")
   112  }
   113  
   114  // IsConsoleRouteURLAvailable Check if the console route URL is available
   115  func (ocp *ClusterOpenShiftAPIClient) IsConsoleRouteURLAvailable() (bool, string, error) {
   116  	url := ""
   117  	route, err := ocp.RouteClient.RouteV1().Routes(consoleNamespace).Get(ocp.ctx, consoleRouteName, metav1.GetOptions{})
   118  	if err == nil {
   119  		if uri, _, err2 := routeapihelpers.IngressURI(route, ""); err2 == nil {
   120  			url = uri.String()
   121  		} else {
   122  			err = err2
   123  		}
   124  	}
   125  	if url == "" {
   126  		return false, url, errors.Wrap(err, "Waiting for openshift-console URL")
   127  	}
   128  	return true, url, nil
   129  }
   130  
   131  // LogClusterOperatorConditions Log OCP cluster operator conditions
   132  func (ocp *ClusterOpenShiftAPIClient) LogClusterOperatorConditions() error {
   133  
   134  	operators, err := ocp.ConfigClient.ConfigV1().ClusterOperators().List(ocp.ctx, metav1.ListOptions{})
   135  	if err != nil {
   136  		return errors.Wrap(err, "Listing ClusterOperator objects")
   137  	}
   138  
   139  	for _, operator := range operators.Items {
   140  		for _, condition := range operator.Status.Conditions {
   141  			if condition.Type == configv1.OperatorUpgradeable {
   142  				continue
   143  			} else if condition.Type == configv1.OperatorAvailable && condition.Status == configv1.ConditionTrue {
   144  				continue
   145  			} else if (condition.Type == configv1.OperatorDegraded || condition.Type == configv1.OperatorProgressing) && condition.Status == configv1.ConditionFalse {
   146  				continue
   147  			}
   148  			if condition.Type == configv1.OperatorDegraded {
   149  				logrus.Errorf("Cluster operator %s %s is %s with %s: %s", operator.ObjectMeta.Name, condition.Type, condition.Status, condition.Reason, condition.Message)
   150  			} else {
   151  				logrus.Infof("Cluster operator %s %s is %s with %s: %s", operator.ObjectMeta.Name, condition.Type, condition.Status, condition.Reason, condition.Message)
   152  			}
   153  		}
   154  	}
   155  
   156  	return nil
   157  }