github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/manager/resources/serviceaccount/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 serviceaccount
    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("serviceaccount_manager")
    39  
    40  type Manager struct {
    41  	Client             k8sclient.Client
    42  	Scheme             *runtime.Scheme
    43  	ServiceAccountFile string
    44  	Name               string
    45  
    46  	LabelsFunc   func(v1.Object) map[string]string
    47  	OverrideFunc func(v1.Object, *corev1.ServiceAccount, resources.Action) error
    48  }
    49  
    50  func (m *Manager) GetName(instance v1.Object) string {
    51  	return GetName(instance.GetName(), m.Name)
    52  }
    53  
    54  func (m *Manager) Reconcile(instance v1.Object, update bool) error {
    55  	name := m.GetName(instance)
    56  	err := m.Client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: instance.GetNamespace()}, &corev1.ServiceAccount{})
    57  	if err != nil {
    58  		if k8serrors.IsNotFound(err) {
    59  			log.Info(fmt.Sprintf("Creating service account '%s'", name))
    60  			serviceAccount, err := m.GetServiceAccountBasedOnCRFromFile(instance)
    61  			if err != nil {
    62  				return err
    63  			}
    64  
    65  			err = m.Client.Create(context.TODO(), serviceAccount, k8sclient.CreateOption{Owner: instance, Scheme: m.Scheme})
    66  			if err != nil {
    67  				return err
    68  			}
    69  			return nil
    70  		}
    71  		return err
    72  	}
    73  
    74  	// TODO: If needed, update logic for servie goes here
    75  
    76  	return nil
    77  }
    78  
    79  func (m *Manager) GetServiceAccountBasedOnCRFromFile(instance v1.Object) (*corev1.ServiceAccount, error) {
    80  	serviceAccount, err := util.GetServiceAccountFromFile(m.ServiceAccountFile)
    81  	if err != nil {
    82  		log.Error(err, fmt.Sprintf("Error reading service account configuration file: %s", m.ServiceAccountFile))
    83  		return nil, err
    84  	}
    85  
    86  	name := m.GetName(instance)
    87  	serviceAccount.Name = name
    88  	serviceAccount.Namespace = instance.GetNamespace()
    89  	serviceAccount.Labels = m.LabelsFunc(instance)
    90  
    91  	return m.BasedOnCR(instance, serviceAccount)
    92  }
    93  
    94  func (m *Manager) BasedOnCR(instance v1.Object, serviceAccount *corev1.ServiceAccount) (*corev1.ServiceAccount, error) {
    95  	if m.OverrideFunc != nil {
    96  		err := m.OverrideFunc(instance, serviceAccount, resources.Create)
    97  		if err != nil {
    98  			return nil, operatorerrors.New(operatorerrors.InvalidServiceAccountCreateRequest, err.Error())
    99  		}
   100  	}
   101  
   102  	return serviceAccount, nil
   103  }
   104  
   105  func (m *Manager) Get(instance v1.Object) (client.Object, error) {
   106  	if instance == nil {
   107  		return nil, nil // Instance has not been reconciled yet
   108  	}
   109  
   110  	name := m.GetName(instance)
   111  	sa := &corev1.ServiceAccount{}
   112  	err := m.Client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: instance.GetNamespace()}, sa)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  
   117  	return sa, nil
   118  }
   119  
   120  func (m *Manager) Exists(instance v1.Object) bool {
   121  	_, err := m.Get(instance)
   122  	if err != nil {
   123  		return false
   124  	}
   125  
   126  	return true
   127  }
   128  
   129  func (m *Manager) Delete(instance v1.Object) error {
   130  	sa, err := m.Get(instance)
   131  	if err != nil {
   132  		if !k8serrors.IsNotFound(err) {
   133  			return err
   134  		}
   135  	}
   136  
   137  	if sa == nil {
   138  		return nil
   139  	}
   140  
   141  	err = m.Client.Delete(context.TODO(), sa)
   142  	if err != nil {
   143  		if !k8serrors.IsNotFound(err) {
   144  			return err
   145  		}
   146  	}
   147  
   148  	return nil
   149  }
   150  
   151  func (m *Manager) CheckState(instance v1.Object) error {
   152  	// NO-OP
   153  	return nil
   154  }
   155  
   156  func (m *Manager) RestoreState(instance v1.Object) error {
   157  	// NO-OP
   158  	return nil
   159  }
   160  
   161  func (m *Manager) SetCustomName(name string) {
   162  	// NO-OP
   163  }
   164  
   165  func GetName(instanceName string, suffix ...string) string {
   166  	if len(suffix) != 0 {
   167  		if suffix[0] != "" {
   168  			return fmt.Sprintf("%s-%s", instanceName, suffix[0])
   169  		}
   170  	}
   171  	return fmt.Sprintf("%s", instanceName)
   172  }