Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

APIGOV-29633 - updates for application profile provisioning #887

Merged
merged 8 commits into from
Feb 11, 2025
7 changes: 7 additions & 0 deletions pkg/agent/discoverycache.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ func (dc *discoveryCache) buildMarketplaceFuncs(mpResources map[string]discoverF
marketplaceFuncs = append(marketplaceFuncs, mApps)
}

mAppProfs, ok := mpResources[management.ManagedApplicationProfileGVK().Kind]
if ok {
marketplaceFuncs = append(marketplaceFuncs, mAppProfs)
}

accessReq, ok := mpResources[management.AccessRequestGVK().Kind]
if ok {
marketplaceFuncs = append(marketplaceFuncs, accessReq)
Expand Down Expand Up @@ -280,6 +285,8 @@ func isMPResource(kind string) bool {
switch kind {
case management.ManagedApplicationGVK().Kind:
return true
case management.ManagedApplicationProfileGVK().Kind:
return true
case management.AccessRequestGVK().Kind:
return true
case management.CredentialGVK().Kind:
Expand Down
25 changes: 25 additions & 0 deletions pkg/agent/discoverycache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func TestDiscoveryCache_execute(t *testing.T) {
c := &mockRIClient{
svcs: newAPIServices(scopeName),
managedApps: newManagedApps(scopeName),
manAppProfs: newManaAppProfs(scopeName),
accessReqs: newAccessReqs(scopeName),
creds: newCredentials(scopeName),
}
Expand All @@ -79,6 +80,9 @@ func TestDiscoveryCache_execute(t *testing.T) {
managedAppHandler := &mockHandler{
kind: management.ManagedApplicationGVK().Kind,
}
managedAppProfHandler := &mockHandler{
kind: management.ManagedApplicationProfileGVK().Kind,
}
accessReqHandler := &mockHandler{
kind: management.AccessRequestGVK().Kind,
}
Expand All @@ -89,6 +93,7 @@ func TestDiscoveryCache_execute(t *testing.T) {
handlers := []handler.Handler{
svcHandler,
managedAppHandler,
managedAppProfHandler,
accessReqHandler,
credHandler,
}
Expand Down Expand Up @@ -158,6 +163,14 @@ func newManagedApps(scope string) []*apiv1.ResourceInstance {
}
}

func newManaAppProfs(scope string) []*apiv1.ResourceInstance {
map1, _ := management.NewManagedApplicationProfile("map1", scope).AsInstance()
map2, _ := management.NewManagedApplicationProfile("map2", scope).AsInstance()
return []*apiv1.ResourceInstance{
map1, map2,
}
}

func newAccessReqs(scope string) []*apiv1.ResourceInstance {
ar1, _ := management.NewAccessRequest("ar1", scope).AsInstance()
ar2, _ := management.NewAccessRequest("ar2", scope).AsInstance()
Expand All @@ -177,6 +190,7 @@ func newCredentials(scope string) []*apiv1.ResourceInstance {
type mockRIClient struct {
svcs []*apiv1.ResourceInstance
managedApps []*apiv1.ResourceInstance
manAppProfs []*apiv1.ResourceInstance
accessReqs []*apiv1.ResourceInstance
creds []*apiv1.ResourceInstance
err error
Expand All @@ -188,6 +202,8 @@ func (m mockRIClient) GetAPIV1ResourceInstances(_ map[string]string, URL string)
return m.svcs, m.err
} else if strings.Contains(URL, "managedapplications") {
return m.managedApps, m.err
} else if strings.Contains(URL, "managedapplicationprofiles") {
return m.manAppProfs, m.err
} else if strings.Contains(URL, "accessrequests") {
return m.accessReqs, m.err
} else if strings.Contains(URL, "credentials") {
Expand Down Expand Up @@ -232,6 +248,15 @@ var mpWatchTopic = &management.WatchTopic{
Name: envName,
},
},
{
Group: "management",
Kind: management.ManagedApplicationProfileGVK().Kind,
Name: "*",
Scope: &management.WatchTopicSpecScope{
Kind: "Environment",
Name: envName,
},
},
{
Group: "management",
Kind: management.AccessRequestGVK().Kind,
Expand Down
2 changes: 2 additions & 0 deletions pkg/agent/handler/accessrequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ func (h *accessRequestHandler) onPending(ctx context.Context, ar *management.Acc
return ar
}

updateDataFromEnumMap(ar.Spec.Data, ard.Spec.Schema)

data := map[string]interface{}{}
status, accessData := h.prov.AccessRequestProvision(req)

Expand Down
11 changes: 8 additions & 3 deletions pkg/agent/handler/accessrequest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,9 @@ func TestAccessRequestHandler(t *testing.T) {

c := &mockClient{
expectedStatus: tc.outboundStatus,
getErr: tc.getErr,
getManAppErr: tc.getErr,
getARDErr: tc.getARDErr,
getRI: mApp,
manApp: mApp,
subError: tc.subError,
t: t,
ard: ardRI,
Expand Down Expand Up @@ -246,7 +246,7 @@ func TestAccessRequestHandler_deleting(t *testing.T) {

c := &mockClient{
expectedStatus: tc.outboundStatus.String(),
getRI: mApp,
manApp: mApp,
isDeleting: true,
t: t,
}
Expand Down Expand Up @@ -329,6 +329,8 @@ type mockClient struct {
getARDErr error
getRI *v1.ResourceInstance
ard *v1.ResourceInstance
manApp *v1.ResourceInstance
getManAppErr error
isDeleting bool
subError error
t *testing.T
Expand All @@ -338,6 +340,9 @@ func (m *mockClient) GetResource(url string) (*v1.ResourceInstance, error) {
if strings.Contains(url, "/accessrequestdefinitions") {
return m.ard, m.getARDErr
}
if strings.Contains(url, "/managedapplication") {
return m.manApp, m.getManAppErr
}
return m.getRI, m.getErr
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/agent/handler/credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,8 @@ func (h *credentials) provisionPreProcess(ctx context.Context, cred *management.
return nil, nil, true
}

updateDataFromEnumMap(cred.Spec.Data, crd.Spec.Schema)

return app, crd, false
}

Expand Down
74 changes: 60 additions & 14 deletions pkg/agent/handler/managedapplicationprofile.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,29 @@ package handler

import (
"context"
"fmt"

apiv1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1"
v1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1"
management "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/management/v1alpha1"
defs "github.com/Axway/agent-sdk/pkg/apic/definitions"
prov "github.com/Axway/agent-sdk/pkg/apic/provisioning"
"github.com/Axway/agent-sdk/pkg/util"
"github.com/Axway/agent-sdk/pkg/util/log"
"github.com/Axway/agent-sdk/pkg/watchmanager/proto"
)

type getTeamByID interface {
GetTeamByID(id string) *defs.PlatformTeam
}

type getManagedAppByName interface {
GetManagedApplicationByName(name string) *apiv1.ResourceInstance
}

type managedApplicationProfileCache interface {
getTeamByID
getManagedAppByName
GetApplicationProfileDefinitionByName(name string) (*v1.ResourceInstance, error)
}

type managedApplicationProfile struct {
marketplaceHandler
logger log.FieldLogger
prov prov.ApplicationProfileProvisioner
cache managedApplicationProfileCache
client client
Expand All @@ -35,6 +33,7 @@ type managedApplicationProfile struct {
// NewManagedApplicationProfileHandler creates a Handler for Credentials
func NewManagedApplicationProfileHandler(prov prov.ApplicationProfileProvisioner, cache managedApplicationProfileCache, client client) Handler {
return &managedApplicationProfile{
logger: log.NewFieldLogger().WithComponent("managedApplicationProfile").WithPackage("agent.handler"),
prov: prov,
cache: cache,
client: client,
Expand Down Expand Up @@ -81,13 +80,15 @@ func (h *managedApplicationProfile) onPending(ctx context.Context, profile *mana
}
}()

app, err := getManagedApp(h.cache, profile.Spec.ManagedApplication)
app, err := h.getManagedApp(ctx, profile)
if err != nil {
log.WithError(err).Error("error getting managed app")
h.onError(ctx, profile, err)
return err
}

h.checkForEnumValueMap(ctx, profile.Spec.Data, profile.Spec.ApplicationProfileDefinition)

pma := provManagedAppProfile{
attributes: profile.Spec.Data,
profileDefinition: profile.Spec.ApplicationProfileDefinition,
Expand Down Expand Up @@ -117,6 +118,39 @@ func (h *managedApplicationProfile) onPending(ctx context.Context, profile *mana
return err
}

func (h *managedApplicationProfile) checkForEnumValueMap(_ context.Context, data map[string]interface{}, profileDef string) {
log := h.logger.WithField("applicationProfileDefinition", profileDef)

// get application profile definition
ri, err := h.cache.GetApplicationProfileDefinitionByName(profileDef)
if err != nil {
log.WithError(err).Error("error getting application profile definition from cache")
return
}
if ri == nil {
log.Debug("could not find application profile definition in cache")
return
}
appProfDef := management.ApplicationProfileDefinition{}
if err := appProfDef.FromInstance(ri); err != nil {
log.WithError(err).Error("error reading application profile definition from cache")
return
}

updateDataFromEnumMap(data, appProfDef.Spec.Schema)
}

func (h *managedApplicationProfile) getManagedApp(_ context.Context, profile *management.ManagedApplicationProfile) (*management.ManagedApplication, error) {
app := management.NewManagedApplication(profile.Spec.ManagedApplication, profile.Metadata.Scope.Name)
ri, err := h.client.GetResource(app.GetSelfLink())
if err != nil {
return nil, err
}

err = app.FromInstance(ri)
return app, err
}

// onError updates the managed app with an error status
func (h *managedApplicationProfile) onError(_ context.Context, profile *management.ManagedApplicationProfile, err error) {
ps := prov.NewRequestStatusBuilder()
Expand Down Expand Up @@ -176,12 +210,24 @@ func (a provManagedAppProfile) GetID() string {
return a.id
}

func getManagedApp(cache getManagedAppByName, name string) (*management.ManagedApplication, error) {
ri := cache.GetManagedApplicationByName(name)
if ri == nil {
return nil, fmt.Errorf("could not retrieved managed application")
func updateDataFromEnumMap(data map[string]interface{}, schema map[string]interface{}) {
enumPropMap := prov.GetEnumValueMapsFromSchema(schema)
if len(enumPropMap) == 0 {
return
}
for k, l := range data {
enumMap, ok := enumPropMap[k]
if !ok {
continue
}
label, ok := l.(string)
if !ok {
continue
}
value, ok := enumMap[label]
if !ok {
continue
}
data[k] = value
}
app := &management.ManagedApplication{}
err := app.FromInstance(ri)
return app, err
}
Loading