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

     1  package apic
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  
     7  	"github.com/Axway/agent-sdk/pkg/apic/provisioning"
     8  	"github.com/Axway/agent-sdk/pkg/config"
     9  	"github.com/Axway/agent-sdk/pkg/util/log"
    10  )
    11  
    12  const (
    13  	maxDescriptionLength = 350
    14  	strEllipsis          = "..."
    15  )
    16  
    17  var pathRe *regexp.Regexp
    18  
    19  func init() {
    20  	pathRe, _ = regexp.Compile("^/")
    21  }
    22  
    23  // ServiceBuilder - Interface to build the service body
    24  type ServiceBuilder interface {
    25  	SetID(ID string) ServiceBuilder
    26  	SetPrimaryKey(key string) ServiceBuilder
    27  	SetRequestDefinitionsAllowed(previouslyPublished bool) ServiceBuilder
    28  	SetTitle(title string) ServiceBuilder
    29  	SetAPIName(apiName string) ServiceBuilder
    30  	SetURL(url string) ServiceBuilder
    31  	SetStage(stage string) ServiceBuilder
    32  	SetStageDescriptor(stageDescriptor string) ServiceBuilder
    33  	SetStageDisplayName(stageName string) ServiceBuilder
    34  	SetDescription(description string) ServiceBuilder
    35  	SetVersion(version string) ServiceBuilder
    36  	SetAuthPolicy(authPolicy string) ServiceBuilder
    37  	SetAPISpec(spec []byte) ServiceBuilder
    38  	SetDocumentation(documentation []byte) ServiceBuilder
    39  	SetTags(tags map[string]interface{}) ServiceBuilder
    40  	SetImage(image string) ServiceBuilder
    41  	SetImageContentType(imageContentType string) ServiceBuilder
    42  	SetResourceType(resourceType string) ServiceBuilder
    43  	SetSubscriptionName(subscriptionName string) ServiceBuilder
    44  	SetAPIUpdateSeverity(apiUpdateSeverity string) ServiceBuilder
    45  	SetState(state string) ServiceBuilder
    46  	SetStatus(status string) ServiceBuilder
    47  	SetServiceAttribute(serviceAttribute map[string]string) ServiceBuilder
    48  	SetInstanceAttribute(instanceAttribute map[string]string) ServiceBuilder
    49  	SetRevisionAttribute(revisionAttribute map[string]string) ServiceBuilder
    50  	SetServiceEndpoints(endpoints []EndpointDefinition) ServiceBuilder
    51  	AddServiceEndpoint(protocol, host string, port int32, basePath string) ServiceBuilder
    52  	SetCredentialRequestDefinitions(credentialRequestDefNames []string) ServiceBuilder
    53  	AddCredentialRequestDefinition(credentialRequestDefName string) ServiceBuilder
    54  	SetAccessRequestDefinitionName(accessRequestDefName string, isUnique bool) ServiceBuilder
    55  	SetIgnoreSpecBasedCreds(ignore bool) ServiceBuilder
    56  
    57  	SetUnstructuredType(assetType string) ServiceBuilder
    58  	SetUnstructuredContentType(contentType string) ServiceBuilder
    59  	SetUnstructuredLabel(label string) ServiceBuilder
    60  	SetUnstructuredFilename(filename string) ServiceBuilder
    61  	SetTeamName(teamName string) ServiceBuilder
    62  	SetServiceAgentDetails(attr map[string]interface{}) ServiceBuilder
    63  	SetInstanceAgentDetails(attr map[string]interface{}) ServiceBuilder
    64  	SetRevisionAgentDetails(attr map[string]interface{}) ServiceBuilder
    65  
    66  	SetSourceDataplaneType(dataplaneType DataplaneType, isDesign bool) ServiceBuilder
    67  	SetReferenceServiceName(serviceName, envName string) ServiceBuilder
    68  	SetReferenceInstanceName(instanceName, envName string) ServiceBuilder
    69  
    70  	Build() (ServiceBody, error)
    71  }
    72  
    73  type serviceBodyBuilder struct {
    74  	err         error
    75  	serviceBody ServiceBody
    76  }
    77  
    78  // NewServiceBodyBuilder - Creates a new service body builder
    79  func NewServiceBodyBuilder() ServiceBuilder {
    80  	return &serviceBodyBuilder{
    81  		serviceBody: ServiceBody{
    82  			AuthPolicy:                Passthrough,
    83  			authPolicies:              make([]string, 0),
    84  			CreatedBy:                 config.AgentTypeName,
    85  			State:                     PublishedStatus,
    86  			Status:                    PublishedStatus,
    87  			scopes:                    make(map[string]string),
    88  			ServiceAttributes:         make(map[string]string),
    89  			RevisionAttributes:        make(map[string]string),
    90  			InstanceAttributes:        make(map[string]string),
    91  			StageDescriptor:           "Stage",
    92  			Endpoints:                 make([]EndpointDefinition, 0),
    93  			UnstructuredProps:         &UnstructuredProperties{},
    94  			credentialRequestPolicies: make([]string, 0),
    95  			ServiceAgentDetails:       make(map[string]interface{}),
    96  			InstanceAgentDetails:      make(map[string]interface{}),
    97  			RevisionAgentDetails:      make(map[string]interface{}),
    98  			requestDefinitionsAllowed: true,
    99  			logger:                    log.NewFieldLogger().WithPackage("sdk.apic").WithComponent("serviceBuilder"),
   100  		},
   101  	}
   102  }
   103  
   104  func (b *serviceBodyBuilder) SetID(ID string) ServiceBuilder {
   105  	b.serviceBody.RestAPIID = ID
   106  	return b
   107  }
   108  
   109  func (b *serviceBodyBuilder) SetPrimaryKey(key string) ServiceBuilder {
   110  	b.serviceBody.PrimaryKey = key
   111  	return b
   112  }
   113  
   114  func (b *serviceBodyBuilder) SetRequestDefinitionsAllowed(key bool) ServiceBuilder {
   115  	b.serviceBody.requestDefinitionsAllowed = key
   116  	return b
   117  }
   118  
   119  func (b *serviceBodyBuilder) SetTitle(title string) ServiceBuilder {
   120  	b.serviceBody.NameToPush = title
   121  	return b
   122  }
   123  
   124  func (b *serviceBodyBuilder) SetAPIName(apiName string) ServiceBuilder {
   125  	b.serviceBody.APIName = apiName
   126  	return b
   127  }
   128  
   129  func (b *serviceBodyBuilder) SetURL(url string) ServiceBuilder {
   130  	b.serviceBody.URL = url
   131  	return b
   132  }
   133  
   134  func (b *serviceBodyBuilder) SetStage(stage string) ServiceBuilder {
   135  	b.serviceBody.Stage = stage
   136  	return b
   137  }
   138  
   139  func (b *serviceBodyBuilder) SetStageDescriptor(stageDescriptor string) ServiceBuilder {
   140  	b.serviceBody.StageDescriptor = stageDescriptor
   141  	return b
   142  }
   143  
   144  func (b *serviceBodyBuilder) SetStageDisplayName(stageDisplayName string) ServiceBuilder {
   145  	b.serviceBody.StageDisplayName = stageDisplayName
   146  	return b
   147  }
   148  
   149  func (b *serviceBodyBuilder) SetDescription(description string) ServiceBuilder {
   150  	b.serviceBody.Description = description
   151  	if len(description) > maxDescriptionLength {
   152  		b.serviceBody.Description = description[0:maxDescriptionLength-len(strEllipsis)] + strEllipsis
   153  	}
   154  	return b
   155  }
   156  
   157  func (b *serviceBodyBuilder) SetVersion(version string) ServiceBuilder {
   158  	b.serviceBody.Version = version
   159  	return b
   160  }
   161  
   162  func (b *serviceBodyBuilder) SetAuthPolicy(authPolicy string) ServiceBuilder {
   163  	b.serviceBody.AuthPolicy = authPolicy
   164  	return b
   165  }
   166  
   167  func (b *serviceBodyBuilder) SetAPISpec(spec []byte) ServiceBuilder {
   168  	b.serviceBody.SpecDefinition = spec
   169  	return b
   170  }
   171  
   172  func (b *serviceBodyBuilder) SetDocumentation(documentation []byte) ServiceBuilder {
   173  	b.serviceBody.Documentation = documentation
   174  	return b
   175  }
   176  
   177  func (b *serviceBodyBuilder) SetTags(tags map[string]interface{}) ServiceBuilder {
   178  	b.serviceBody.Tags = tags
   179  	return b
   180  }
   181  
   182  func (b *serviceBodyBuilder) SetImage(image string) ServiceBuilder {
   183  	b.serviceBody.Image = image
   184  	return b
   185  }
   186  
   187  func (b *serviceBodyBuilder) SetImageContentType(imageContentType string) ServiceBuilder {
   188  	b.serviceBody.ImageContentType = imageContentType
   189  	return b
   190  }
   191  
   192  func (b *serviceBodyBuilder) SetResourceType(resourceType string) ServiceBuilder {
   193  	b.serviceBody.ResourceType = resourceType
   194  	return b
   195  }
   196  
   197  func (b *serviceBodyBuilder) SetResourceContentType(resourceContentType string) ServiceBuilder {
   198  	b.serviceBody.ResourceContentType = resourceContentType
   199  	return b
   200  }
   201  
   202  func (b *serviceBodyBuilder) SetSubscriptionName(subscriptionName string) ServiceBuilder {
   203  	b.serviceBody.SubscriptionName = subscriptionName
   204  	return b
   205  }
   206  
   207  func (b *serviceBodyBuilder) SetAPIUpdateSeverity(apiUpdateSeverity string) ServiceBuilder {
   208  	b.serviceBody.APIUpdateSeverity = apiUpdateSeverity
   209  	return b
   210  }
   211  
   212  func (b *serviceBodyBuilder) SetState(state string) ServiceBuilder {
   213  	b.serviceBody.State = state
   214  	return b
   215  }
   216  
   217  func (b *serviceBodyBuilder) SetStatus(status string) ServiceBuilder {
   218  	b.serviceBody.Status = status
   219  	return b
   220  }
   221  
   222  func (b *serviceBodyBuilder) SetServiceAttribute(attr map[string]string) ServiceBuilder {
   223  	b.serviceBody.ServiceAttributes = attr
   224  	return b
   225  }
   226  
   227  func (b *serviceBodyBuilder) SetInstanceAttribute(attr map[string]string) ServiceBuilder {
   228  	b.serviceBody.InstanceAttributes = attr
   229  	return b
   230  }
   231  
   232  func (b *serviceBodyBuilder) SetRevisionAttribute(attr map[string]string) ServiceBuilder {
   233  	b.serviceBody.RevisionAttributes = attr
   234  	return b
   235  }
   236  
   237  func (b *serviceBodyBuilder) SetServiceAgentDetails(attr map[string]interface{}) ServiceBuilder {
   238  	b.serviceBody.ServiceAgentDetails = attr
   239  	return b
   240  }
   241  
   242  func (b *serviceBodyBuilder) SetInstanceAgentDetails(attr map[string]interface{}) ServiceBuilder {
   243  	b.serviceBody.InstanceAgentDetails = attr
   244  	return b
   245  }
   246  
   247  func (b *serviceBodyBuilder) SetRevisionAgentDetails(attr map[string]interface{}) ServiceBuilder {
   248  	b.serviceBody.RevisionAgentDetails = attr
   249  	return b
   250  }
   251  
   252  func (b *serviceBodyBuilder) SetServiceEndpoints(endpoints []EndpointDefinition) ServiceBuilder {
   253  	b.serviceBody.Endpoints = endpoints
   254  	return b
   255  }
   256  
   257  func (b *serviceBodyBuilder) AddServiceEndpoint(protocol, host string, port int32, basePath string) ServiceBuilder {
   258  	ep := EndpointDefinition{
   259  		Host:     host,
   260  		Port:     port,
   261  		Protocol: protocol,
   262  		BasePath: basePath,
   263  	}
   264  	b.serviceBody.Endpoints = append(b.serviceBody.Endpoints, ep)
   265  	return b
   266  }
   267  
   268  func (b *serviceBodyBuilder) SetUnstructuredType(assetType string) ServiceBuilder {
   269  	b.serviceBody.UnstructuredProps.AssetType = assetType
   270  	return b
   271  }
   272  
   273  func (b *serviceBodyBuilder) SetUnstructuredContentType(contentType string) ServiceBuilder {
   274  	b.serviceBody.UnstructuredProps.ContentType = contentType
   275  	return b
   276  }
   277  
   278  func (b *serviceBodyBuilder) SetUnstructuredLabel(label string) ServiceBuilder {
   279  	b.serviceBody.UnstructuredProps.Label = label
   280  	return b
   281  }
   282  
   283  func (b *serviceBodyBuilder) SetUnstructuredFilename(filename string) ServiceBuilder {
   284  	b.serviceBody.UnstructuredProps.Filename = filename
   285  	return b
   286  }
   287  
   288  func (b *serviceBodyBuilder) SetTeamName(teamName string) ServiceBuilder {
   289  	b.serviceBody.TeamName = teamName
   290  	return b
   291  }
   292  
   293  func (b *serviceBodyBuilder) Build() (ServiceBody, error) {
   294  	if b.err != nil {
   295  		return b.serviceBody, b.err
   296  	}
   297  
   298  	specParser := NewSpecResourceParser(b.serviceBody.SpecDefinition, b.serviceBody.ResourceType)
   299  	err := specParser.Parse()
   300  	if err != nil {
   301  		return b.serviceBody, fmt.Errorf("failed to parse service specification for '%s': %s", b.serviceBody.APIName, err)
   302  	}
   303  	specProcessor := specParser.GetSpecProcessor()
   304  	if b.serviceBody.ResourceContentType == "" {
   305  		b.serviceBody.ResourceContentType = specParser.getResourceContentType()
   306  	}
   307  	b.serviceBody.ResourceType = specProcessor.GetResourceType()
   308  	b.serviceBody.specHash = fmt.Sprintf("%v", specParser.specHash)
   309  	b.serviceBody.specVersion = specProcessor.GetVersion()
   310  	if b.serviceBody.specVersion == "" {
   311  		b.serviceBody.specVersion = b.serviceBody.Version
   312  	}
   313  
   314  	// Check if the type is unstructured to gather more info
   315  
   316  	if len(b.serviceBody.Endpoints) == 0 {
   317  		endPoints, err := specProcessor.GetEndpoints()
   318  		if err != nil {
   319  			return b.serviceBody, fmt.Errorf("failed to create endpoints for '%s': %s", b.serviceBody.APIName, err)
   320  		}
   321  		b.serviceBody.Endpoints = endPoints
   322  	}
   323  
   324  	// check all endpoints paths are valid
   325  	for _, ep := range b.serviceBody.Endpoints {
   326  		if ep.BasePath != "" && !pathRe.MatchString(ep.BasePath) {
   327  			return b.serviceBody, fmt.Errorf("path did not validate against '^/' for '%s'", ep.BasePath)
   328  		}
   329  	}
   330  
   331  	if b.serviceBody.dataplaneType == "" {
   332  		b.serviceBody.dataplaneType = "Unidentified"
   333  	}
   334  
   335  	var i interface{} = specProcessor
   336  	val, ok := i.(OasSpecProcessor)
   337  	if !ok {
   338  		return b.serviceBody, nil
   339  	}
   340  
   341  	val.ParseAuthInfo()
   342  
   343  	// get the auth policy from the spec
   344  	b.serviceBody.authPolicies = val.GetAuthPolicies()
   345  
   346  	// use the first auth policy in the list as the AuthPolicy for determining if subscriptions are enabled
   347  	if len(b.serviceBody.authPolicies) > 0 {
   348  		b.serviceBody.AuthPolicy = b.serviceBody.authPolicies[0]
   349  	}
   350  
   351  	// get the apikey info
   352  	b.serviceBody.apiKeyInfo = val.GetAPIKeyInfo()
   353  
   354  	// get oauth scopes
   355  	b.serviceBody.scopes = val.GetOAuthScopes()
   356  
   357  	// if the spec has multiple then use the oauth ard
   358  	err = b.serviceBody.createAccessRequestDefinition()
   359  	if err != nil {
   360  		return b.serviceBody, err
   361  	}
   362  
   363  	// only set ard name based on spec if not already set, use first auth we find
   364  	if b.serviceBody.ardName != "" {
   365  		return b.serviceBody, nil
   366  	}
   367  
   368  	if b.serviceBody.ignoreSpecBasesCreds {
   369  		return b.serviceBody, nil
   370  	}
   371  
   372  	for _, p := range b.serviceBody.authPolicies {
   373  		if p == Basic {
   374  			b.serviceBody.ardName = provisioning.BasicAuthARD
   375  			break
   376  		}
   377  		if p == Apikey {
   378  			b.serviceBody.ardName = provisioning.APIKeyARD
   379  			break
   380  		}
   381  	}
   382  
   383  	return b.serviceBody, nil
   384  }
   385  
   386  // SetCredentialRequestDefinitions -
   387  func (b *serviceBodyBuilder) SetCredentialRequestDefinitions(credentialRequestDefNames []string) ServiceBuilder {
   388  	b.serviceBody.credentialRequestPolicies = credentialRequestDefNames
   389  	return b
   390  }
   391  
   392  // AddCredentialRequestDefinition -
   393  func (b *serviceBodyBuilder) AddCredentialRequestDefinition(credentialRequestDefName string) ServiceBuilder {
   394  	b.serviceBody.credentialRequestPolicies = append(b.serviceBody.credentialRequestPolicies, credentialRequestDefName)
   395  	return b
   396  }
   397  
   398  // SetAccessRequestDefinitionName -
   399  func (b *serviceBodyBuilder) SetAccessRequestDefinitionName(accessRequestDefName string, isUnique bool) ServiceBuilder {
   400  	b.serviceBody.ardName = accessRequestDefName
   401  	b.serviceBody.uniqueARD = isUnique
   402  	return b
   403  }
   404  
   405  func (b *serviceBodyBuilder) SetIgnoreSpecBasedCreds(ignore bool) ServiceBuilder {
   406  	b.serviceBody.ignoreSpecBasesCreds = ignore
   407  	return b
   408  }
   409  
   410  func (b *serviceBodyBuilder) SetSourceDataplaneType(dataplaneType DataplaneType, isDesign bool) ServiceBuilder {
   411  	b.serviceBody.dataplaneType = dataplaneType
   412  	b.serviceBody.isDesignDataplane = isDesign
   413  	return b
   414  }
   415  
   416  func (b *serviceBodyBuilder) SetReferenceServiceName(serviceName, envName string) ServiceBuilder {
   417  	if envName != "" {
   418  		b.serviceBody.referencedServiceName = fmt.Sprintf("%s/%s", envName, serviceName)
   419  	} else {
   420  		b.serviceBody.referencedServiceName = serviceName
   421  	}
   422  
   423  	return b
   424  }
   425  
   426  func (b *serviceBodyBuilder) SetReferenceInstanceName(instanceName, envName string) ServiceBuilder {
   427  	if envName != "" {
   428  		b.serviceBody.referencedInstanceName = fmt.Sprintf("%s/%s", envName, instanceName)
   429  	} else {
   430  		b.serviceBody.referencedInstanceName = instanceName
   431  	}
   432  	return b
   433  }