github.com/Axway/agent-sdk@v1.1.101/pkg/agent/handler/managedapplication.go (about) 1 package handler 2 3 import ( 4 "context" 5 "fmt" 6 7 agentcache "github.com/Axway/agent-sdk/pkg/agent/cache" 8 apiv1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1" 9 management "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/management/v1alpha1" 10 defs "github.com/Axway/agent-sdk/pkg/apic/definitions" 11 prov "github.com/Axway/agent-sdk/pkg/apic/provisioning" 12 "github.com/Axway/agent-sdk/pkg/util" 13 "github.com/Axway/agent-sdk/pkg/watchmanager/proto" 14 ) 15 16 const ( 17 maFinalizer = "agent.managedapplication.provisioned" 18 ) 19 20 type managedAppProvision interface { 21 ApplicationRequestProvision(applicationRequest prov.ApplicationRequest) (status prov.RequestStatus) 22 ApplicationRequestDeprovision(applicationRequest prov.ApplicationRequest) (status prov.RequestStatus) 23 } 24 25 type managedApplication struct { 26 marketplaceHandler 27 prov managedAppProvision 28 cache agentcache.Manager 29 client client 30 } 31 32 // NewManagedApplicationHandler creates a Handler for Credentials 33 func NewManagedApplicationHandler(prov managedAppProvision, cache agentcache.Manager, client client) Handler { 34 return &managedApplication{ 35 prov: prov, 36 cache: cache, 37 client: client, 38 } 39 } 40 41 // Handle processes grpc events triggered for ManagedApplications 42 func (h *managedApplication) Handle(ctx context.Context, meta *proto.EventMeta, resource *apiv1.ResourceInstance) error { 43 action := GetActionFromContext(ctx) 44 if resource.Kind != management.ManagedApplicationGVK().Kind || h.prov == nil || h.shouldIgnoreSubResourceUpdate(action, meta) { 45 return nil 46 } 47 48 log := getLoggerFromContext(ctx).WithComponent("managedApplicationHandler") 49 ctx = setLoggerInContext(ctx, log) 50 51 app := &management.ManagedApplication{} 52 err := app.FromInstance(resource) 53 if err != nil { 54 log.WithError(err).Error("could not handle application request") 55 return nil 56 } 57 58 if ok := isStatusFound(app.Status); !ok { 59 log.Debug("could not handle application request as it did not have a status subresource") 60 return nil 61 } 62 63 ma := provManagedApp{ 64 managedAppName: app.Name, 65 teamName: h.getTeamName(ctx, app.Owner), 66 data: util.GetAgentDetails(app), 67 consumerOrgID: h.getConsumerOrgID(app), 68 id: app.Metadata.ID, 69 } 70 71 if ok := h.shouldProcessPending(app.Status, app.Metadata.State); ok { 72 log.Trace("processing resource in pending status") 73 return h.onPending(ctx, app, ma) 74 } 75 76 if ok := h.shouldProcessDeleting(app.Status, app.Metadata.State, app.Finalizers); ok { 77 log.Trace("processing resource in deleting state") 78 h.onDeleting(ctx, app, ma) 79 } 80 81 return nil 82 } 83 84 func (h *managedApplication) onPending(ctx context.Context, app *management.ManagedApplication, pma provManagedApp) error { 85 log := getLoggerFromContext(ctx) 86 status := h.prov.ApplicationRequestProvision(pma) 87 88 app.Status = prov.NewStatusReason(status) 89 90 details := util.MergeMapStringString(util.GetAgentDetailStrings(app), status.GetProperties()) 91 util.SetAgentDetails(app, util.MapStringStringToMapStringInterface(details)) 92 93 // add finalizer 94 ri, _ := app.AsInstance() 95 if app.Status.Level == prov.Success.String() { 96 // only add finalizer on success 97 h.client.UpdateResourceFinalizer(ri, maFinalizer, "", true) 98 } 99 100 app.SubResources = map[string]interface{}{ 101 defs.XAgentDetails: util.GetAgentDetails(app), 102 } 103 104 err := h.client.CreateSubResource(app.ResourceMeta, app.SubResources) 105 if err != nil { 106 log.WithError(err).Error("error creating subresources") 107 } 108 109 statusErr := h.client.CreateSubResource(app.ResourceMeta, map[string]interface{}{"status": app.Status}) 110 if statusErr != nil { 111 log.WithError(statusErr).Error("error creating status subresources") 112 return statusErr 113 } 114 115 return err 116 } 117 118 func (h *managedApplication) onDeleting(ctx context.Context, app *management.ManagedApplication, pma provManagedApp) { 119 log := getLoggerFromContext(ctx) 120 status := h.prov.ApplicationRequestDeprovision(pma) 121 122 if status.GetStatus() == prov.Success { 123 ri, _ := app.AsInstance() 124 h.client.UpdateResourceFinalizer(ri, maFinalizer, "", false) 125 } else { 126 err := fmt.Errorf(status.GetMessage()) 127 log.WithError(err).Error("request status was not Success, skipping") 128 h.onError(app, err) 129 h.client.CreateSubResource(app.ResourceMeta, app.SubResources) 130 } 131 } 132 133 // onError updates the managed app with an error status 134 func (h *managedApplication) onError(ar *management.ManagedApplication, err error) { 135 ps := prov.NewRequestStatusBuilder() 136 status := ps.SetMessage(err.Error()).Failed() 137 ar.Status = prov.NewStatusReason(status) 138 ar.SubResources = map[string]interface{}{ 139 "status": ar.Status, 140 } 141 } 142 143 func (h *managedApplication) getTeamName(_ context.Context, owner *apiv1.Owner) string { 144 teamName := "" 145 if owner != nil && owner.ID != "" { 146 team := h.cache.GetTeamByID(owner.ID) 147 if team != nil { 148 teamName = team.Name 149 } 150 } 151 return teamName 152 } 153 154 func (h *managedApplication) getConsumerOrgID(app *management.ManagedApplication) string { 155 consumerOrgID := "" 156 if app != nil && app.Marketplace.Resource.Owner != nil && app.Marketplace.Resource.Owner.Organization.ID != "" { 157 consumerOrgID = app.Marketplace.Resource.Owner.Organization.ID 158 } 159 return consumerOrgID 160 } 161 162 type provManagedApp struct { 163 managedAppName string 164 teamName string 165 consumerOrgID string 166 id string 167 data map[string]interface{} 168 } 169 170 // GetManagedApplicationName returns the name of the managed application 171 func (a provManagedApp) GetManagedApplicationName() string { 172 return a.managedAppName 173 } 174 175 // GetTeamName gets the owning team name for the managed application 176 func (a provManagedApp) GetID() string { 177 return a.id 178 } 179 180 // GetTeamName gets the owning team name for the managed application 181 func (a provManagedApp) GetTeamName() string { 182 return a.teamName 183 } 184 185 // GetApplicationDetailsValue returns a value found on the managed application 186 func (a provManagedApp) GetApplicationDetailsValue(key string) string { 187 if a.data == nil { 188 return "" 189 } 190 191 return util.ToString(a.data[key]) 192 } 193 194 // GetConsumerOrgID returns the ID of the consumer org for the managed application 195 func (a provManagedApp) GetConsumerOrgID() string { 196 return a.consumerOrgID 197 }