github.com/Axway/agent-sdk@v1.1.101/pkg/agent/instancevalidator.go (about)

     1  package agent
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	"github.com/Axway/agent-sdk/pkg/util"
     8  
     9  	defs "github.com/Axway/agent-sdk/pkg/apic/definitions"
    10  
    11  	apiV1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1"
    12  	"github.com/Axway/agent-sdk/pkg/jobs"
    13  	utilErrors "github.com/Axway/agent-sdk/pkg/util/errors"
    14  	hc "github.com/Axway/agent-sdk/pkg/util/healthcheck"
    15  	"github.com/Axway/agent-sdk/pkg/util/log"
    16  )
    17  
    18  type instanceValidator struct {
    19  	jobs.Job
    20  	logger    log.FieldLogger
    21  	cacheLock *sync.Mutex
    22  }
    23  
    24  func newInstanceValidator() *instanceValidator {
    25  	return &instanceValidator{
    26  		logger:    logger.WithComponent("instanceValidator"),
    27  		cacheLock: &sync.Mutex{},
    28  	}
    29  }
    30  
    31  // Ready -
    32  func (j *instanceValidator) Ready() bool {
    33  	status, _ := hc.GetGlobalStatus()
    34  	return status == string(hc.OK)
    35  }
    36  
    37  // Status -
    38  func (j *instanceValidator) Status() error {
    39  	j.logger.Trace("status check")
    40  	if status, _ := hc.GetGlobalStatus(); status != string(hc.OK) {
    41  		err := fmt.Errorf("agent is marked as not running")
    42  		j.logger.WithError(err).Trace("status failed")
    43  		return err
    44  	}
    45  	return nil
    46  }
    47  
    48  // Execute -
    49  func (j *instanceValidator) Execute() error {
    50  	if getAPIValidator() != nil {
    51  		j.logger.Trace("executing")
    52  		PublishingLock()
    53  		defer PublishingUnlock()
    54  		j.validateAPIOnDataplane()
    55  	} else {
    56  		j.logger.Trace("no registered validator")
    57  	}
    58  
    59  	j.logger.Trace("finished executing")
    60  	return nil
    61  }
    62  
    63  func (j *instanceValidator) validateAPIOnDataplane() {
    64  	j.cacheLock.Lock()
    65  	defer j.cacheLock.Unlock()
    66  
    67  	logger := j.logger
    68  
    69  	logger.Trace("validating api service instances on dataplane")
    70  
    71  	// Validate the API on dataplane.
    72  	for _, key := range agent.cacheManager.GetAPIServiceInstanceKeys() {
    73  		logger := logger.WithField("instanceCacheID", key)
    74  		logger.Tracef("validating")
    75  
    76  		instance, err := agent.cacheManager.GetAPIServiceInstanceByID(key)
    77  		if err != nil {
    78  			logger.WithError(err).Trace("could not get instance from cache")
    79  			continue
    80  		}
    81  		logger = logger.WithField("name", instance.Name)
    82  
    83  		externalAPIID, _ := util.GetAgentDetailsValue(instance, defs.AttrExternalAPIID)
    84  		if externalAPIID == "" {
    85  			logger.Trace("could not get instance external id")
    86  			continue // skip service instances without external api id
    87  		} else if err != nil {
    88  			logger.WithError(err).Trace("could not get instance external id")
    89  		}
    90  		logger = logger.WithField("externalAPIID", externalAPIID)
    91  		externalAPIStage, _ := util.GetAgentDetailsValue(instance, defs.AttrExternalAPIStage)
    92  		if externalAPIStage != "" {
    93  			logger = logger.WithField("externalAPIStage", externalAPIStage)
    94  		}
    95  		externalPrimaryKey, _ := util.GetAgentDetailsValue(instance, defs.AttrExternalAPIPrimaryKey)
    96  		if externalPrimaryKey != "" {
    97  			logger = logger.WithField("externalPrimaryKey", externalPrimaryKey)
    98  		}
    99  
   100  		logger.Trace("validating API Instance on dataplane")
   101  		apiValidator := getAPIValidator()
   102  		if externalAPIID != "" && !apiValidator(externalAPIID, externalAPIStage) {
   103  			logger.Trace("removing API Instance no longer on dataplane")
   104  			j.deleteServiceInstance(logger, instance, externalPrimaryKey, externalAPIID)
   105  		}
   106  	}
   107  
   108  	j.validateServices()
   109  }
   110  
   111  func (j *instanceValidator) validateServices() {
   112  	logger.Trace("validating api services have at least one instance on dataplane")
   113  	for _, key := range agent.cacheManager.GetAPIServiceKeys() {
   114  		logger := logger.WithField("serviceCacheID", key)
   115  		logger.Tracef("validating")
   116  
   117  		service := agent.cacheManager.GetAPIServiceWithPrimaryKey(key)
   118  		if service == nil {
   119  			logger.Trace("service was no longer in the cache")
   120  			continue
   121  		}
   122  		logger = logger.WithField("name", service.Name)
   123  		instanceCount := agent.cacheManager.GetAPIServiceInstanceCount(service.Name)
   124  		logger = logger.WithField("instanceCount", instanceCount)
   125  
   126  		if agent.cacheManager.GetAPIServiceInstanceCount(service.Name) == 0 {
   127  			logger.Trace("service has no more instances")
   128  			j.deleteService(logger, service)
   129  		}
   130  	}
   131  }
   132  
   133  func (j *instanceValidator) deleteServiceInstance(logger log.FieldLogger, ri *apiV1.ResourceInstance, primaryKey, apiID string) {
   134  	// delete if it is an api service instance
   135  	logger = logger.WithField("instanceTitle", ri.Title)
   136  	logger.Infof("API no longer exists on the dataplane, deleting the API Service Instance")
   137  
   138  	err := agent.apicClient.DeleteAPIServiceInstance(ri.Name)
   139  	if err != nil {
   140  		logger.WithError(utilErrors.Wrap(ErrDeletingServiceInstanceItem, err.Error()).FormatError(ri.Title)).Error("deleting instance")
   141  		return
   142  	}
   143  	agent.cacheManager.DeleteAPIServiceInstance(ri.Metadata.ID)
   144  
   145  	logger.Debugf("Deleted API Service Instance item from Amplify Central")
   146  }
   147  
   148  func (j *instanceValidator) deleteService(logger log.FieldLogger, ri *apiV1.ResourceInstance) {
   149  	logger = logger.WithField("serviceTitle", ri.Title)
   150  	logger.Infof("API Service no longer has a service instance; deleting the API Service")
   151  
   152  	err := agent.apicClient.DeleteServiceByName(ri.Name)
   153  	if err != nil {
   154  		logger.WithError(utilErrors.Wrap(ErrDeletingService, err.Error()).FormatError(ri.Title)).Error("deleting service")
   155  		return
   156  	}
   157  	agent.cacheManager.DeleteAPIService(ri.Name)
   158  
   159  	logger.Debugf("Deleted API Service from Amplify Central")
   160  }