github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/manager/resources/service/manager.go (about)

     1  /*
     2   * Copyright contributors to the Hyperledger Fabric Operator project
     3   *
     4   * SPDX-License-Identifier: Apache-2.0
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at:
     9   *
    10   * 	  http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  package service
    20  
    21  import (
    22  	"context"
    23  	"fmt"
    24  
    25  	k8sclient "github.com/IBM-Blockchain/fabric-operator/pkg/k8s/controllerclient"
    26  	"github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources"
    27  	"github.com/IBM-Blockchain/fabric-operator/pkg/operatorerrors"
    28  	"github.com/IBM-Blockchain/fabric-operator/pkg/util"
    29  	corev1 "k8s.io/api/core/v1"
    30  	k8serrors "k8s.io/apimachinery/pkg/api/errors"
    31  	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    32  	"k8s.io/apimachinery/pkg/runtime"
    33  	"k8s.io/apimachinery/pkg/types"
    34  	"sigs.k8s.io/controller-runtime/pkg/client"
    35  	logf "sigs.k8s.io/controller-runtime/pkg/log"
    36  )
    37  
    38  var log = logf.Log.WithName("service_manager")
    39  
    40  type Manager struct {
    41  	Client      k8sclient.Client
    42  	Scheme      *runtime.Scheme
    43  	ServiceFile string
    44  	Name        string
    45  	CustomName  string
    46  
    47  	LabelsFunc   func(v1.Object) map[string]string
    48  	OverrideFunc func(v1.Object, *corev1.Service, resources.Action) error
    49  }
    50  
    51  func (m *Manager) GetName(instance v1.Object) string {
    52  	if m.CustomName != "" {
    53  		return m.CustomName
    54  	}
    55  	return GetName(instance.GetName(), m.Name)
    56  }
    57  
    58  func (m *Manager) Reconcile(instance v1.Object, update bool) error {
    59  	name := m.GetName(instance)
    60  
    61  	err := m.Client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: instance.GetNamespace()}, &corev1.Service{})
    62  	if err != nil {
    63  		if k8serrors.IsNotFound(err) {
    64  			log.Info(fmt.Sprintf("Creating service '%s'", name))
    65  			service, err := m.GetServiceBasedOnCRFromFile(instance)
    66  			if err != nil {
    67  				return err
    68  			}
    69  
    70  			err = m.Client.Create(context.TODO(), service, k8sclient.CreateOption{Owner: instance, Scheme: m.Scheme})
    71  			if err != nil {
    72  				return err
    73  			}
    74  			return nil
    75  		}
    76  		return err
    77  	}
    78  
    79  	// TODO: If needed, update logic for servie goes here
    80  
    81  	return nil
    82  }
    83  
    84  func (m *Manager) GetServiceBasedOnCRFromFile(instance v1.Object) (*corev1.Service, error) {
    85  	service, err := util.GetServiceFromFile(m.ServiceFile)
    86  	if err != nil {
    87  		log.Error(err, fmt.Sprintf("Error reading service configuration file: %s", m.ServiceFile))
    88  		return nil, err
    89  	}
    90  
    91  	service.Name = m.GetName(instance)
    92  	service.Namespace = instance.GetNamespace()
    93  	service.Labels = m.LabelsFunc(instance)
    94  	service.Spec.Selector = m.getSelectorLabels(instance)
    95  
    96  	return m.BasedOnCR(instance, service)
    97  }
    98  
    99  func (m *Manager) BasedOnCR(instance v1.Object, service *corev1.Service) (*corev1.Service, error) {
   100  	if m.OverrideFunc != nil {
   101  		err := m.OverrideFunc(instance, service, resources.Create)
   102  		if err != nil {
   103  			return nil, operatorerrors.New(operatorerrors.InvalidServiceCreateRequest, err.Error())
   104  		}
   105  	}
   106  
   107  	return service, nil
   108  }
   109  
   110  func (m *Manager) getSelectorLabels(instance v1.Object) map[string]string {
   111  	labels := m.LabelsFunc(instance)
   112  	return labels
   113  }
   114  
   115  func (m *Manager) Get(instance v1.Object) (client.Object, error) {
   116  	if instance == nil {
   117  		return nil, nil // Instance has not been reconciled yet
   118  	}
   119  
   120  	name := m.GetName(instance)
   121  	service := &corev1.Service{}
   122  	err := m.Client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: instance.GetNamespace()}, service)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	return service, nil
   128  }
   129  
   130  func (m *Manager) Exists(instance v1.Object) bool {
   131  	_, err := m.Get(instance)
   132  	if err != nil {
   133  		return false
   134  	}
   135  
   136  	return true
   137  }
   138  
   139  func (m *Manager) Delete(instance v1.Object) error {
   140  	service, err := m.Get(instance)
   141  	if err != nil {
   142  		if !k8serrors.IsNotFound(err) {
   143  			return err
   144  		}
   145  	}
   146  
   147  	if service == nil {
   148  		return nil
   149  	}
   150  
   151  	err = m.Client.Delete(context.TODO(), service)
   152  	if err != nil {
   153  		if !k8serrors.IsNotFound(err) {
   154  			return err
   155  		}
   156  	}
   157  
   158  	return nil
   159  }
   160  
   161  func (m *Manager) CheckState(instance v1.Object) error {
   162  	// NO-OP
   163  	return nil
   164  }
   165  
   166  func (m *Manager) RestoreState(instance v1.Object) error {
   167  	// NO-OP
   168  	return nil
   169  }
   170  
   171  func (m *Manager) SetCustomName(name string) {
   172  	m.CustomName = name
   173  }
   174  
   175  func GetName(instanceName string, suffix ...string) string {
   176  	if len(suffix) != 0 {
   177  		if suffix[0] != "" {
   178  			return fmt.Sprintf("%s%s", instanceName, suffix[0])
   179  		}
   180  	}
   181  	return fmt.Sprintf("%s", instanceName)
   182  }