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 }