github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/manager/resources/role/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 role
    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  	rbacv1 "k8s.io/api/rbac/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("role_manager")
    39  
    40  type Manager struct {
    41  	Client   k8sclient.Client
    42  	Scheme   *runtime.Scheme
    43  	RoleFile string
    44  	Name     string
    45  
    46  	LabelsFunc   func(v1.Object) map[string]string
    47  	OverrideFunc func(v1.Object, *rbacv1.Role, 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()}, &rbacv1.Role{})
    57  	if err != nil {
    58  		if k8serrors.IsNotFound(err) {
    59  			log.Info(fmt.Sprintf("Creating role '%s'", name))
    60  			role, err := m.GetRoleBasedOnCRFromFile(instance)
    61  			if err != nil {
    62  				return err
    63  			}
    64  
    65  			err = m.Client.Create(context.TODO(), role, 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) GetRoleBasedOnCRFromFile(instance v1.Object) (*rbacv1.Role, error) {
    80  	role, err := util.GetRoleFromFile(m.RoleFile)
    81  	if err != nil {
    82  		log.Error(err, fmt.Sprintf("Error reading role configuration file: %s", m.RoleFile))
    83  		return nil, err
    84  	}
    85  
    86  	role.Name = m.GetName(instance)
    87  	role.Namespace = instance.GetNamespace()
    88  	role.Labels = m.LabelsFunc(instance)
    89  
    90  	return m.BasedOnCR(instance, role)
    91  }
    92  
    93  func (m *Manager) BasedOnCR(instance v1.Object, role *rbacv1.Role) (*rbacv1.Role, error) {
    94  	if m.OverrideFunc != nil {
    95  		err := m.OverrideFunc(instance, role, resources.Create)
    96  		if err != nil {
    97  			return nil, operatorerrors.New(operatorerrors.InvalidRoleCreateRequest, err.Error())
    98  		}
    99  	}
   100  
   101  	return role, nil
   102  }
   103  
   104  func (m *Manager) Get(instance v1.Object) (client.Object, error) {
   105  	if instance == nil {
   106  		return nil, nil // Instance has not been reconciled yet
   107  	}
   108  
   109  	name := m.GetName(instance)
   110  	role := &rbacv1.Role{}
   111  	err := m.Client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: instance.GetNamespace()}, role)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  
   116  	return role, nil
   117  }
   118  
   119  func (m *Manager) Exists(instance v1.Object) bool {
   120  	_, err := m.Get(instance)
   121  	if err != nil {
   122  		return false
   123  	}
   124  
   125  	return true
   126  }
   127  
   128  func (m *Manager) Delete(instance v1.Object) error {
   129  	role, err := m.Get(instance)
   130  	if err != nil {
   131  		if !k8serrors.IsNotFound(err) {
   132  			return err
   133  		}
   134  	}
   135  
   136  	if role == nil {
   137  		return nil
   138  	}
   139  
   140  	err = m.Client.Delete(context.TODO(), role)
   141  	if err != nil {
   142  		if !k8serrors.IsNotFound(err) {
   143  			return err
   144  		}
   145  	}
   146  
   147  	return nil
   148  }
   149  
   150  func (m *Manager) CheckState(instance v1.Object) error {
   151  	// NO-OP
   152  	return nil
   153  }
   154  
   155  func (m *Manager) RestoreState(instance v1.Object) error {
   156  	// NO-OP
   157  	return nil
   158  }
   159  
   160  func (m *Manager) SetCustomName(name string) {
   161  	// NO-OP
   162  }
   163  
   164  func GetName(instanceName string, suffix ...string) string {
   165  	if len(suffix) != 0 {
   166  		if suffix[0] != "" {
   167  			return fmt.Sprintf("%s-%s-role", instanceName, suffix[0])
   168  		}
   169  	}
   170  	return fmt.Sprintf("%s-role", instanceName)
   171  }