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