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 }