├── .github └── workflows │ ├── build-push.yml │ ├── copydocs.yml │ ├── dependency-graph.yml │ └── run-tests.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE.txt ├── MAINTAINERS.md ├── Makefile ├── README.md ├── build.sbt ├── docs ├── QuickStart.md ├── README.md └── openapi-3-developer.json ├── project ├── build.properties └── plugins.sbt └── src ├── main ├── resources │ ├── application.conf │ ├── exchange.conf │ ├── logback.xml │ ├── messages.txt │ ├── messages_de.txt │ ├── messages_es.txt │ ├── messages_fr.txt │ ├── messages_it.txt │ ├── messages_ja.txt │ ├── messages_ko.txt │ ├── messages_pt_br.txt │ ├── messages_zh_cn.txt │ ├── messages_zh_tw.txt │ ├── reference.conf │ ├── swagger │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── index.css │ │ ├── index.html │ │ ├── oauth2-redirect.html │ │ ├── swagger-initializer.js │ │ ├── swagger-ui-bundle.js │ │ ├── swagger-ui-bundle.js.map │ │ ├── swagger-ui-es-bundle-core.js │ │ ├── swagger-ui-es-bundle-core.js.map │ │ ├── swagger-ui-es-bundle.js │ │ ├── swagger-ui-es-bundle.js.map │ │ ├── swagger-ui-standalone-preset.js │ │ ├── swagger-ui-standalone-preset.js.map │ │ ├── swagger-ui.css │ │ ├── swagger-ui.css.map │ │ ├── swagger-ui.js │ │ └── swagger-ui.js.map │ └── version.txt └── scala │ └── org │ └── openhorizon │ └── exchangeapi │ ├── ExchangeApiApp.scala │ ├── SwaggerDocService.scala │ ├── auth │ ├── Access.scala │ ├── AccessGroups.scala │ ├── AuthCache.scala │ ├── AuthRoles.scala │ ├── AuthenticationSupport.scala │ ├── AuthorizationSupport.scala │ ├── CacheIdType.scala │ ├── CompositeId.scala │ ├── Creds.scala │ ├── Exceptions.scala │ ├── IAgbot.scala │ ├── IIdentity.scala │ ├── INode.scala │ ├── IUser.scala │ ├── Identity.scala │ ├── Module.scala │ ├── OrgAndId.scala │ ├── OrgAndIdCred.scala │ ├── Password.scala │ ├── RequestInfo.scala │ ├── Role.scala │ ├── TAction.scala │ ├── TAgbot.scala │ ├── TBusiness.scala │ ├── TManagementPolicy.scala │ ├── TNode.scala │ ├── TOrg.scala │ ├── TPattern.scala │ ├── TService.scala │ ├── TUser.scala │ ├── Target.scala │ ├── Token.scala │ └── cloud │ │ ├── IBM.scala │ │ └── ISV.scala │ ├── route │ ├── administration │ │ ├── AdminConfigRequest.scala │ │ ├── AdminDropdbTokenResponse.scala │ │ ├── AdminOrgStatus.scala │ │ ├── AdminStatus.scala │ │ ├── ClearAuthCache.scala │ │ ├── Configuration.scala │ │ ├── DeleteIBMChangesRequest.scala │ │ ├── DeleteOrgChangesRequest.scala │ │ ├── DropDatabase.scala │ │ ├── InitializeDatabase.scala │ │ ├── OrganizationStatus.scala │ │ ├── Reload.scala │ │ ├── Status.scala │ │ ├── Version.scala │ │ └── dropdatabase │ │ │ └── Token.scala │ ├── agent │ │ └── AgentConfigurationManagement.scala │ ├── agreementbot │ │ ├── AgreementBot.scala │ │ ├── AgreementBots.scala │ │ ├── DeploymentPattern.scala │ │ ├── DeploymentPatterns.scala │ │ ├── DeploymentPolicies.scala │ │ ├── DeploymentPolicy.scala │ │ ├── GetAgbotAgreementsResponse.scala │ │ ├── GetAgbotAttributeResponse.scala │ │ ├── GetAgbotBusinessPolsResponse.scala │ │ ├── GetAgbotMsgsResponse.scala │ │ ├── GetAgbotPatternsResponse.scala │ │ ├── GetAgbotsResponse.scala │ │ ├── Heartbeat.scala │ │ ├── PatchAgbotsRequest.scala │ │ ├── PostAgbotBusinessPolRequest.scala │ │ ├── PostAgbotPatternRequest.scala │ │ ├── PostAgbotsMsgsRequest.scala │ │ ├── PostAgreementsConfirmRequest.scala │ │ ├── PutAgbotAgreementRequest.scala │ │ ├── PutAgbotsRequest.scala │ │ ├── agreement │ │ │ ├── Agreement.scala │ │ │ ├── Agreements.scala │ │ │ └── Confirm.scala │ │ └── message │ │ │ ├── Message.scala │ │ │ └── Messages.scala │ ├── catalog │ │ ├── DeploymentPatterns.scala │ │ ├── OrganizationDeploymentPatterns.scala │ │ ├── OrganizationServices.scala │ │ └── Services.scala │ ├── deploymentpattern │ │ ├── DeploymentPattern.scala │ │ ├── DeploymentPatterns.scala │ │ ├── GetPatternAttributeResponse.scala │ │ ├── GetPatternsResponse.scala │ │ ├── NodeHealth.scala │ │ ├── PatchPatternRequest.scala │ │ ├── PatternUtils.scala │ │ ├── PostPatternSearchRequest.scala │ │ ├── PostPutPatternRequest.scala │ │ ├── PutPatternKeyRequest.scala │ │ ├── Search.scala │ │ └── key │ │ │ ├── Key.scala │ │ │ └── Keys.scala │ ├── deploymentpolicy │ │ ├── BusinessPolicyNodeResponse.scala │ │ ├── BusinessPolicySearchHashElement.scala │ │ ├── BusinessUtils.scala │ │ ├── DeploymentPolicies.scala │ │ ├── DeploymentPolicy.scala │ │ ├── DeploymentPolicySearch.scala │ │ ├── GetBusinessPoliciesResponse.scala │ │ ├── GetBusinessPolicyAttributeResponse.scala │ │ ├── PatchBusinessPolicyRequest.scala │ │ ├── PolicySearchResponseDesync.scala │ │ ├── PostBusinessPolicySearchRequest.scala │ │ ├── PostBusinessPolicySearchResponse.scala │ │ └── PostPutBusinessPolicyRequest.scala │ ├── managementpolicy │ │ ├── GetManagementPoliciesResponse.scala │ │ ├── GetManagementPolicyAttributeResponse.scala │ │ ├── ManagementPolicies.scala │ │ ├── ManagementPolicy.scala │ │ └── PostPutManagementPolicyRequest.scala │ ├── node │ │ ├── ConfigurationState.scala │ │ ├── Details.scala │ │ ├── Errors.scala │ │ ├── GetNodeAgreementsResponse.scala │ │ ├── GetNodeAttributeResponse.scala │ │ ├── GetNodeMsgsResponse.scala │ │ ├── GetNodesResponse.scala │ │ ├── GetNodesUtils.scala │ │ ├── Heartbeat.scala │ │ ├── Node.scala │ │ ├── NodeDetails.scala │ │ ├── NodeMangementPolicyStatus.scala │ │ ├── NodeResponse.scala │ │ ├── Nodes.scala │ │ ├── PatchNodesRequest.scala │ │ ├── PatternNodeResponse.scala │ │ ├── PatternSearchHashElement.scala │ │ ├── Policy.scala │ │ ├── PostNodeConfigStateRequest.scala │ │ ├── PostNodeErrorRequest.scala │ │ ├── PostNodeErrorResponse.scala │ │ ├── PostNodesMsgsRequest.scala │ │ ├── PostPatternSearchResponse.scala │ │ ├── PostSearchNodesResponse.scala │ │ ├── PostServiceSearchRequest.scala │ │ ├── PostServiceSearchResponse.scala │ │ ├── PutNodeAgreementRequest.scala │ │ ├── PutNodeErrorRequest.scala │ │ ├── PutNodeMgmtPolStatusRequest.scala │ │ ├── PutNodePolicyRequest.scala │ │ ├── PutNodeStatusRequest.scala │ │ ├── PutNodesRequest.scala │ │ ├── Status.scala │ │ ├── UpgradedVersions.scala │ │ ├── agreement │ │ │ ├── Agreement.scala │ │ │ └── Agreements.scala │ │ ├── managementpolicy │ │ │ ├── Status.scala │ │ │ └── Statuses.scala │ │ └── message │ │ │ ├── Message.scala │ │ │ └── Messages.scala │ ├── nodegroup │ │ ├── GetNodeGroupsResponse.scala │ │ ├── NodeGroup.scala │ │ ├── NodeGroupResp.scala │ │ ├── NodeGroups.scala │ │ ├── PutNodeGroupsRequest.scala │ │ └── node │ │ │ └── Node.scala │ ├── organization │ │ ├── AllNodeErrorsInOrgResp.scala │ │ ├── ChangeEntry.scala │ │ ├── Changes.scala │ │ ├── Cleanup.scala │ │ ├── GetMyOrgsRequest.scala │ │ ├── GetOrgAttributeResponse.scala │ │ ├── GetOrgStatusResponse.scala │ │ ├── GetOrgsResponse.scala │ │ ├── MaxChangeId.scala │ │ ├── MaxChangeIdResponse.scala │ │ ├── MyOrganizations.scala │ │ ├── NodeErrorsResp.scala │ │ ├── NodeHealthAgreementElement.scala │ │ ├── NodeHealthHashElement.scala │ │ ├── Organization.scala │ │ ├── Organizations.scala │ │ ├── PatchOrgRequest.scala │ │ ├── PostNodeHealthRequest.scala │ │ ├── PostNodeHealthResponse.scala │ │ ├── PostPutOrgRequest.scala │ │ ├── ResourceChangesInnerObject.scala │ │ ├── ResourceChangesRequest.scala │ │ ├── ResourceChangesRespObject.scala │ │ └── Status.scala │ ├── search │ │ ├── NodeError.scala │ │ ├── NodeErrors.scala │ │ ├── NodeHealth.scala │ │ └── NodeService.scala │ ├── service │ │ ├── GetServiceAttributeResponse.scala │ │ ├── GetServicesResponse.scala │ │ ├── PatchServiceRequest.scala │ │ ├── Policy.scala │ │ ├── PostPutServiceDockAuthRequest.scala │ │ ├── PostPutServiceRequest.scala │ │ ├── PutServiceKeyRequest.scala │ │ ├── PutServicePolicyRequest.scala │ │ ├── Service.scala │ │ ├── Services.scala │ │ ├── SharableVals.scala │ │ ├── dockerauth │ │ │ ├── DockerAuth.scala │ │ │ └── DockerAuths.scala │ │ └── key │ │ │ ├── Key.scala │ │ │ └── Keys.scala │ └── user │ │ ├── ChangePassword.scala │ │ ├── ChangePwRequest.scala │ │ ├── Confirm.scala │ │ ├── GetUsersResponse.scala │ │ ├── PatchUsersRequest.scala │ │ ├── PostPutUsersRequest.scala │ │ ├── User.scala │ │ └── Users.scala │ ├── table │ ├── ExchangeApiTables.scala │ ├── ExchangePostgresProfile.scala │ ├── agent │ │ ├── AgentVersions.scala │ │ ├── AgentVersionsChanged.scala │ │ ├── AgentVersionsChangedTQ.scala │ │ ├── AgentVersionsRequest.scala │ │ ├── AgentVersionsResponse.scala │ │ ├── certificate │ │ │ ├── AgentCertificateVersions.scala │ │ │ └── AgentCertificateVersionsTQ.scala │ │ ├── configuration │ │ │ ├── AgentConfigurationVersions.scala │ │ │ └── AgentConfigurationVersionsTQ.scala │ │ └── software │ │ │ ├── AgentSoftwareVersions.scala │ │ │ └── AgentSoftwareVersionsTQ.scala │ ├── agreementbot │ │ ├── AAService.scala │ │ ├── AAWorkload.scala │ │ ├── Agbot.scala │ │ ├── AgbotRow.scala │ │ ├── Agbots.scala │ │ ├── AgbotsTQ.scala │ │ ├── agreement │ │ │ ├── AgbotAgreement.scala │ │ │ ├── AgbotAgreementRow.scala │ │ │ ├── AgbotAgreements.scala │ │ │ └── AgbotAgreementsTQ.scala │ │ ├── deploymentpattern │ │ │ ├── AgbotPattern.scala │ │ │ ├── AgbotPatternRow.scala │ │ │ ├── AgbotPatterns.scala │ │ │ └── AgbotPatternsTQ.scala │ │ ├── deploymentpolicy │ │ │ ├── AgbotBusinessPol.scala │ │ │ ├── AgbotBusinessPolRow.scala │ │ │ ├── AgbotBusinessPols.scala │ │ │ └── AgbotBusinessPolsTQ.scala │ │ └── message │ │ │ ├── AgbotMsg.scala │ │ │ ├── AgbotMsgRow.scala │ │ │ ├── AgbotMsgs.scala │ │ │ └── AgbotMsgsTQ.scala │ ├── deploymentpattern │ │ ├── OneSecretBindingService.scala │ │ ├── OneUserInputService.scala │ │ ├── OneUserInputValue.scala │ │ ├── PDataVerification.scala │ │ ├── PServiceVersions.scala │ │ ├── PServices.scala │ │ ├── Pattern.scala │ │ ├── PatternRow.scala │ │ ├── Patterns.scala │ │ ├── PatternsTQ.scala │ │ └── key │ │ │ ├── PatternKey.scala │ │ │ ├── PatternKeyRow.scala │ │ │ ├── PatternKeys.scala │ │ │ └── PatternKeysTQ.scala │ ├── deploymentpolicy │ │ ├── BService.scala │ │ ├── BServiceVersions.scala │ │ ├── Business.scala │ │ ├── BusinessPoliciesTQ.scala │ │ ├── BusinessPolicy.scala │ │ ├── BusinessPolicyRow.scala │ │ └── search │ │ │ ├── SearchOffsetPolicy.scala │ │ │ ├── SearchOffsetPolicyAttributes.scala │ │ │ └── SearchOffsetPolicyTQ.scala │ ├── managementpolicy │ │ ├── AgentUpgradePolicy.scala │ │ ├── ManagementPolicies.scala │ │ ├── ManagementPoliciesTQ.scala │ │ ├── ManagementPolicy.scala │ │ └── ManagementPolicyRow.scala │ ├── node │ │ ├── ContainerStatus.scala │ │ ├── Node.scala │ │ ├── NodeHeartbeatIntervals.scala │ │ ├── NodeRow.scala │ │ ├── NodeType.scala │ │ ├── Nodes.scala │ │ ├── NodesTQ.scala │ │ ├── OneService.scala │ │ ├── Op.scala │ │ ├── Prop.scala │ │ ├── PropList.scala │ │ ├── PropType.scala │ │ ├── PropVar.scala │ │ ├── RegService.scala │ │ ├── RegServiceSearch.scala │ │ ├── RegServiceTrait.scala │ │ ├── agreement │ │ │ ├── AgreementsHash.scala │ │ │ ├── NAService.scala │ │ │ ├── NAgrService.scala │ │ │ ├── NodeAgreement.scala │ │ │ ├── NodeAgreementRow.scala │ │ │ ├── NodeAgreements.scala │ │ │ └── NodeAgreementsTQ.scala │ │ ├── deploymentpolicy │ │ │ ├── NodePolicies.scala │ │ │ ├── NodePolicy.scala │ │ │ ├── NodePolicyRow.scala │ │ │ ├── NodePolicyTQ.scala │ │ │ └── PropertiesAndConstraints.scala │ │ ├── error │ │ │ ├── NodeError.scala │ │ │ ├── NodeErrorRow.scala │ │ │ ├── NodeErrorTQ.scala │ │ │ └── NodeErrors.scala │ │ ├── group │ │ │ ├── NodeGroup.scala │ │ │ ├── NodeGroupRow.scala │ │ │ ├── NodeGroupTQ.scala │ │ │ ├── NodeGroups.scala │ │ │ └── assignment │ │ │ │ ├── NodeGroupAssignment.scala │ │ │ │ ├── NodeGroupAssignmentRow.scala │ │ │ │ ├── NodeGroupAssignmentTQ.scala │ │ │ │ ├── NodeGroupAssignments.scala │ │ │ │ └── PostPutNodeGroupsRequest.scala │ │ ├── managementpolicy │ │ │ └── status │ │ │ │ ├── GetNMPStatusResponse.scala │ │ │ │ ├── NMPStatus.scala │ │ │ │ ├── NodeMgmtPolStatus.scala │ │ │ │ ├── NodeMgmtPolStatusRow.scala │ │ │ │ ├── NodeMgmtPolStatuses.scala │ │ │ │ ├── PolicyStatus.scala │ │ │ │ └── UpgradedVersions.scala │ │ ├── message │ │ │ ├── NodeMsg.scala │ │ │ ├── NodeMsgRow.scala │ │ │ ├── NodeMsgs.scala │ │ │ └── NodeMsgsTQ.scala │ │ └── status │ │ │ ├── NodeStatus.scala │ │ │ ├── NodeStatusRow.scala │ │ │ ├── NodeStatusTQ.scala │ │ │ └── NodeStatuses.scala │ ├── organization │ │ ├── Org.scala │ │ ├── OrgLimits.scala │ │ ├── OrgRow.scala │ │ ├── Orgs.scala │ │ └── OrgsTQ.scala │ ├── resourcechange │ │ ├── ResChangeCategory.scala │ │ ├── ResChangeOperation.scala │ │ ├── ResChangeResource.scala │ │ ├── ResourceChange.scala │ │ ├── ResourceChangeRow.scala │ │ ├── ResourceChanges.scala │ │ └── ResourceChangesTQ.scala │ ├── schema │ │ ├── Schema.scala │ │ ├── SchemaRow.scala │ │ ├── SchemaTQ.scala │ │ └── SchemaTable.scala │ ├── service │ │ ├── OneProperty.scala │ │ ├── SearchService.scala │ │ ├── SearchServiceKey.scala │ │ ├── SearchServiceTQ.scala │ │ ├── Service.scala │ │ ├── ServiceRef.scala │ │ ├── ServiceRef2.scala │ │ ├── ServiceRow.scala │ │ ├── Services.scala │ │ ├── ServicesTQ.scala │ │ ├── dockerauth │ │ │ ├── ServiceDockAuth.scala │ │ │ ├── ServiceDockAuthRow.scala │ │ │ ├── ServiceDockAuths.scala │ │ │ └── ServiceDockAuthsTQ.scala │ │ ├── key │ │ │ ├── ServiceKey.scala │ │ │ ├── ServiceKeyRow.scala │ │ │ ├── ServiceKeys.scala │ │ │ └── ServiceKeysTQ.scala │ │ └── policy │ │ │ ├── ServicePolicies.scala │ │ │ ├── ServicePolicy.scala │ │ │ ├── ServicePolicyRow.scala │ │ │ └── ServicePolicyTQ.scala │ └── user │ │ ├── User.scala │ │ ├── UserRow.scala │ │ ├── Users.scala │ │ └── UsersTQ.scala │ └── utility │ ├── AccessDeniedRejection.scala │ ├── AlreadyExists2Rejection.scala │ ├── AlreadyExistsRejection.scala │ ├── ApiRespType.scala │ ├── ApiResponse.scala │ ├── ApiTime.scala │ ├── ApiUtils.scala │ ├── AuthRejection.scala │ ├── BadCredsRejection.scala │ ├── BadGwRejection.scala │ ├── BadInputRejection.scala │ ├── Configuration.scala │ ├── DatabaseConnection.scala │ ├── ExchMsg.scala │ ├── ExchangePosgtresErrorHandling.scala │ ├── ExchangeRejection.scala │ ├── GwTimeoutRejection.scala │ ├── HttpCode.scala │ ├── InternalErrorRejection.scala │ ├── LogLevel.scala │ ├── NodeAgbotTokenValidation.scala │ ├── NotFoundRejection.scala │ ├── Nth.scala │ ├── RouteUtils.scala │ ├── StrConstants.scala │ ├── Version.scala │ └── VersionRange.scala └── test ├── bash ├── README.md ├── agbot.sh ├── anonymous.sh ├── dropalltables.sh ├── frontend.sh ├── functions.sh ├── get │ ├── admin │ │ ├── dropdb-token │ │ │ └── root.sh │ │ └── gettest │ │ │ └── root.sh │ ├── agbots │ │ └── notthere.sh │ ├── agreements │ │ ├── agbots-notthere.sh │ │ └── nodes-notthere.sh │ ├── nodes │ │ ├── 1-urlparms-noid.sh │ │ ├── 1-urlparms-user.sh │ │ ├── 1-urlparms.sh │ │ ├── all-root-urlparms.sh │ │ └── notthere.sh │ └── users │ │ ├── all-root-encoded.sh │ │ ├── user-baduser.sh │ │ └── user-newpw.sh ├── https.sh ├── node.sh ├── patch │ ├── agbots │ │ ├── 1-agbot-badinput.sh │ │ ├── 1-agbot-publicKey-blank.sh │ │ ├── 1-agbot-publicKey.sh │ │ └── 1-agbot-token.sh │ ├── nodes │ │ ├── 1-node-badinput.sh │ │ ├── 1-node-name.sh │ │ ├── 1-node-pattern.sh │ │ ├── 1-node-publicKey-blank.sh │ │ └── 1-node-publicKey.sh │ ├── pattern │ │ └── patch.sh │ └── services │ │ ├── gps-arch-bad.sh │ │ ├── gps-sharable-bad.sh │ │ ├── gps.sh │ │ └── location.sh ├── post │ ├── admin │ │ ├── dropdb │ │ │ └── root.sh │ │ ├── hashpw │ │ │ ├── root.sh │ │ │ └── user.sh │ │ ├── initdb │ │ │ └── root.sh │ │ └── reload │ │ │ ├── root.sh │ │ │ └── user.sh │ ├── agbots │ │ ├── dataheartbeat │ │ │ ├── 123-list.sh │ │ │ └── 123.sh │ │ ├── heartbeat │ │ │ ├── 1-user.sh │ │ │ └── 1.sh │ │ ├── isrecentdata │ │ │ └── 123-list.sh │ │ └── msgs │ │ │ └── a1-msg1.sh │ ├── agreements │ │ └── confirm │ │ │ ├── 123-a2.sh │ │ │ ├── 123-user.sh │ │ │ └── 123.sh │ ├── nodes │ │ ├── heartbeat │ │ │ ├── 1-user.sh │ │ │ └── 1.sh │ │ └── msgs │ │ │ ├── 1-msg1.sh │ │ │ ├── 1-msg2.sh │ │ │ └── 2-msg1.sh │ ├── orgs │ │ └── create.sh │ ├── patterns │ │ ├── nodehealth │ │ │ └── p1.sh │ │ ├── p1.sh │ │ └── search │ │ │ └── location.sh │ ├── search │ │ └── devices │ │ │ ├── multiple-wildcard.sh │ │ │ ├── netspeed-dave.sh │ │ │ ├── netspeed-wildcard-agbot.sh │ │ │ ├── netspeed-wildcard.sh │ │ │ ├── sdr-arch-x86.sh │ │ │ ├── sdr-badpw.sh │ │ │ ├── sdr-datav-false.sh │ │ │ ├── sdr-good-agbot.sh │ │ │ ├── sdr-good.sh │ │ │ ├── sdr-memory-400.sh │ │ │ ├── sdr-noversion.sh │ │ │ ├── sdr-version-2.sh │ │ │ ├── sdr-wildcard-prod.sh │ │ │ ├── sdr-wildcard-stale.sh │ │ │ └── sdr-wildcard.sh │ ├── services │ │ ├── dockauths │ │ │ └── gps.sh │ │ ├── gps.sh │ │ ├── location-bad-reqsvc.sh │ │ ├── location-diff-arch-bad.sh │ │ └── location.sh │ └── users │ │ ├── 2-create-admin.sh │ │ ├── 2-create-badinput.sh │ │ ├── 2-create-noemail.sh │ │ ├── 2-create.sh │ │ ├── 3-create-2.sh │ │ ├── changepw │ │ ├── user-backtoorig.sh │ │ └── user.sh │ │ ├── confirm │ │ ├── baduser.sh │ │ ├── user-encoded.sh │ │ ├── user-newpw.sh │ │ ├── user-urlparms.sh │ │ ├── user-urlparms2.sh │ │ └── user.sh │ │ ├── new-create-admin.sh │ │ ├── reset │ │ ├── anonymous.sh │ │ ├── user-root.sh │ │ └── user.sh │ │ ├── user-create-anonymous.sh │ │ ├── user-create-frontend.sh │ │ └── user-create-root.sh ├── primedb.sh ├── put │ ├── admin │ │ ├── config │ │ │ ├── maxAgbots.sh │ │ │ ├── maxAgreements.sh │ │ │ ├── maxDevices.sh │ │ │ └── maxMessagesInMailbox.sh │ │ ├── loglevel │ │ │ └── root.sh │ │ └── table │ │ │ └── users.sh │ ├── agbots │ │ ├── a1-compatible.sh │ │ ├── a1-frontend.sh │ │ ├── a1-root.sh │ │ ├── a1.sh │ │ ├── a2-root.sh │ │ ├── a2-user.sh │ │ └── a3.sh │ ├── agreements │ │ ├── 123-agbot-user.sh │ │ ├── 123-agbot.sh │ │ ├── 123-node.sh │ │ ├── 456-agbot.sh │ │ ├── 456-node.sh │ │ ├── 789-agbot.sh │ │ └── 789-node.sh │ ├── nodes │ │ ├── 1-node.sh │ │ ├── 1-user-changes.sh │ │ ├── 1-user-compatible.sh │ │ ├── 1-user.sh │ │ ├── 2-memory-400-node.sh │ │ ├── 2-memory-400.sh │ │ ├── 3-version-2-root.sh │ │ ├── 3-version-2-user.sh │ │ ├── 4-badbool.sh │ │ ├── 4-badint.sh │ │ ├── 4-badop.sh │ │ ├── 999-badinput.sh │ │ ├── status │ │ │ └── 1-node.sh │ │ └── weird-user.sh │ ├── patterns │ │ ├── p1-no-nodehealth.sh │ │ └── p1.sh │ ├── services │ │ ├── dockauths │ │ │ └── gps-1.sh │ │ ├── gps-arch-bad.sh │ │ ├── gps-sharable-bad.sh │ │ ├── gps.sh │ │ └── keys │ │ │ └── key.sh │ └── users │ │ ├── 2-create-root.sh │ │ ├── 2-update-root.sh │ │ ├── root-root.sh │ │ ├── root-user.sh │ │ ├── user-create-root.sh │ │ ├── user-update-email.sh │ │ ├── user-update-root.sh │ │ └── user-update.sh ├── root.sh ├── scale │ ├── agbot.sh │ ├── deleteperforg.sh │ ├── functions.sh │ ├── node.sh │ ├── scaledriver.sh │ ├── summarize.sh │ ├── test.sh │ └── wrapper.sh ├── user.sh └── user2.sh ├── go ├── .gitignore ├── Makefile ├── agbot │ └── agbot.go ├── node │ └── node.go └── perfutils │ └── perfutils.go ├── java └── org │ └── openhorizon │ └── exchangeapi │ └── annotation │ └── AdminStatusTest.java ├── resources └── logback-test.xml └── scala └── org └── openhorizon └── exchangeapi ├── AdminSuite.scala ├── AgbotsSuite.scala ├── BusinessSuite.scala ├── CatalogSuite.scala ├── NodesSuite.scala ├── PatternsSuite.scala ├── PerfSuite.scala ├── ServicesSuite.scala ├── SlickSuite.scala ├── UsersSuite.scala ├── route ├── administration │ ├── TestAdminConfigRequest.scala │ ├── TestAdminDropdbTokenResponse.scala │ └── TestGetAdminStatus.scala ├── agent │ ├── TestAgentConfigMgmt.scala │ ├── TestDeleteAgentConfigMgmt.scala │ ├── TestGetAgentConfigMgmt.scala │ └── TestPutAgentConfigMgmt.scala ├── agreement │ └── TestPostAgreementConfirmRoute.scala ├── agreementbot │ └── message │ │ └── TestAgbotGetMsgRoute.scala ├── deploymentpattern │ └── TestGetPatternsResponse.scala ├── deploymentpolicy │ ├── TestBusPolPostSearchRoute.scala │ ├── TestBusinessPolicyNodeResponse.scala │ └── TestBusinessPolicySearchHashElement.scala ├── managementpolicy │ ├── ManagementPoliciesSuite.scala │ ├── TestGetManagementPoliciesResponse.scala │ └── TestMgmtPolsGet.scala ├── node │ ├── TestGetNode.scala │ ├── TestNodeHealthAgreementElement.scala │ ├── TestNodePatch.scala │ ├── TestNodePutMgmtPolStatus.scala │ ├── TestNodesGetDetails.scala │ ├── TestPatternNodeResponse.scala │ ├── TestPatternSearchHashElement.scala │ ├── managementpolicy │ │ ├── TestNodeDeleteMgmtPolStatus.scala │ │ ├── TestNodeGetAllMgmtPolStatus.scala │ │ └── TestNodeGetMgmtPolStatus.scala │ └── message │ │ └── TestNodeGetMsgRoute.scala ├── nodegroup │ ├── TestDeleteNodeGroup.scala │ ├── TestGetAllNodeGroups.scala │ ├── TestGetNodeGroup.scala │ ├── TestPostNodeGroup.scala │ ├── TestPutNodeGroup.scala │ └── node │ │ ├── TestDeleteNodeFromNodeGroup.scala │ │ └── TestPostNodeToNodeGroup.scala ├── organization │ ├── TestDeleteOrgRoute.scala │ ├── TestGetMaxChangeIDRoute.scala │ ├── TestGetOrgRoute.scala │ ├── TestGetOrgsRoute.scala │ ├── TestPatchOrgRoute.scala │ ├── TestPostMyOrgsRoute.scala │ ├── TestPostOrgChangesRoute.scala │ ├── TestPostOrgRoute.scala │ └── TestPutOrgRoute.scala ├── search │ ├── TestGetAllNodeErrorsRoute.scala │ ├── TestPostNodeErrorsRoute.scala │ ├── TestPostNodeHealthRoute.scala │ └── TestPostNodesServiceRoute.scala ├── service │ ├── TestGetServiceAttributeResponse.scala │ └── TestGetServicesResponse.scala └── user │ ├── TestDeleteUserRoute.scala │ ├── TestGetUserRoute.scala │ ├── TestGetUsersResponse.scala │ ├── TestGetUsersRoute.scala │ ├── TestPatchUserRoute.scala │ ├── TestPostChangeUserPasswordRoute.scala │ ├── TestPostConfirmUserRoute.scala │ ├── TestPostUserRoute.scala │ └── TestPutUserRoute.scala ├── tag └── AdminStatusTest.scala └── utility ├── TestVersion.scala ├── TestVersionRange.scala ├── apiutils └── TestApiUtilsTime.scala ├── exchconfiguration └── TestExchConfiguration.scala └── tokenvalidation └── TestNodeAgbotTokenValidation.scala /.github/workflows/copydocs.yml: -------------------------------------------------------------------------------- 1 | name : Copy Docs 2 | on: 3 | push: 4 | branches: 5 | - master 6 | paths: 7 | - 'docs/**' 8 | 9 | jobs: 10 | copy: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Copycat 14 | uses: andstor/copycat-action@v3 15 | with: 16 | commit_message: "Syncing from exchange-api" 17 | clean: false 18 | personal_token: ${{ secrets.PERSONAL_TOKEN }} 19 | src_path: docs 20 | dst_path: /docs/exchange-api 21 | dst_owner: open-horizon 22 | dst_repo_name: open-horizon.github.io 23 | dst_branch: master 24 | src_branch: master -------------------------------------------------------------------------------- /.github/workflows/dependency-graph.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/dependency-graph.yml 2 | name: Update Dependency Graph 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - v2.124 8 | - v2.122 9 | - v2.110 10 | - v2.87 11 | jobs: 12 | dependency-graph: 13 | name: Update Dependency Graph 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | - uses: sbt/setup-sbt@v1 18 | - uses: scalacenter/sbt-dependency-submission@v2 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created/used by sbt 2 | /bin/ 3 | project/project/ 4 | project/target/ 5 | target/ 6 | .lib/ 7 | 8 | # Create by Makefile to hold build timestamps 9 | /.docker-* 10 | 11 | /keys/ 12 | 13 | # IntelliJ IDEA 14 | .idea/ 15 | /exchange-api.iml 16 | /.bsp/ 17 | 18 | # VSCode 19 | /.bloop/ 20 | /.metals/ 21 | /.vscode/ 22 | /project/.bloop/ 23 | /project/metals.sbt 24 | 25 | # Eclipse? 26 | .classpath 27 | .cache-main 28 | .cache-tests 29 | .project 30 | .settings/ 31 | 32 | 33 | # Mac specific 34 | .DS_Store 35 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | Repository Maintainers 2 | ====================== 3 | 4 | See the information about [community membership roles](https://wiki.lfedge.org/display/OH/Community+Membership) to learn about the role of the maintainers and the process to become one. 5 | 6 | | Name | GitHub | Email | 7 | |---------------|------------------------------------------------|---------------------------| 8 | | Nathan Phelps | [@naphelps](https://github.com/naphelps) | | 9 | 10 | # Emeritus Maintainers 11 | 12 | The emeritus maintainers of this repository are: 13 | 14 | | Name | GitHub | email | 15 | | ------------- |------------------------------------------------|----------------------| 16 | | Bruce Potter | [@bmpotter](https://github.com/bmpotter) | | 17 | | Lorenzo King | [@lorenzoking](https://github.com/lorenzoking) | | 18 | | Sadiyah Faruk | [@sf2ne](https://github.com/sf2ne) | | 19 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.11.0 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "[0.14.3,)") 2 | 3 | // Builds docker image of our exchange svr 4 | addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "[1.11.1,)") 5 | 6 | // Linter 7 | // addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "[1.1.0,)") 8 | 9 | // A fast restart of our rest api svr in sbt. Does NOT require use of spray 10 | addSbtPlugin("io.spray" % "sbt-revolver" % "[0.10.0,)") 11 | 12 | // Code coverage report generation 13 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "[2.3.1,)") 14 | 15 | ThisBuild / libraryDependencySchemes ++= Seq( 16 | "org.scala-lang.modules" %% "scala-xml" % VersionScheme.Always 17 | ) 18 | -------------------------------------------------------------------------------- /src/main/resources/swagger/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-horizon/exchange-api/9810084bc3a83cc663cdc8f5b8e8db3dc17770f9/src/main/resources/swagger/favicon-16x16.png -------------------------------------------------------------------------------- /src/main/resources/swagger/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-horizon/exchange-api/9810084bc3a83cc663cdc8f5b8e8db3dc17770f9/src/main/resources/swagger/favicon-32x32.png -------------------------------------------------------------------------------- /src/main/resources/swagger/index.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | overflow: -moz-scrollbars-vertical; 4 | overflow-y: scroll; 5 | } 6 | 7 | *, 8 | *:before, 9 | *:after { 10 | box-sizing: inherit; 11 | } 12 | 13 | body { 14 | margin: 0; 15 | background: #fafafa; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/resources/swagger/swagger-initializer.js: -------------------------------------------------------------------------------- 1 | window.onload = function() { 2 | // 3 | 4 | // the following lines will be replaced by docker/configurator, when it runs in a docker-container 5 | window.ui = SwaggerUIBundle({ 6 | url: "https://petstore.swagger.io/v2/swagger.json", 7 | dom_id: '#swagger-ui', 8 | deepLinking: true, 9 | presets: [ 10 | SwaggerUIBundle.presets.apis, 11 | SwaggerUIStandalonePreset 12 | ], 13 | plugins: [ 14 | SwaggerUIBundle.plugins.DownloadUrl 15 | ], 16 | layout: "StandaloneLayout" 17 | }); 18 | 19 | // 20 | }; 21 | -------------------------------------------------------------------------------- /src/main/resources/version.txt: -------------------------------------------------------------------------------- 1 | 2.127.0 2 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/AccessGroups.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | import org.openhorizon.exchangeapi.auth.Access.{ADMIN, CREATE_IN_OTHER_ORGS, CREATE_ORGS, DELETE_ORG, NEVER_ALLOWED, READ_OTHER_ORGS, SET_IBM_ORG_TYPE, WRITE_OTHER_ORGS} 4 | 5 | object AccessGroups { 6 | val CROSS_ORG_ACCESS: Set[Access.Value] = 7 | Set(CREATE_ORGS, 8 | DELETE_ORG, 9 | READ_OTHER_ORGS, 10 | WRITE_OTHER_ORGS, 11 | CREATE_IN_OTHER_ORGS, 12 | SET_IBM_ORG_TYPE, 13 | ADMIN, 14 | NEVER_ALLOWED) 15 | } 16 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/AuthRoles.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | // These are default roles (always defined). More can be added in the config file 4 | object AuthRoles { 5 | val SuperUser = "SuperUser" 6 | val AdminUser = "AdminUser" 7 | val HubAdmin = "HubAdmin" 8 | val User = "User" 9 | val Node = "Node" 10 | val Agbot = "Agbot" 11 | val Anonymous = "Anonymous" 12 | val requiredRoles: Set[String] = 13 | Set(Anonymous, 14 | User, 15 | AdminUser, 16 | HubAdmin, 17 | SuperUser, 18 | Node, 19 | Agbot) 20 | } 21 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/CacheIdType.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | // Enum for type of id in CacheId class 4 | object CacheIdType extends Enumeration { 5 | type CacheIdType = Value 6 | val User: Value = Value("User") 7 | val Node: Value = Value("Node") 8 | val Agbot: Value = Value("Agbot") 9 | val None: Value = Value("None") 10 | } 11 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/CompositeId.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | import scala.util.matching.Regex 4 | 5 | final case class CompositeId(compositeId: String) { 6 | def getOrg: String = { 7 | val reg: Regex = """^(\S+?)/.*""".r 8 | compositeId match { 9 | case reg(org) => org 10 | case _ => "" 11 | } 12 | } 13 | 14 | def getId: String = { 15 | val reg: Regex = """^\S+?/(\S+)$""".r 16 | compositeId match { 17 | case reg(id) => id 18 | case _ => "" 19 | } 20 | } 21 | 22 | def split: (String, String) = { 23 | val reg: Regex = """^(\S*?)/(\S*)$""".r 24 | compositeId match { 25 | case reg(org, id) => (org, id) 26 | // These 2 lines never get run, and aren't needed. If we really want to handle a special, put something like this as the 1st case above: case reg(org, "") => return (org, "") 27 | //case reg(org, _) => return (org, "") 28 | //case reg(_, id) => return ("", id) 29 | case _ => ("", "") 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/Creds.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | final case class Creds(id: String = "", 4 | token: String = "") { // id and token are generic names and their values can actually be username and password 5 | //def isAnonymous: Boolean = (id == "" && token == "") 6 | //someday: maybe add an optional hint to this so when they specify creds as username/password we know to try to authenticate as a user 1st 7 | } 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/IIdentity.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | import org.apache.pekko.event.LoggingAdapter 4 | import org.openhorizon.exchangeapi.auth.Access.Access 5 | 6 | import scala.util.{Failure, Try} 7 | 8 | /** A generic identity before we have run authenticate to figure out what type of credentials this is */ 9 | case class IIdentity(creds: Creds, identity: Identity2) extends Identity { 10 | 11 | override def identity2: Identity2 = identity.copy() 12 | 13 | def authorizeTo(target: Target, access: Access)(implicit logger: LoggingAdapter): Try[Identity] = { 14 | // should never be called because authenticate() will return a real resource 15 | Failure(new AuthInternalErrorException("Not Implemented")) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/OrgAndId.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | final case class OrgAndId(org: String, 4 | id: String) { 5 | override def toString: String = 6 | if (org == "" || id.startsWith(org + "/") || id.startsWith(Role.superUser)) 7 | id.trim 8 | else 9 | org.trim + "/" + id.trim 10 | } 11 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/OrgAndIdCred.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | // This class is separate from the one above, because when the id is for a cred, we want automatically add the org only when a different org is not there 4 | final case class OrgAndIdCred(org: String, 5 | id: String) { 6 | override def toString: String = 7 | if (org == "" || id.contains("/") || id.startsWith(Role.superUser)) 8 | id.trim 9 | else 10 | org.trim + "/" + id.trim // we only check for slash, because they could already have on a different org 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/RequestInfo.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | // The context info about the request passed into the login() methods 4 | final case class RequestInfo(creds: Creds, 5 | isDbMigration: Boolean, 6 | hint: String) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/TAction.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | case class TAction(id: String = "") extends Target { // for post rest api methods that do not target any specific resource (e.g. admin operations) 4 | override def label = "action" 5 | } 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/TAgbot.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | import org.openhorizon.exchangeapi.ExchangeApiApp.getOwnerOfResource 4 | 5 | import java.util.UUID 6 | import scala.concurrent.Await 7 | import scala.concurrent.duration.DurationInt 8 | 9 | case class TAgbot(id: String, owner: Option[UUID] = None) extends Target { 10 | override def isOwner(user: IUser): Boolean = { 11 | if (owner.isEmpty || owner.get == user.identity.identifier.get) 12 | true 13 | else 14 | false 15 | } 16 | 17 | override def isThere: Boolean = all || mine || owner.isDefined 18 | override def label = "agbot" 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/TBusiness.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | import org.openhorizon.exchangeapi.ExchangeApiApp.getOwnerOfResource 4 | 5 | import java.util.UUID 6 | import scala.concurrent.Await 7 | import scala.concurrent.duration.DurationInt 8 | 9 | case class TBusiness(id: String, owner: Option[UUID] = None) extends Target { // for business policies only the user that created it can update/delete it 10 | override def isOwner(user: IUser): Boolean = { 11 | if (owner.isEmpty || owner.get == user.identity.identifier.get) 12 | true 13 | else 14 | false 15 | } 16 | // business policies can never be public, so no need to override isPublic 17 | override def isThere: Boolean = all || mine || owner.isDefined 18 | override def label = "business policy" 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/TManagementPolicy.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | import org.openhorizon.exchangeapi.ExchangeApiApp.getOwnerOfResource 4 | 5 | import java.util.UUID 6 | import scala.concurrent.Await 7 | import scala.concurrent.duration.DurationInt 8 | 9 | case class TManagementPolicy(id: String, owner: Option[UUID] = None) extends Target { // for management policies only the user that created it can update/delete it 10 | override def isOwner(user: IUser): Boolean = { 11 | if (owner.isEmpty || owner.get == user.identity.identifier.get) 12 | true 13 | else 14 | false 15 | } 16 | // management policies can never be public, so no need to override isPublic 17 | override def isThere: Boolean = all || mine || owner.isDefined 18 | override def label = "management policy" 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/TNode.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | import org.openhorizon.exchangeapi.ExchangeApiApp.{getOwnerOfResource, logger} 4 | 5 | import java.util.UUID 6 | import scala.concurrent.Await 7 | import scala.concurrent.duration.DurationInt 8 | 9 | case class TNode(id: String, owner: Option[UUID] = None) extends Target { 10 | override def isOwner(user: IUser): Boolean = 11 | if (owner.isEmpty || owner.get == user.identity.identifier.get) 12 | true 13 | else 14 | false 15 | override def isThere: Boolean = all || mine || owner.isDefined 16 | override def label = "node" 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/TOrg.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | case class TOrg(id: String) extends Target { 4 | override def getOrg: String = id // otherwise the regex in the base class will return blank because there is no / 5 | override def getId = "" 6 | override def isThere: Boolean = true // we don't have a cache to quickly tell if this org exists, so return true and let the db access sort it out 7 | override def label = "org" 8 | } 9 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/TPattern.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | import org.openhorizon.exchangeapi.ExchangeApiApp.getOwnerOfResource 4 | 5 | import java.util.UUID 6 | import scala.concurrent.Await 7 | import scala.concurrent.duration.DurationInt 8 | 9 | case class TPattern(id: String, owner: Option[UUID] = None, public: Boolean = false) extends Target { // for patterns only the user that created it can update/delete it 10 | override def isOwner(user: IUser): Boolean = { 11 | if (owner.isEmpty || owner.get == user.identity.identifier.get) 12 | true 13 | else 14 | false 15 | } 16 | override def isPublic: Boolean = if (all) true else public 17 | override def isThere: Boolean = all || mine || owner.isDefined 18 | override def label = "pattern" 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/TService.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | import org.openhorizon.exchangeapi.ExchangeApiApp.getOwnerOfResource 4 | 5 | import java.util.UUID 6 | import scala.concurrent.Await 7 | import scala.concurrent.duration.DurationInt 8 | import scala.util.{Failure, Success} 9 | 10 | case class TService(id: String, owner: Option[UUID] = None, public: Boolean = false) extends Target { // for services only the user that created it can update/delete it 11 | override def isOwner(user: IUser): Boolean = { 12 | if (owner.isEmpty || owner.get == user.identity.identifier.get) 13 | true 14 | else 15 | false 16 | } 17 | override def isPublic: Boolean = if (all) true else public 18 | override def isThere: Boolean = all || mine || owner.isDefined 19 | override def label = "service" 20 | } 21 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/TUser.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | import java.util.UUID 4 | 5 | case class TUser(id: String, owner: Option[UUID] = None) extends Target { 6 | override def isOwner(user: IUser): Boolean = owner == user.identity.identifier 7 | override def isThere: Boolean = all || mine || owner.isDefined 8 | override def isSuperUser: Boolean = Role.isSuperUser(id) 9 | override def label = "user" 10 | } 11 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/Token.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth 2 | 3 | import org.openhorizon.exchangeapi.utility.ApiTime 4 | 5 | /** Create and validate web tokens that expire */ 6 | /*object Token { 7 | // From: https://github.com/pauldijou/jwt-scala 8 | val defaultExpiration = 600 // seconds 9 | val algorithm: JwtAlgorithm.HS256.type = JwtAlgorithm.HS256 10 | 11 | /** Returns a temporary pw reset token. */ 12 | def create(secret: String, expiration: Int = defaultExpiration): String = { 13 | //implicit val clock: Clock = Clock.systemUTC() 14 | //Jwt.encode(JwtClaim({"""{"user":1}"""}).issuedNow.expiresIn(defaultExpiration), secret, algorithm) 15 | Jwt.encode(JwtClaim({ """{"user":1}""" }).expiresAt(ApiTime.nowSeconds + expiration), secret, algorithm) 16 | } 17 | 18 | /** Returns true if the token is correct for this secret and not expired */ 19 | def isValid(token: String, secret: String): Boolean = { Jwt.isValid(token, secret, Seq(algorithm)) } 20 | }*/ 21 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/auth/cloud/ISV.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.auth.cloud 2 | 3 | //case class ISV(configuration: OidcConfiguration = new OidcConfiguration().withSecret("").withClientId("")) 4 | 5 | 6 | //new OidcConfiguration().withClientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST).withClientId("").withScope("openid").withSecret("") 7 | 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/administration/AdminConfigRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.administration 2 | 3 | final case class AdminConfigRequest(varPath: String, value: String) { 4 | require(varPath!=null && value!=null) 5 | } 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/administration/AdminDropdbTokenResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.administration 2 | 3 | final case class AdminDropdbTokenResponse(token: String) 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/administration/AdminOrgStatus.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.administration 2 | 3 | import io.swagger.v3.oas.annotations.media.Schema 4 | 5 | case class AdminOrgStatus(msg: String = "", 6 | @Schema(implementation = classOf[Map[String, Int]]) nodes: Map[String, Int]){ 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/administration/DeleteIBMChangesRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.administration 2 | 3 | /** Case class for request body for deleting some of the IBM changes route */ 4 | final case class DeleteIBMChangesRequest(resources: List[String]) { 5 | def getAnyProblem: Option[String] = { 6 | if (resources.isEmpty) Some("resources list cannot be empty") 7 | else None 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/administration/DeleteOrgChangesRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.administration 2 | 3 | /** Case class for request body for deleting some of the org changes in the resourcechanges table */ 4 | final case class DeleteOrgChangesRequest(resources: List[String]) { 5 | def getAnyProblem: Option[String] = None 6 | } 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/agreementbot/GetAgbotAgreementsResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.agreementbot 2 | 3 | import org.openhorizon.exchangeapi.table.agreementbot.agreement.AgbotAgreement 4 | 5 | /** Output format for GET /orgs/{organization}/agbots/{id}/agreements */ 6 | final case class GetAgbotAgreementsResponse(agreements: Map[String,AgbotAgreement], lastIndex: Int = 0) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/agreementbot/GetAgbotAttributeResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.agreementbot 2 | 3 | final case class GetAgbotAttributeResponse(attribute: String, 4 | value: String) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/agreementbot/GetAgbotBusinessPolsResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.agreementbot 2 | 3 | import org.openhorizon.exchangeapi.table.agreementbot.deploymentpolicy.AgbotBusinessPol 4 | 5 | /** Output format for GET /orgs/{organization}/agbots/{id}/businesspols */ 6 | final case class GetAgbotBusinessPolsResponse(businessPols: Map[String,AgbotBusinessPol]) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/agreementbot/GetAgbotMsgsResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.agreementbot 2 | 3 | import org.openhorizon.exchangeapi.table.agreementbot.message.AgbotMsg 4 | 5 | /** Response for GET /orgs/{organization}/agbots/{id}/msgs */ 6 | final case class GetAgbotMsgsResponse(messages: List[AgbotMsg], lastIndex: Int = 0) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/agreementbot/GetAgbotPatternsResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.agreementbot 2 | 3 | import org.openhorizon.exchangeapi.table.agreementbot.deploymentpattern.AgbotPattern 4 | 5 | /** Output format for GET /orgs/{organization}/agbots/{id}/patterns */ 6 | final case class GetAgbotPatternsResponse(patterns: Map[String,AgbotPattern]) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/agreementbot/GetAgbotsResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.agreementbot 2 | 3 | import org.openhorizon.exchangeapi.table.agreementbot.Agbot 4 | 5 | /** Output format for GET /orgs/{organization}/agbots */ 6 | final case class GetAgbotsResponse(agbots: Map[String, Agbot], lastIndex: Int = 0) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/agreementbot/PostAgbotPatternRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.agreementbot 2 | 3 | import org.openhorizon.exchangeapi.table.agreementbot.deploymentpattern.{AgbotPattern, AgbotPatternRow} 4 | import org.openhorizon.exchangeapi.utility.ApiTime 5 | 6 | /** Input format for POST /orgs/{organization}/agbots/{id}/patterns */ 7 | final case class PostAgbotPatternRequest(patternOrgid: String, pattern: String, nodeOrgid: Option[String]) { 8 | require(patternOrgid!=null && pattern!=null) 9 | def toAgbotPattern: AgbotPattern = AgbotPattern(patternOrgid, pattern, nodeOrgid.getOrElse(patternOrgid), ApiTime.nowUTC) 10 | def toAgbotPatternRow(agbotId: String, patId: String): AgbotPatternRow = AgbotPatternRow(patId, agbotId, patternOrgid, pattern, nodeOrgid.getOrElse(patternOrgid), ApiTime.nowUTC) 11 | def formId: String = patternOrgid + "_" + pattern + "_" + nodeOrgid.getOrElse(patternOrgid) 12 | def getAnyProblem: Option[String] = None 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/agreementbot/PostAgbotsMsgsRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.agreementbot 2 | 3 | /** Input body for POST /orgs/{organization}/agbots/{id}/msgs */ 4 | final case class PostAgbotsMsgsRequest(message: String, ttl: Int) { 5 | require(message!=null) 6 | } 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/agreementbot/PostAgreementsConfirmRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.agreementbot 2 | 3 | /** Input body for POST /orgs/{organization}/agreements/confirm */ 4 | final case class PostAgreementsConfirmRequest(agreementId: String) { 5 | require(agreementId != null) 6 | } 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/agreementbot/PutAgbotAgreementRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.agreementbot 2 | 3 | import org.openhorizon.exchangeapi.table.agreementbot.AAService 4 | import org.openhorizon.exchangeapi.table.agreementbot.agreement.AgbotAgreementRow 5 | import org.openhorizon.exchangeapi.utility.ApiTime 6 | 7 | /** Input format for PUT /orgs/{organization}/agbots/{id}/agreements/ */ 8 | final case class PutAgbotAgreementRequest(service: AAService, state: String) { 9 | require(service!=null && state!=null) 10 | def getAnyProblem: Option[String] = None 11 | 12 | def toAgbotAgreementRow(agbotId: String, agrId: String): AgbotAgreementRow = { 13 | AgbotAgreementRow(agrId, agbotId, service.orgid, service.pattern, service.url, state, ApiTime.nowUTC, "") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpattern/GetPatternAttributeResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpattern 2 | 3 | final case class GetPatternAttributeResponse(attribute: String, 4 | value: String) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpattern/GetPatternsResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpattern 2 | 3 | import org.openhorizon.exchangeapi.table.deploymentpattern.Pattern 4 | 5 | final case class GetPatternsResponse(patterns: Map[String,Pattern] = Map.empty[String, Pattern], 6 | lastIndex: Int = 0) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpattern/PatternUtils.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpattern 2 | 3 | import org.openhorizon.exchangeapi.table.deploymentpattern.PServices 4 | import org.openhorizon.exchangeapi.utility.{ExchMsg, Version} 5 | 6 | object PatternUtils { 7 | def validatePatternServices(services: List[PServices]): Option[String] = { 8 | // Check that it is signed and check the version syntax 9 | for (s <- services) { 10 | if (s.serviceVersions.isEmpty) return Option(ExchMsg.translate("no.version.specified.for.service", s.serviceOrgid, s.serviceUrl, s.serviceArch)) 11 | for (sv <- s.serviceVersions) { 12 | if (!Version(sv.version).isValid) return Option(ExchMsg.translate("version.not.valid.format", sv.version)) 13 | if (sv.deployment_overrides.getOrElse("") != "" && sv.deployment_overrides_signature.getOrElse("") == "") { 14 | return Option(ExchMsg.translate("pattern.definition.not.signed")) 15 | } 16 | } 17 | } 18 | None 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpattern/PostPatternSearchRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpattern 2 | 3 | /** 4 | * Input for pattern-based search for nodes to make agreements with. 5 | * 6 | * Pattern does not use changedSince like policy search because pattern agreements either exist 7 | * or they do not. Pattern agreements are not time-boxed. 8 | **/ 9 | final case class PostPatternSearchRequest(arch: Option[String], 10 | nodeOrgids: Option[List[String]], 11 | numEntries: Option[String] = None, // Not used. 12 | secondsStale: Option[Int], 13 | serviceUrl: String = "", 14 | startIndex: Option[String] = None) 15 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpattern/PutPatternKeyRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpattern 2 | 3 | import org.openhorizon.exchangeapi.table.deploymentpattern.key.{PatternKey, PatternKeyRow} 4 | import org.openhorizon.exchangeapi.utility.ApiTime 5 | 6 | final case class PutPatternKeyRequest(key: String) { 7 | require(key!=null) 8 | def toPatternKey: PatternKey = PatternKey(key, ApiTime.nowUTC) 9 | def toPatternKeyRow(patternId: String, keyId: String): PatternKeyRow = PatternKeyRow(keyId, patternId, key, ApiTime.nowUTC) 10 | def getAnyProblem: Option[String] = None 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpolicy/BusinessPolicyNodeResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpolicy 2 | 3 | final case class BusinessPolicyNodeResponse(id: String, 4 | nodeType: String, 5 | publicKey: String) 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpolicy/BusinessPolicySearchHashElement.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpolicy 2 | 3 | final case class BusinessPolicySearchHashElement(nodeType: String, 4 | publicKey: String, 5 | noAgreementYet: Boolean) 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpolicy/BusinessUtils.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpolicy 2 | 3 | import org.openhorizon.exchangeapi.table.deploymentpolicy.BService 4 | import org.openhorizon.exchangeapi.utility.{ExchMsg, Version} 5 | 6 | object BusinessUtils { 7 | def getAnyProblem(service: BService): Option[String] = { 8 | // Ensure the references to the service are not null 9 | if (service.name==null || service.org==null || service.arch==null) return Option(ExchMsg.translate("no.service.ref.specified.for.service")) 10 | // Check they specified at least 1 service version 11 | if (service.serviceVersions==null || service.serviceVersions.isEmpty) return Option(ExchMsg.translate("no.version.specified.for.service2")) 12 | // Check the version syntax 13 | for (sv <- service.serviceVersions) { 14 | if (!Version(sv.version).isValid) return Option(ExchMsg.translate("version.not.valid.format", sv.version)) 15 | } 16 | None 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpolicy/GetBusinessPoliciesResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpolicy 2 | 3 | import org.openhorizon.exchangeapi.table.deploymentpolicy.BusinessPolicy 4 | 5 | final case class GetBusinessPoliciesResponse(businessPolicy: Map[String, BusinessPolicy] = Map.empty[String, BusinessPolicy], 6 | lastIndex: Int = 0) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpolicy/GetBusinessPolicyAttributeResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpolicy 2 | 3 | final case class GetBusinessPolicyAttributeResponse(attribute: String, 4 | value: String) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpolicy/PolicySearchResponseDesync.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpolicy 2 | 3 | final case class PolicySearchResponseDesync(agbot: String, 4 | offset: Option[String], 5 | session: Option[String]) extends Throwable 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpolicy/PostBusinessPolicySearchRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpolicy 2 | 3 | final case class PostBusinessPolicySearchRequest(changedSince: Long = 0L, 4 | nodeOrgids: Option[List[String]] = None, 5 | numEntries: Option[Int] = None, 6 | session: Option[String] = None, 7 | startIndex: Option[String] = None) 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/deploymentpolicy/PostBusinessPolicySearchResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.deploymentpolicy 2 | 3 | final case class PostBusinessPolicySearchResponse(nodes: List[BusinessPolicyNodeResponse], 4 | offsetUpdated: Boolean = false) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/managementpolicy/GetManagementPoliciesResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.managementpolicy 2 | 3 | import org.openhorizon.exchangeapi.table.managementpolicy.ManagementPolicy 4 | 5 | final case class GetManagementPoliciesResponse(managementPolicy: Map[String, ManagementPolicy] = Map.empty[String, ManagementPolicy], 6 | lastIndex: Int = 0) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/managementpolicy/GetManagementPolicyAttributeResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.managementpolicy 2 | 3 | final case class GetManagementPolicyAttributeResponse(attribute: String, 4 | value: String) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/GetNodeAgreementsResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | import org.openhorizon.exchangeapi.table.node.agreement.NodeAgreement 4 | 5 | /** Output format for GET /orgs/{organization}/nodes/{node}/agreements */ 6 | final case class GetNodeAgreementsResponse(agreements: Map[String,NodeAgreement], lastIndex: Int = 0) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/GetNodeAttributeResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | final case class GetNodeAttributeResponse(attribute: String, 4 | value: String) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/GetNodeMsgsResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | import org.openhorizon.exchangeapi.table.node.message.NodeMsg 4 | 5 | /** Response for GET /orgs/{organization}/nodes/{node}/msgs */ 6 | final case class GetNodeMsgsResponse(messages: List[NodeMsg], lastIndex: Int = 0) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/GetNodesResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | import org.openhorizon.exchangeapi.table.node.Node 4 | 5 | /** Output format for GET /orgs/{organization}/nodes */ 6 | final case class GetNodesResponse(nodes: Map[String,Node], lastIndex: Int = 0) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/GetNodesUtils.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | import org.openhorizon.exchangeapi.table.node.NodeType 4 | import org.openhorizon.exchangeapi.utility.ExchMsg 5 | 6 | object GetNodesUtils { 7 | def getNodesProblem(nodetype: Option[String]): Option[String] = { 8 | if (nodetype.isDefined && !NodeType.containsString(nodetype.get.toLowerCase)) return Option(ExchMsg.translate("invalid.node.type2", NodeType.valuesAsString)) 9 | None 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/NodeMangementPolicyStatus.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | final case class NodeMangementPolicyStatus(scheduledTime: String, 4 | startTime: Option[String], 5 | endTime: Option[String], 6 | upgradedVersions: Option[UpgradedVersions], 7 | status: Option[String], 8 | errorMessage: Option[String]) 9 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/NodeResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | import org.openhorizon.exchangeapi.table.deploymentpattern.OneUserInputService 4 | import org.openhorizon.exchangeapi.table.node.RegService 5 | 6 | final case class NodeResponse(id: String, 7 | name: String, 8 | services: List[RegService], 9 | userInput: List[OneUserInputService], 10 | msgEndPoint: String, 11 | publicKey: String, 12 | arch: String, 13 | clusterNamespace: String, 14 | isNamespaceScoped: Boolean = false) 15 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/PatternNodeResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | final case class PatternNodeResponse(id: String, nodeType: String, publicKey: String) 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/PatternSearchHashElement.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | // Tried this to have names on the tuple returned from the db, but didn't work... 4 | final case class PatternSearchHashElement(nodeType: String, publicKey: String, noAgreementYet: Boolean) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/PostNodeErrorRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | // Leaving this here for the UI wanting to implement filtering later 4 | final case class PostNodeErrorRequest() { 5 | def getAnyProblem: Option[String] = None 6 | } 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/PostNodeErrorResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | final case class PostNodeErrorResponse(nodes: Seq[String]) 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/PostNodesMsgsRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | /** Input body for POST /orgs/{organization}/nodes/{node}/msgs */ 4 | final case class PostNodesMsgsRequest(message: String, ttl: Int) { 5 | require(message!=null) 6 | } 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/PostPatternSearchResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | final case class PostPatternSearchResponse(nodes: List[PatternNodeResponse], lastIndex: Int) 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/PostSearchNodesResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | final case class PostSearchNodesResponse(nodes: List[NodeResponse], lastIndex: Int) 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/PostServiceSearchRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | /** Input body for POST /orgs/{organization}/search/nodes/service -- now in OrgsRoutes */ 4 | final case class PostServiceSearchRequest(orgid: String, serviceURL: String, serviceVersion: String, serviceArch: String) { 5 | require(orgid!=null && serviceURL!=null && serviceVersion!=null && serviceArch!=null) 6 | def getAnyProblem: Option[String] = None 7 | } 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/PostServiceSearchResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | final case class PostServiceSearchResponse(nodes: scala.collection.Seq[(String, Option[String])]) 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/PutNodeErrorRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | import io.swagger.v3.oas.annotations.media.{ArraySchema, Schema} 4 | import org.json4s.jackson.Serialization.write 5 | import org.json4s.{DefaultFormats, Formats} 6 | import org.openhorizon.exchangeapi.table.node.error.NodeErrorRow 7 | import org.openhorizon.exchangeapi.utility.ApiTime 8 | 9 | /** Input body for PUT /orgs/{organization}/nodes/{node}/errors */ 10 | final case class PutNodeErrorRequest(@ArraySchema(schema = new Schema(implementation = classOf[Object])) errors: List[Any]) { 11 | require(errors!=null) 12 | protected implicit val jsonFormats: Formats = DefaultFormats 13 | def getAnyProblem: Option[String] = None 14 | 15 | def toNodeErrorRow(nodeId: String): NodeErrorRow = NodeErrorRow(nodeId, write(errors), ApiTime.nowUTC) 16 | } 17 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/PutNodeMgmtPolStatusRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | final case class PutNodeMgmtPolStatusRequest(agentUpgradePolicyStatus: NodeMangementPolicyStatus) 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/PutNodeStatusRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | import io.swagger.v3.oas.annotations.media.{ArraySchema, Schema} 4 | import org.json4s.jackson.Serialization.write 5 | import org.json4s.{DefaultFormats, Formats} 6 | import org.openhorizon.exchangeapi.table.node.OneService 7 | import org.openhorizon.exchangeapi.table.node.status.NodeStatusRow 8 | import org.openhorizon.exchangeapi.utility.ApiTime 9 | 10 | /** Input body for PUT /orgs/{organization}/nodes/{node}/status */ 11 | final case class PutNodeStatusRequest(connectivity: Option[Map[String,Boolean]], services: List[OneService]) { 12 | require(connectivity!=null && services!=null) 13 | protected implicit val jsonFormats: Formats = DefaultFormats 14 | def getAnyProblem: Option[String] = None 15 | var runningServices = "|" 16 | for(s <- services){ 17 | runningServices = runningServices + s.orgid + "/" + s.serviceUrl + "_" + s.version + "_" + s.arch + "|" 18 | } 19 | def toNodeStatusRow(nodeId: String): NodeStatusRow = NodeStatusRow(nodeId, write(connectivity), write(services), runningServices, ApiTime.nowUTC) 20 | } 21 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/node/UpgradedVersions.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.node 2 | 3 | final case class UpgradedVersions(softwareVersion: Option[String], 4 | certVersion: Option[String], 5 | configVersion: Option[String]) 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/nodegroup/GetNodeGroupsResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.nodegroup 2 | 3 | final case class GetNodeGroupsResponse(nodeGroups: Seq[NodeGroupResp]) 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/nodegroup/NodeGroupResp.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.nodegroup 2 | 3 | final case class NodeGroupResp(name: String, 4 | description: String = "", 5 | members: Seq[String], 6 | admin: Boolean, 7 | lastUpdated: String) 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/nodegroup/PutNodeGroupsRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.nodegroup 2 | 3 | final case class PutNodeGroupsRequest(members: Option[Seq[String]], 4 | description: Option[String]) { 5 | def getAnyProblem: Option[String] = None 6 | } 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/AllNodeErrorsInOrgResp.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | 4 | final case class AllNodeErrorsInOrgResp(nodeErrors: Seq[NodeErrorsResp]) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/ChangeEntry.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | import scala.collection.mutable.ListBuffer 4 | 5 | final case class ChangeEntry(orgId: String, 6 | var resource: String, 7 | id: String, 8 | var operation: String, 9 | resourceChanges: ListBuffer[ResourceChangesInnerObject]){ 10 | def addToResourceChanges(innerObject: ResourceChangesInnerObject): ListBuffer[ResourceChangesInnerObject] = { this.resourceChanges += innerObject} 11 | def setOperation(newOp: String): Unit = {this.operation = newOp} 12 | def setResource(newResource: String): Unit = {this.resource = newResource} 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/GetMyOrgsRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | import org.openhorizon.exchangeapi.auth.cloud.IamAccountInfo 4 | 5 | final case class GetMyOrgsRequest(accounts: List[IamAccountInfo]) { 6 | def getAnyProblem: Option[String] = None 7 | } 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/GetOrgAttributeResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | final case class GetOrgAttributeResponse(attribute: String, 4 | value: String) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/GetOrgStatusResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | final case class GetOrgStatusResponse(msg: String, 4 | numberOfUsers: Int, 5 | numberOfNodes: Int, 6 | numberOfNodeAgreements: Int, 7 | numberOfRegisteredNodes: Int, 8 | numberOfNodeMsgs: Int, 9 | SchemaVersion: Int) 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/GetOrgsResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | import org.openhorizon.exchangeapi.table.organization.Org 4 | 5 | final case class GetOrgsResponse(orgs: Map[String, Org] = Map.empty[String, Org], 6 | lastIndex: Int = 0) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/MaxChangeIdResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | final case class MaxChangeIdResponse(maxChangeId: Long) 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/NodeErrorsResp.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | final case class NodeErrorsResp(nodeId: String, 4 | error: String, 5 | lastUpdated: String) 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/NodeHealthAgreementElement.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | final case class NodeHealthAgreementElement(lastUpdated: String) 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/NodeHealthHashElement.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | class NodeHealthHashElement(var lastHeartbeat: Option[String], 4 | var agreements: Map[String, NodeHealthAgreementElement]) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/PostNodeHealthRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | final case class PostNodeHealthRequest(lastTime: String, 4 | nodeOrgids: Option[List[String]]) { 5 | require(lastTime!=null) 6 | def getAnyProblem: Option[String] = None 7 | } 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/PostNodeHealthResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | final case class PostNodeHealthResponse(nodes: Map[String, NodeHealthHashElement]) 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/ResourceChangesInnerObject.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | final case class ResourceChangesInnerObject(changeId: Long, 4 | lastUpdated: String) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/ResourceChangesRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | import org.openhorizon.exchangeapi.utility.{ApiTime, ExchMsg} 4 | 5 | import java.time.ZonedDateTime 6 | import java.time.format.DateTimeParseException 7 | 8 | final case class ResourceChangesRequest(changeId: Long, 9 | lastUpdated: Option[String], 10 | maxRecords: Int, 11 | orgList: Option[List[String]]) { 12 | def getAnyProblem: Option[String] = { 13 | try { 14 | ZonedDateTime.parse(lastUpdated.getOrElse(ApiTime.beginningUTC)) //if lastUpdated is provided, make sure we can parse it 15 | None //if the parse was successful, no problem 16 | } 17 | catch { 18 | case _: DateTimeParseException => Some.apply(ExchMsg.translate("error.parsing.timestamp", lastUpdated.get)) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/organization/ResourceChangesRespObject.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.organization 2 | 3 | final case class ResourceChangesRespObject(changes: List[ChangeEntry], 4 | mostRecentChangeId: Long, 5 | hitMaxRecords: Boolean, 6 | exchangeVersion: String) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/service/GetServiceAttributeResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.service 2 | 3 | case class GetServiceAttributeResponse(attribute: String, 4 | value: String) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/service/GetServicesResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.service 2 | 3 | import org.openhorizon.exchangeapi.table.service.Service 4 | 5 | final case class GetServicesResponse(services: Map[String, Service] = Map.empty[String, Service], 6 | lastIndex: Int = 0) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/service/PutServiceKeyRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.service 2 | 3 | import org.openhorizon.exchangeapi.table.service.key.{ServiceKey, ServiceKeyRow} 4 | import org.openhorizon.exchangeapi.utility.ApiTime 5 | 6 | final case class PutServiceKeyRequest(key: String) { 7 | require(key!=null) 8 | def toServiceKey: ServiceKey = ServiceKey(key, ApiTime.nowUTC) 9 | def toServiceKeyRow(serviceId: String, keyId: String): ServiceKeyRow = ServiceKeyRow(keyId, serviceId, key, ApiTime.nowUTC) 10 | def getAnyProblem: Option[String] = None 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/service/SharableVals.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.service 2 | 3 | object SharableVals extends Enumeration { 4 | type SharableVals = Value 5 | val EXCLUSIVE: Value = Value("exclusive") 6 | val SINGLE: Value = Value("single") // this is being replaced by singleton 7 | val SINGLETON: Value = Value("singleton") 8 | val MULTIPLE: Value = Value("multiple") 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/user/ChangePwRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.user 2 | 3 | import org.openhorizon.exchangeapi.table.user.UsersTQ 4 | import org.openhorizon.exchangeapi.utility.{ApiTime, ExchMsg} 5 | import slick.dbio.DBIO 6 | import slick.jdbc.PostgresProfile.api._ 7 | 8 | final case class ChangePwRequest(newPassword: String) { 9 | require(newPassword!=null) 10 | def getAnyProblem: Option[String] = { 11 | if (newPassword == "") Option(ExchMsg.translate("password.cannot.be.set.to.empty.string")) 12 | else None // None means no problems with input 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/user/GetUsersResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.user 2 | 3 | import org.openhorizon.exchangeapi.table.user.User 4 | 5 | final case class GetUsersResponse(users: Map[String, User] = Map.empty[String, User], 6 | lastIndex: Int = 0) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/user/PatchUsersRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.user 2 | 3 | import org.json4s.{DefaultFormats, Formats} 4 | import org.openhorizon.exchangeapi.auth.Identity 5 | import org.openhorizon.exchangeapi.table.user.UsersTQ 6 | import org.openhorizon.exchangeapi.utility.{ApiTime, ExchMsg} 7 | import slick.dbio.DBIO 8 | import slick.jdbc.PostgresProfile.api._ 9 | 10 | final case class PatchUsersRequest(password: Option[String] = None, 11 | admin: Option[Boolean] = None, 12 | hubAdmin: Option[Boolean] = None, 13 | email: Option[String] = None) 14 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/route/user/PostPutUsersRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.user 2 | 3 | import org.openhorizon.exchangeapi.auth.Identity 4 | import org.openhorizon.exchangeapi.utility.ExchMsg 5 | 6 | final case class PostPutUsersRequest(password: String = "", 7 | admin: Boolean = false, 8 | hubAdmin: Option[Boolean] = None, 9 | email: String) 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agent/AgentVersions.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agent 2 | 3 | trait AgentVersions { 4 | def agentCertVersions: Seq[String] 5 | def agentConfigVersions: Seq[String] 6 | def agentSoftwareVersions: Seq[String] 7 | } 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agent/AgentVersionsChanged.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agent 2 | 3 | import org.openhorizon.exchangeapi.table.organization.OrgsTQ 4 | import slick.jdbc.PostgresProfile.api._ 5 | import slick.model.ForeignKeyAction 6 | 7 | class AgentVersionsChanged(tag: Tag) extends Table[(java.sql.Timestamp, String)](tag, "agent_version_last_updated") { 8 | def changed = column[java.sql.Timestamp]("changed") 9 | def organization = column[String]("organization", O.PrimaryKey, O.Default("IBM")) 10 | 11 | def * = (changed, organization) 12 | def fkOrg = foreignKey("fk_org", organization, OrgsTQ)(_.orgid, onUpdate=ForeignKeyAction.Cascade, onDelete=ForeignKeyAction.Cascade) 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agent/AgentVersionsChangedTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agent 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.{Rep, TableQuery} 5 | 6 | import java.sql.Timestamp 7 | 8 | object AgentVersionsChangedTQ extends TableQuery(new AgentVersionsChanged(_)) { 9 | def getChanged(organization: String): Query[Rep[Timestamp], Timestamp, Seq] = this.filter(_.organization === organization).map(_.changed) 10 | } 11 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agent/AgentVersionsRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agent 2 | 3 | final case class AgentVersionsRequest(agentCertVersions: Seq[String], 4 | agentConfigVersions: Seq[String], 5 | agentSoftwareVersions: Seq[String]) extends AgentVersions 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agent/AgentVersionsResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agent 2 | 3 | final case class AgentVersionsResponse(agentCertVersions: Seq[String], 4 | agentConfigVersions: Seq[String], 5 | agentSoftwareVersions: Seq[String], 6 | lastUpdated: String) extends AgentVersions 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agent/certificate/AgentCertificateVersions.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agent.certificate 2 | 3 | import org.openhorizon.exchangeapi.table.organization.OrgsTQ 4 | import slick.jdbc.PostgresProfile.api._ 5 | 6 | 7 | class AgentCertificateVersions(tag: Tag) extends Table[(String, String, Option[Long])](tag, "agent_version_certificate") { 8 | def certificateVersion = column[String]("version") 9 | def organization = column[String]("organization", O.Default("IBM")) 10 | def priority = column[Option[Long]]("priority") 11 | 12 | def * = (certificateVersion, organization, priority) 13 | def pkAgentVerCert = primaryKey("pk_agent_version_certificate", (organization, certificateVersion)) 14 | def fkOrg = foreignKey("fk_organization", organization, OrgsTQ)(_.orgid, onUpdate=ForeignKeyAction.Cascade, onDelete=ForeignKeyAction.Cascade) 15 | def idxPriority = index("idx_avcert_priority", (organization, priority), unique = true) 16 | } 17 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agent/certificate/AgentCertificateVersionsTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agent.certificate 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.{Rep, TableQuery} 5 | 6 | 7 | object AgentCertificateVersionsTQ extends TableQuery(new AgentCertificateVersions(_)) { 8 | def getAgentCertificateVersions(organization: String): Query[Rep[String], String, Seq] = this.filter(_.organization === organization).map(_.certificateVersion) 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agent/configuration/AgentConfigurationVersions.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agent.configuration 2 | 3 | import org.openhorizon.exchangeapi.table.organization.OrgsTQ 4 | import slick.jdbc.PostgresProfile.api._ 5 | import slick.model.ForeignKeyAction 6 | 7 | 8 | class AgentConfigurationVersions(tag: Tag) extends Table[(String, String, Option[Long])](tag, "agent_version_configuration") { 9 | def configurationVersion = column[String]("version") 10 | def organization = column[String]("organization", O.Default("IBM")) 11 | def priority = column[Option[Long]]("priority") 12 | 13 | def * = (configurationVersion, organization, priority) 14 | def pkAgentVerConfig = primaryKey("pk_agent_version_configuration", (organization, configurationVersion)) 15 | def fkOrg = foreignKey("fk_organization", organization, OrgsTQ)(_.orgid, onUpdate=ForeignKeyAction.Cascade, onDelete=ForeignKeyAction.Cascade) 16 | def idxPriority = index("idx_avconfig_priority", (organization, priority), unique = true) 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agent/configuration/AgentConfigurationVersionsTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agent.configuration 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.{Rep, TableQuery} 5 | 6 | 7 | object AgentConfigurationVersionsTQ extends TableQuery(new AgentConfigurationVersions(_)) { 8 | def getAgentConfigurationVersions(organization: String): Query[Rep[String], String, Seq] = this.filter(_.organization === organization).map(_.configurationVersion) 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agent/software/AgentSoftwareVersions.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agent.software 2 | 3 | import org.openhorizon.exchangeapi.table.organization.OrgsTQ 4 | import slick.jdbc.PostgresProfile.api._ 5 | 6 | class AgentSoftwareVersions(tag: Tag) extends Table[(String, String, Option[Long])](tag, "agent_version_software") { 7 | def organization = column[String]("organization", O.Default("IBM")) 8 | def softwareVersion = column[String]("version") 9 | def priority = column[Option[Long]]("priority") 10 | 11 | def * = (organization, softwareVersion, priority) 12 | def pkAgentVerSoft = primaryKey("pk_agent_version_software", (organization, softwareVersion)) 13 | def fkOrg = foreignKey("fk_organization", organization, OrgsTQ)(_.orgid, onUpdate=ForeignKeyAction.Cascade, onDelete=ForeignKeyAction.Cascade) 14 | def idxPriority = index("idx_avsoft_priority", (organization, priority), unique = true) 15 | } 16 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agent/software/AgentSoftwareVersionsTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agent.software 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.{Rep, TableQuery} 5 | 6 | 7 | object AgentSoftwareVersionsTQ extends TableQuery(new AgentSoftwareVersions(_)) { 8 | def getAgentSoftwareVersions(organization: String): Query[Rep[String], String, Seq] = this.filter(_.organization === organization).map(_.softwareVersion) 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/AAService.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot 2 | 3 | final case class AAService(orgid: String, 4 | pattern: String, 5 | url: String) 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/AAWorkload.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot 2 | 3 | final case class AAWorkload(orgid: String, 4 | pattern: String, 5 | url: String) 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/Agbot.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot 2 | 3 | // This is the agbot table minus the key - used as the data structure to return to the REST clients 4 | case class Agbot(id: String, 5 | lastHeartbeat: String, 6 | msgEndPoint: String, 7 | name: String, 8 | orgid: String, 9 | owner: String, 10 | publicKey: String, 11 | token: String = "***************") { 12 | def this(tuple: (String, String, String, String, String, String, String)) = 13 | this(id = tuple._1, 14 | lastHeartbeat = tuple._2, 15 | msgEndPoint = tuple._3, 16 | name = tuple._4, 17 | orgid = tuple._5, 18 | owner = tuple._6, 19 | publicKey = tuple._7) 20 | } 21 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/agreement/AgbotAgreement.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot.agreement 2 | 3 | import org.openhorizon.exchangeapi.table.agreementbot.AAService 4 | 5 | 6 | final case class AgbotAgreement(service: AAService, 7 | state: String, 8 | lastUpdated: String, 9 | dataLastReceived: String) 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/agreement/AgbotAgreementRow.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot.agreement 2 | 3 | import org.openhorizon.exchangeapi.table.agreementbot.AAService 4 | import slick.dbio.DBIO 5 | import slick.jdbc.PostgresProfile.api._ 6 | 7 | 8 | final case class AgbotAgreementRow(agrId: String, agbotId: String, serviceOrgid: String, servicePattern: String, serviceUrl: String, state: String, lastUpdated: String, dataLastReceived: String) { 9 | def toAgbotAgreement: AgbotAgreement = AgbotAgreement(AAService(serviceOrgid, servicePattern, serviceUrl), state, lastUpdated, dataLastReceived) 10 | 11 | def upsert: DBIO[_] = AgbotAgreementsTQ.insertOrUpdate(this) 12 | } 13 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/agreement/AgbotAgreementsTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot.agreement 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.{Rep, TableQuery} 5 | 6 | 7 | object AgbotAgreementsTQ extends TableQuery(new AgbotAgreements(_)) { 8 | def getAgreements(agbotId: String): Query[AgbotAgreements, AgbotAgreementRow, Seq] = this.filter(_.agbotId === agbotId) 9 | 10 | def getAgreement(agbotId: String, agrId: String): Query[AgbotAgreements, AgbotAgreementRow, Seq] = this.filter(r => { 11 | r.agbotId === agbotId && r.agrId === agrId 12 | }) 13 | 14 | def getNumOwned(agbotId: String): Rep[Int] = this.filter(_.agbotId === agbotId).length 15 | 16 | def getAgreementsWithState = this.filter(_.state =!= "") 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/deploymentpattern/AgbotPattern.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot.deploymentpattern 2 | 3 | final case class AgbotPattern(patternOrgid: String, 4 | pattern: String, 5 | nodeOrgid: String, 6 | lastUpdated: String) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/deploymentpattern/AgbotPatternRow.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot.deploymentpattern 2 | 3 | import slick.dbio.DBIO 4 | import slick.jdbc.PostgresProfile.api._ 5 | 6 | 7 | final case class AgbotPatternRow(patId: String, 8 | agbotId: String, 9 | patternOrgid: String, 10 | pattern: String, 11 | nodeOrgid: String, 12 | lastUpdated: String) { 13 | def toAgbotPattern: AgbotPattern = AgbotPattern(patternOrgid, pattern, nodeOrgid, lastUpdated) 14 | 15 | def upsert: DBIO[_] = AgbotPatternsTQ.insertOrUpdate(this) 16 | def insert: DBIO[_] = AgbotPatternsTQ += this 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/deploymentpattern/AgbotPatternsTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot.deploymentpattern 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.TableQuery 5 | 6 | 7 | object AgbotPatternsTQ extends TableQuery(new AgbotPatterns(_)) { 8 | def getPatterns(agbotId: String): Query[AgbotPatterns, AgbotPatternRow, Seq] = this.filter(_.agbotId === agbotId) 9 | def getPattern(agbotId: String, patId: String): Query[AgbotPatterns, AgbotPatternRow, Seq] = this.filter(r => {r.agbotId === agbotId && r.patId === patId} ) 10 | } 11 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/deploymentpolicy/AgbotBusinessPol.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot.deploymentpolicy 2 | 3 | final case class AgbotBusinessPol(businessPolOrgid: String, 4 | businessPol: String, 5 | nodeOrgid: String, 6 | lastUpdated: String) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/deploymentpolicy/AgbotBusinessPolRow.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot.deploymentpolicy 2 | 3 | import slick.dbio.DBIO 4 | import slick.jdbc.PostgresProfile.api._ 5 | 6 | final case class AgbotBusinessPolRow(busPolId: String, 7 | agbotId: String, 8 | businessPolOrgid: String, 9 | businessPol: String, 10 | nodeOrgid: String, 11 | lastUpdated: String) { 12 | def toAgbotBusinessPol: AgbotBusinessPol = AgbotBusinessPol(businessPolOrgid, businessPol, nodeOrgid, lastUpdated) 13 | 14 | def upsert: DBIO[_] = AgbotBusinessPolsTQ.insertOrUpdate(this) 15 | 16 | def insert: DBIO[_] = AgbotBusinessPolsTQ += this 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/deploymentpolicy/AgbotBusinessPolsTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot.deploymentpolicy 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.TableQuery 5 | 6 | 7 | object AgbotBusinessPolsTQ extends TableQuery(new AgbotBusinessPols(_)) { 8 | def getBusinessPols(agbotId: String): Query[AgbotBusinessPols, AgbotBusinessPolRow, Seq] = this.filter(_.agbotId === agbotId) 9 | 10 | def getBusinessPol(agbotId: String, busPolId: String): Query[AgbotBusinessPols, AgbotBusinessPolRow, Seq] = this.filter(r => { 11 | r.agbotId === agbotId && r.busPolId === busPolId 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/message/AgbotMsg.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot.message 2 | 3 | final case class AgbotMsg(msgId: Int, 4 | nodeId: String, 5 | nodePubKey: String, 6 | message: String, 7 | timeSent: String, 8 | timeExpires: String) 9 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/message/AgbotMsgRow.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot.message 2 | 3 | import slick.dbio.DBIO 4 | import slick.jdbc.PostgresProfile.api._ 5 | 6 | 7 | /** The agbotmsgs table holds the msgs sent to agbots by nodes */ 8 | final case class AgbotMsgRow(msgId: Int, agbotId: String, nodeId: String, nodePubKey: String, message: String, timeSent: String, timeExpires: String) { 9 | def toAgbotMsg: AgbotMsg = AgbotMsg(msgId, nodeId, nodePubKey, message, timeSent, timeExpires) 10 | 11 | def insert: DBIO[_] = ((AgbotMsgsTQ returning AgbotMsgsTQ.map(_.msgId)) += this) // inserts the row and returns the msgId of the new row 12 | 13 | def upsert: DBIO[_] = AgbotMsgsTQ.insertOrUpdate(this) // do not think we need this 14 | } 15 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/agreementbot/message/AgbotMsgsTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.agreementbot.message 2 | 3 | import org.openhorizon.exchangeapi.utility.ApiTime 4 | import slick.jdbc.PostgresProfile.api._ 5 | import slick.lifted.{Rep, TableQuery} 6 | 7 | 8 | object AgbotMsgsTQ extends TableQuery(new AgbotMsgs(_)) { 9 | def getMsgs(agbotId: String): Query[AgbotMsgs, AgbotMsgRow, Seq] = this.filter(_.agbotId === agbotId) // this is that agbots msg mailbox 10 | def getMsg(agbotId: String, msgId: Int): Query[AgbotMsgs, AgbotMsgRow, Seq] = this.filter(r => { 11 | r.agbotId === agbotId && r.msgId === msgId 12 | }) 13 | def getMsgsExpired = this.filter(_.timeExpires < ApiTime.nowUTC) 14 | def getNumOwned(agbotId: String): Rep[Int] = this.filter(_.agbotId === agbotId).length 15 | } 16 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpattern/OneSecretBindingService.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpattern 2 | 3 | final case class OneSecretBindingService(serviceOrgid: String, 4 | serviceUrl: String, 5 | serviceArch: Option[String], 6 | serviceVersionRange: Option[String], 7 | secrets: List[Map[String, String]], 8 | enableNodeLevelSecrets: Option[Boolean] = Option(false)) 9 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpattern/OneUserInputService.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpattern 2 | 3 | final case class OneUserInputService(serviceOrgid: String, 4 | serviceUrl: String, 5 | serviceArch: Option[String], 6 | serviceVersionRange: Option[String], 7 | inputs: List[OneUserInputValue]) 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpattern/OneUserInputValue.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpattern 2 | 3 | final case class OneUserInputValue(name: String, 4 | value: Any) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpattern/PDataVerification.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpattern 2 | 3 | final case class PDataVerification(enabled: Boolean, 4 | URL: String, 5 | user: String, 6 | password: String, 7 | interval: Int, 8 | check_rate: Int, 9 | metering: Map[String,Any]) 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpattern/PServiceVersions.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpattern 2 | 3 | final case class PServiceVersions(version: String, 4 | deployment_overrides: Option[String], 5 | deployment_overrides_signature: Option[String], 6 | priority: Option[Map[String,Int]], 7 | upgradePolicy: Option[Map[String,String]]) 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpattern/PServices.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpattern 2 | 3 | final case class PServices(serviceUrl: String, 4 | serviceOrgid: String, 5 | serviceArch: String, 6 | agreementLess: Option[Boolean], 7 | serviceVersions: List[PServiceVersions], 8 | dataVerification: Option[Map[String,Any]], 9 | nodeHealth: Option[Map[String,Int]]) 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpattern/key/PatternKey.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpattern.key 2 | 3 | final case class PatternKey(key: String, 4 | lastUpdated: String) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpattern/key/PatternKeyRow.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpattern.key 2 | 3 | import slick.dbio.DBIO 4 | import slick.jdbc.PostgresProfile.api._ 5 | 6 | final case class PatternKeyRow(keyId: String, 7 | patternId: String, 8 | key: String, 9 | lastUpdated: String) { 10 | def toPatternKey: PatternKey = PatternKey(key, lastUpdated) 11 | 12 | def upsert: DBIO[_] = PatternKeysTQ.insertOrUpdate(this) 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpattern/key/PatternKeys.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpattern.key 2 | 3 | import org.openhorizon.exchangeapi.table.deploymentpattern.PatternsTQ 4 | import slick.jdbc.PostgresProfile.api._ 5 | import slick.model.ForeignKeyAction 6 | 7 | class PatternKeys(tag: Tag) extends Table[PatternKeyRow](tag, "patternkeys") { 8 | def keyId = column[String]("keyid") // key - the key name 9 | def patternId = column[String]("patternid") // additional key - the composite orgid/patternid 10 | def key = column[String]("key") // the actual key content 11 | def lastUpdated = column[String]("lastupdated") 12 | 13 | def * = (keyId, patternId, key, lastUpdated).<>(PatternKeyRow.tupled, PatternKeyRow.unapply) 14 | 15 | def primKey = primaryKey("pk_ptk", (keyId, patternId)) 16 | def pattern = foreignKey("pattern_fk", patternId, PatternsTQ)(_.pattern, onUpdate=ForeignKeyAction.Cascade, onDelete=ForeignKeyAction.Cascade) 17 | def idx_deploy_pattern_keys_fk_patterns = index(name = "idx_deploy_pattern_keys_fk_patterns", on = patternId, unique = false) 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpattern/key/PatternKeysTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpattern.key 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.TableQuery 5 | 6 | object PatternKeysTQ extends TableQuery(new PatternKeys(_)) { 7 | def getKeys(patternId: String): Query[PatternKeys, PatternKeyRow, Seq] = this.filter(_.patternId === patternId) 8 | def getKey(patternId: String, keyId: String): Query[PatternKeys, PatternKeyRow, Seq] = this.filter(r => {r.patternId === patternId && r.keyId === keyId} ) 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpolicy/BService.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpolicy 2 | 3 | final case class BService(name: String, 4 | org: String, 5 | arch: String, 6 | serviceVersions: List[BServiceVersions], 7 | nodeHealth: Option[Map[String,Int]], 8 | clusterNamespace: Option[String] = None) 9 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpolicy/BServiceVersions.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpolicy 2 | 3 | final case class BServiceVersions(version: String, 4 | priority: Option[Map[String,Int]], 5 | upgradePolicy: Option[Map[String,String]]) 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpolicy/search/SearchOffsetPolicyAttributes.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpolicy.search 2 | 3 | final case class SearchOffsetPolicyAttributes(agbot: String, 4 | offset: Option[String] = None, 5 | policy: String, 6 | session: Option[String] = None) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/deploymentpolicy/search/SearchOffsetPolicyTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.deploymentpolicy.search 2 | 3 | import slick.dbio.{Effect, NoStream} 4 | import slick.jdbc.PostgresProfile.api._ 5 | import slick.lifted.{Rep, TableQuery} 6 | import slick.sql.FixedSqlAction 7 | 8 | object SearchOffsetPolicyTQ extends TableQuery(new SearchOffsetPolicy(_)){ 9 | def dropAllOffsets(): FixedSqlAction[Int, NoStream, Effect.Write] = 10 | this.delete 11 | 12 | def getOffsetSession(agbot: String, policy: String): Query[(Rep[Option[String]], Rep[Option[String]]), (Option[String], Option[String]), Seq] = 13 | this 14 | .filter(_.agbot === agbot) 15 | .filter(_.policy === policy) 16 | .map(offset => (offset.offset, offset.session)) 17 | 18 | def setOffsetSession(agbot: String, offset: Option[String], policy: String, session: Option[String]): FixedSqlAction[Int, NoStream, Effect.Write] = 19 | this.insertOrUpdate(SearchOffsetPolicyAttributes(agbot, offset, policy, session)) 20 | } 21 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/managementpolicy/AgentUpgradePolicy.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.managementpolicy 2 | 3 | final case class AgentUpgradePolicy(allowDowngrade: Boolean, 4 | manifest: String) { 5 | override def clone = new AgentUpgradePolicy(allowDowngrade, manifest) 6 | } 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/ContainerStatus.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node 2 | 3 | final case class ContainerStatus(name: String, 4 | image: String, 5 | created: Int, 6 | state: String) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/NodeHeartbeatIntervals.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node 2 | 3 | final case class NodeHeartbeatIntervals(minInterval: Int, 4 | maxInterval: Int, 5 | intervalAdjustment: Int) 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/NodeType.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node 2 | 3 | object NodeType extends Enumeration { 4 | type NodeType = Value 5 | val DEVICE: NodeType.Value = Value("device") 6 | val CLUSTER: NodeType.Value = Value("cluster") 7 | def isDevice(str: String): Boolean = str == DEVICE.toString 8 | def isCluster(str: String): Boolean = str == CLUSTER.toString 9 | def containsString(str: String): Boolean = values.find(_.toString == str).orNull != null 10 | def valuesAsString: String = values.map(_.toString).mkString(", ") 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/OneService.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node 2 | 3 | import io.swagger.v3.oas.annotations.media.Schema 4 | 5 | final case class OneService(agreementId: String, 6 | serviceUrl: String, 7 | orgid: String, 8 | version: String, 9 | arch: String, 10 | containerStatus: List[ContainerStatus], 11 | @Schema(implementation = classOf[Object]) operatorStatus: Option[Any], 12 | configState: Option[String]) 13 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/Op.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node 2 | 3 | /** The valid operators for properties */ 4 | object Op { 5 | val EQUAL = "=" 6 | val GTEQUAL = ">=" 7 | val LTEQUAL = "<=" 8 | val IN = "in" 9 | val all = Set(EQUAL, GTEQUAL, LTEQUAL, IN ) 10 | def contains(s: String): Boolean = all.contains(s) 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/PropList.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node 2 | 3 | final case class PropList(args: String*) extends PropVar 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/PropType.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node 2 | 3 | // I do not think we can use actual enums in classes that get mapped to json and swagger 4 | object PropType { 5 | val STRING = "string" 6 | val LIST = "list" 7 | val VERSION = "version" 8 | val BOOLEAN = "boolean" 9 | val INT = "int" 10 | val WILDCARD = "wildcard" // means 1 side does not care what value the other side has 11 | val all = Set(STRING, LIST, VERSION, BOOLEAN, INT, WILDCARD) 12 | 13 | def contains(s: String): Boolean = all.contains(s) 14 | } 15 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/PropVar.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node 2 | 3 | abstract class PropVar 4 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/RegService.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node 2 | 3 | /** Contains the object representations of the DB tables related to nodes. */ 4 | final case class RegService(url: String, 5 | numAgreements: Int, 6 | configState: Option[String], 7 | policy: String, 8 | properties: List[Prop], 9 | version: Option[String]) 10 | extends RegServiceTrait 11 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/RegServiceSearch.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node 2 | 3 | /** 1 service in the search criteria */ 4 | final case class RegServiceSearch(url: String, 5 | properties: List[Prop]) 6 | extends RegServiceTrait 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/agreement/NAService.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.agreement 2 | 3 | final case class NAService(orgid: String, 4 | url: String) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/agreement/NAgrService.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.agreement 2 | 3 | final case class NAgrService(orgid: String, 4 | pattern: String, 5 | url: String) 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/agreement/NodeAgreement.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.agreement 2 | 3 | final case class NodeAgreement(services: List[NAService], 4 | agrService: NAgrService, 5 | state: String, 6 | lastUpdated: String) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/agreement/NodeAgreementsTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.agreement 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.{Rep, TableQuery} 5 | 6 | object NodeAgreementsTQ extends TableQuery(new NodeAgreements(_)){ 7 | def getAgreements(nodeId: String): Query[NodeAgreements, NodeAgreementRow, Seq] = this.filter(_.nodeId === nodeId) 8 | def getAgreement(nodeId: String, agId: String): Query[NodeAgreements, NodeAgreementRow, Seq] = this.filter(r => {r.nodeId === nodeId && r.agId === agId} ) 9 | def getNumOwned(nodeId: String): Rep[Int] = this.filter(_.nodeId === nodeId).length 10 | def getAgreementsWithState(orgid: String): Query[NodeAgreements, NodeAgreementRow, Seq] = this.filter(a => {(a.nodeId like orgid + "/%") && a.state =!= ""} ) 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/deploymentpolicy/NodePolicy.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.deploymentpolicy 2 | 3 | import org.openhorizon.exchangeapi.table.service.OneProperty 4 | 5 | final case class NodePolicy(label: String, 6 | description: String, 7 | properties: List[OneProperty], 8 | constraints: List[String], 9 | deployment: PropertiesAndConstraints, 10 | management: PropertiesAndConstraints, 11 | nodePolicyVersion: String, 12 | lastUpdated: String) 13 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/deploymentpolicy/NodePolicyTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.deploymentpolicy 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.TableQuery 5 | 6 | object NodePolicyTQ extends TableQuery(new NodePolicies(_)) { 7 | def getNodePolicy(nodeId: String): Query[NodePolicies, NodePolicyRow, Seq] = this.filter(_.nodeId === nodeId) 8 | } 9 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/deploymentpolicy/PropertiesAndConstraints.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.deploymentpolicy 2 | 3 | import org.openhorizon.exchangeapi.table.service.OneProperty 4 | 5 | final case class PropertiesAndConstraints(properties: Option[List[OneProperty]], 6 | constraints: Option[List[String]]) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/error/NodeError.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.error 2 | 3 | //Node Errors 4 | // We are using the type Any instead of this case class so anax and the UI can change the fields w/o our code having to change 5 | final case class NodeError(errors: List[Any], 6 | lastUpdated: String) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/error/NodeErrorRow.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.error 2 | 3 | import org.json4s.jackson.Serialization.read 4 | import org.json4s.{DefaultFormats, Formats} 5 | import slick.jdbc.PostgresProfile.api._ 6 | 7 | final case class NodeErrorRow(nodeId: String, 8 | errors: String, 9 | lastUpdated: String) { 10 | protected implicit val jsonFormats: Formats = DefaultFormats 11 | 12 | def toNodeError: NodeError = { 13 | val err: List[Any] = if (errors != "") read[List[Any]](errors) else List[Any]() 14 | NodeError(err, lastUpdated) 15 | } 16 | 17 | def upsert = NodeErrorTQ.insertOrUpdate(this) 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/error/NodeErrorTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.error 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | 5 | object NodeErrorTQ extends TableQuery(new NodeErrors(_)) { 6 | def getNodeError(nodeId: String) = this.filter(_.nodeId === nodeId) 7 | } 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/error/NodeErrors.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.error 2 | 3 | import org.openhorizon.exchangeapi.table.node.{NodeRow, Nodes, NodesTQ} 4 | import slick.jdbc.PostgresProfile.api._ 5 | import slick.lifted.{ForeignKeyQuery, ProvenShape} 6 | 7 | class NodeErrors(tag: Tag) extends Table[NodeErrorRow](tag, "nodeerror") { 8 | def nodeId = column[String]("nodeid", O.PrimaryKey) 9 | def errors = column[String]("errors") 10 | def lastUpdated = column[String]("lastUpdated") 11 | //def * = (nodeId, errors, lastUpdated) <> (NodeErrorRow.tupled, NodeErrorRow.unapply) 12 | 13 | def * : ProvenShape[NodeErrorRow] = (nodeId, errors, lastUpdated).mapTo[NodeErrorRow] 14 | 15 | def node_error_fk: ForeignKeyQuery[Nodes, NodeRow] = foreignKey("node_error_fk_nodes", nodeId, NodesTQ)(_.id, onUpdate = ForeignKeyAction.Cascade, onDelete = ForeignKeyAction.Cascade) 16 | def idx_node_error_fk_nodes = index(name = "idx_node_error_fk_nodes", on = nodeId, unique = false) 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/group/NodeGroup.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.group 2 | 3 | import org.openhorizon.exchangeapi.table.organization.OrgsTQ 4 | import slick.jdbc.PostgresProfile.api._ 5 | 6 | class NodeGroup(tag: Tag) extends Table[NodeGroupRow](tag, "node_group") { 7 | def description = column[Option[String]]("description") 8 | def group = column[Long]("group", O.AutoInc) 9 | def organization = column[String]("orgid") 10 | def lastUpdated = column[String]("lastUpdated") 11 | def name = column[String]("name") 12 | def admin = column[Boolean]("admin") 13 | //def lastUpdated = column[String]("lastUpdated") 14 | def * = (admin, description, group, organization, lastUpdated, name).<>(NodeGroupRow.tupled, NodeGroupRow.unapply) 15 | def nodeGroupIdx = index("node_group_idx", (organization, name), unique = true) 16 | def pkNodeGroup = primaryKey("pk_node_group", group) 17 | def fkOrg = foreignKey("fk_organization", organization, OrgsTQ)(_.orgid, onUpdate=ForeignKeyAction.Cascade, onDelete=ForeignKeyAction.Cascade) 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/group/NodeGroupRow.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.group 2 | 3 | import org.json4s.{DefaultFormats, Formats} 4 | import slick.dbio.DBIO 5 | import slick.jdbc.PostgresProfile.api._ 6 | 7 | //Node Groups for MCM 8 | final case class NodeGroupRow(admin: Boolean = false, 9 | description: Option[String], 10 | group: Long, 11 | organization: String, 12 | lastUpdated: String, 13 | name: String) { 14 | protected implicit val jsonFormats: Formats = DefaultFormats 15 | def update: DBIO[_] = (for { m <- NodeGroupTQ if m.group === group } yield m).update(this) 16 | def upsert: DBIO[_] = NodeGroupTQ.insertOrUpdate(this) 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/group/NodeGroupTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.group 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.{Rep, TableQuery} 5 | 6 | object NodeGroupTQ extends TableQuery(new NodeGroup(_)){ 7 | def getAllNodeGroups(orgid: String): Query[NodeGroup, NodeGroupRow, Seq] = this.filter(_.organization === orgid) 8 | def getNodeGroupId(orgid: String, name: String): Query[Rep[Long], Long, Seq] = this.filter(_.organization === orgid).filter(_.name === name).map(_.group) 9 | def getNodeGroupName(orgid: String, name: String): Query[NodeGroup, NodeGroupRow, Seq] = this.filter(_.organization === orgid).filter(_.name === name) 10 | } 11 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/group/NodeGroups.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.group 2 | 3 | final case class NodeGroups(description: String, 4 | group: String, 5 | organization: String, 6 | lastUpdated: String) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/group/assignment/NodeGroupAssignmentRow.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.group.assignment 2 | 3 | import org.json4s.{DefaultFormats, Formats} 4 | import slick.jdbc.PostgresProfile.api._ 5 | 6 | final case class NodeGroupAssignmentRow(node: String, 7 | group: Long) { 8 | protected implicit val jsonFormats: Formats = DefaultFormats 9 | def upsert = NodeGroupAssignmentTQ.insertOrUpdate(this) 10 | } 11 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/group/assignment/NodeGroupAssignmentTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.group.assignment 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.{Rep, TableQuery} 5 | 6 | object NodeGroupAssignmentTQ extends TableQuery(new NodeGroupAssignment(_)){ 7 | def getNodeGroupAssignment(node: String): Query[Rep[Long], Long, Seq] = this.filter(_.node === node).map(_.group) 8 | } 9 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/group/assignment/NodeGroupAssignments.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.group.assignment 2 | 3 | final case class NodeGroupAssignments(node: String, 4 | group: String) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/group/assignment/PostPutNodeGroupsRequest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.group.assignment 2 | 3 | import org.openhorizon.exchangeapi.table.node.group.NodeGroupRow 4 | import org.openhorizon.exchangeapi.utility.ApiTime 5 | import slick.dbio.DBIO 6 | 7 | final case class PostPutNodeGroupsRequest(description: Option[String], members: Option[Seq[String]]) { 8 | def getAnyProblem: Option[String] = None 9 | 10 | // Note: write() handles correctly the case where the optional fields are None. 11 | def getDbUpsertGroup(description: Option[String], 12 | group: Long = 0L, 13 | lastUpdated: String = ApiTime.nowUTC, 14 | name: String, 15 | orgid: String): DBIO[_] = 16 | NodeGroupRow(description = description, 17 | group = group, 18 | lastUpdated = lastUpdated, 19 | name = name, 20 | organization = orgid).upsert 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/managementpolicy/status/NMPStatus.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.managementpolicy.status 2 | 3 | case class NMPStatus(var agentUpgradePolicyStatus: PolicyStatus){ 4 | def copy = new NMPStatus(agentUpgradePolicyStatus) 5 | } 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/managementpolicy/status/PolicyStatus.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.managementpolicy.status 2 | 3 | final case class PolicyStatus(scheduledTime: String, 4 | startTime: String, 5 | endTime: String, 6 | upgradedVersions: UpgradedVersions, 7 | status: String, 8 | errorMessage: String, 9 | lastUpdated: String) 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/managementpolicy/status/UpgradedVersions.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.managementpolicy.status 2 | 3 | final case class UpgradedVersions(softwareVersion: String, 4 | certVersion: String, 5 | configVersion: String) 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/message/NodeMsg.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.message 2 | 3 | final case class NodeMsg(msgId: Int, 4 | agbotId: String, 5 | agbotPubKey: String, 6 | message: String, 7 | timeSent: String, 8 | timeExpires: String) 9 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/message/NodeMsgRow.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.message 2 | 3 | import slick.dbio.DBIO 4 | import slick.jdbc.PostgresProfile.api._ 5 | 6 | /** The nodemsgs table holds the msgs sent to nodes by agbots */ 7 | final case class NodeMsgRow(msgId: Int, 8 | nodeId: String, 9 | agbotId: String, 10 | agbotPubKey: String, 11 | message: String, 12 | timeSent: String, 13 | timeExpires: String) { 14 | def toNodeMsg: NodeMsg = NodeMsg(msgId, agbotId, agbotPubKey, message, timeSent, timeExpires) 15 | 16 | def insert: DBIO[_] = ((NodeMsgsTQ returning NodeMsgsTQ.map(_.msgId)) += this) // inserts the row and returns the msgId of the new row 17 | def upsert: DBIO[_] = NodeMsgsTQ.insertOrUpdate(this) // do not think we need this 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/message/NodeMsgsTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.message 2 | 3 | import org.openhorizon.exchangeapi.utility.ApiTime 4 | import slick.jdbc.PostgresProfile.api._ 5 | import slick.lifted.{Rep, TableQuery} 6 | 7 | object NodeMsgsTQ extends TableQuery(new NodeMsgs(_)){ 8 | def getMsgs(nodeId: String): Query[NodeMsgs, NodeMsgRow, Seq] = this.filter(_.nodeId === nodeId) // this is that nodes msg mailbox 9 | def getMsg(nodeId: String, msgId: Int): Query[NodeMsgs, NodeMsgRow, Seq] = this.filter(r => {r.nodeId === nodeId && r.msgId === msgId} ) 10 | def getMsgsExpired = this.filter(_.timeExpires < ApiTime.nowUTC) 11 | def getNumOwned(nodeId: String): Rep[Int] = this.filter(_.nodeId === nodeId).length 12 | def getNodeMsgsInOrg(orgid: String): Query[NodeMsgs, NodeMsgRow, Seq] = this.filter(a => {(a.nodeId like orgid + "/%")} ) 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/status/NodeStatus.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.status 2 | 3 | import io.swagger.v3.oas.annotations.media.{ArraySchema, Schema} 4 | import org.openhorizon.exchangeapi.table.node.OneService 5 | 6 | final case class NodeStatus(connectivity: Map[String,Boolean], 7 | services: List[OneService], 8 | runningServices: String, 9 | lastUpdated: String) 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/status/NodeStatusTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.status 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.TableQuery 5 | 6 | object NodeStatusTQ extends TableQuery(new NodeStatuses(_)) { 7 | def getNodeStatus(nodeId: String): Query[NodeStatuses, NodeStatusRow, Seq] = this.filter(_.nodeId === nodeId) 8 | } 9 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/node/status/NodeStatuses.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.node.status 2 | 3 | import org.openhorizon.exchangeapi.table.node.{NodeRow, Nodes, NodesTQ} 4 | import slick.jdbc.PostgresProfile.api._ 5 | import slick.lifted.{ForeignKeyQuery, Index, ProvenShape} 6 | 7 | class NodeStatuses(tag: Tag) extends Table[NodeStatusRow](tag, "nodestatus") { 8 | def nodeId = column[String]("nodeid", O.PrimaryKey) 9 | def connectivity = column[String]("connectivity") 10 | def services = column[String]("services") 11 | def runningServices = column[String]("runningservices") 12 | def lastUpdated = column[String]("lastUpdated") 13 | 14 | def * : ProvenShape[NodeStatusRow] = (nodeId, connectivity, services, runningServices, lastUpdated).<>(NodeStatusRow.tupled, NodeStatusRow.unapply) 15 | def node: ForeignKeyQuery[Nodes, NodeRow] = foreignKey("node_status_fk_nodes", nodeId, NodesTQ)(_.id, onUpdate = ForeignKeyAction.Cascade, onDelete = ForeignKeyAction.Cascade) 16 | def idx_node_status_fk_nodes = index(name = "idx_node_status_fk_nodes", on = nodeId, unique = false) 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/organization/OrgLimits.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.organization 2 | 3 | import org.json4s.jackson.Serialization.read 4 | import org.json4s.{DefaultFormats, Formats} 5 | 6 | final case class OrgLimits(maxNodes: Int) 7 | 8 | object OrgLimits { 9 | protected implicit val jsonFormats: Formats = DefaultFormats 10 | 11 | def toOrgLimit(limitsString: String): OrgLimits = 12 | if (limitsString != "") 13 | read[OrgLimits](limitsString) 14 | else 15 | OrgLimits(0) 16 | } -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/organization/Orgs.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.organization 2 | 3 | import org.json4s._ 4 | import org.openhorizon.exchangeapi.table.ExchangePostgresProfile.api._ 5 | 6 | 7 | class Orgs(tag: Tag) extends Table[OrgRow](tag, "orgs") { 8 | def orgid = column[String]("orgid", O.PrimaryKey) 9 | def orgType = column[String]("orgtype") 10 | def label = column[String]("label") 11 | def description = column[String]("description") 12 | def lastUpdated = column[String]("lastupdated") 13 | def tags = column[Option[JValue]]("tags") 14 | def limits = column[String]("limits") 15 | def heartbeatIntervals = column[String]("heartbeatintervals") 16 | // this describes what you get back when you return rows from a query 17 | def * = (orgid, orgType, label, description, lastUpdated, tags, limits, heartbeatIntervals).<>(OrgRow.tupled, OrgRow.unapply) 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/resourcechange/ResChangeCategory.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.resourcechange 2 | 3 | object ResChangeCategory extends Enumeration { 4 | type ResChangeCategory = Value 5 | val AGBOT: ResChangeCategory.Value = Value("agbot") 6 | val MGMTPOLICY: ResChangeCategory.Value = Value("mgmtpolicy") 7 | val NODE: ResChangeCategory.Value = Value("node") 8 | val ORG: ResChangeCategory.Value = Value("org") 9 | val PATTERN: ResChangeCategory.Value = Value("pattern") 10 | val POLICY: ResChangeCategory.Value = Value("policy") 11 | val SERVICE: ResChangeCategory.Value = Value("service") 12 | val NODEGROUP: ResChangeCategory.Value = Value("ha_group") 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/resourcechange/ResChangeOperation.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.resourcechange 2 | 3 | object ResChangeOperation extends Enumeration { 4 | type ResChangeOperation = Value 5 | val CREATED: ResChangeOperation.Value = Value("created") 6 | val CREATEDMODIFIED: ResChangeOperation.Value = Value("created/modified") 7 | val MODIFIED: ResChangeOperation.Value = Value("modified") 8 | val DELETED: ResChangeOperation.Value = Value("deleted") 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/schema/Schema.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.schema 2 | 3 | final case class Schema(id: Int, 4 | schemaVersion: Int, 5 | description: String, 6 | lastUpdated: String) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/schema/SchemaRow.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.schema 2 | 3 | import slick.dbio.DBIO 4 | import slick.jdbc.PostgresProfile.api._ 5 | 6 | /** Stores the current DB schema version, and includes methods to upgrade to the latest schema. */ 7 | 8 | final case class SchemaRow(id: Int, 9 | schemaVersion: Int, 10 | description: String, 11 | lastUpdated: String) { 12 | //protected implicit val jsonFormats: Formats = DefaultFormats 13 | 14 | def toSchema: Schema = Schema(id, schemaVersion, description, lastUpdated) 15 | 16 | // update returns a DB action to update this row 17 | def update: DBIO[_] = (for {m <- SchemaTQ if m.id === 0 } yield m).update(this) 18 | 19 | // insert returns a DB action to insert this row 20 | def insert: DBIO[_] = SchemaTQ += this 21 | 22 | // Returns a DB action to insert or update this row 23 | def upsert: DBIO[_] = SchemaTQ.insertOrUpdate(this) 24 | } 25 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/schema/SchemaTable.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.schema 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | 5 | 6 | class SchemaTable(tag: Tag) extends Table[SchemaRow](tag, "schema") { 7 | def id = column[Int]("id", O.PrimaryKey) // we only have 1 row, so this is always 0 8 | def schemaversion = column[Int]("schemaversion") 9 | def description = column[String]("description") 10 | def lastUpdated = column[String]("lastupdated") 11 | 12 | def * = (id, schemaversion, description, lastUpdated).<>(SchemaRow.tupled, SchemaRow.unapply) 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/OneProperty.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service 2 | 3 | final case class OneProperty(name: String, 4 | `type`: Option[String] = None, 5 | value: Any) { 6 | override def clone() = new OneProperty(name, `type`, value) 7 | } 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/SearchService.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | 5 | class SearchService(tag: Tag) extends Table[SearchServiceKey](tag, "search_service") { 6 | def architecture = column[String]("architecture", O.Default("%")) 7 | def domain = column[String]("domain") 8 | def organization = column[String]("organization") 9 | def session = column[String]("session") 10 | def version = column[String]("version", O.Default("%")) 11 | 12 | def * = (architecture, domain, organization, session, version) <> (SearchServiceKey.tupled, SearchServiceKey.unapply) 13 | def pk_servicesearch = primaryKey("pk_searchservice", (architecture, domain, organization, session, version)) 14 | def idx_servicesearch_session = index("idx_searchservice_session", session, unique = false) 15 | } 16 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/SearchServiceKey.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service 2 | 3 | case class SearchServiceKey(architecture: String = "%", 4 | domain: String, 5 | organization: String, 6 | session: String, 7 | version: String = "%") 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/SearchServiceTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service 2 | 3 | import slick.lifted.TableQuery 4 | 5 | object SearchServiceTQ extends TableQuery(new SearchService(_)) {} 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/ServiceRef.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service 2 | 3 | final case class ServiceRef(url: String, 4 | org: String, 5 | version: Option[String], 6 | versionRange: Option[String], 7 | arch: String) 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/ServiceRef2.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service 2 | 3 | final case class ServiceRef2(url: String, 4 | org: String, 5 | versionRange: String, 6 | arch: String) 7 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/dockerauth/ServiceDockAuth.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service.dockerauth 2 | 3 | final case class ServiceDockAuth(dockAuthId: Int, 4 | registry: String, 5 | username: String, 6 | token: String, 7 | lastUpdated: String) 8 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/dockerauth/ServiceDockAuthRow.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service.dockerauth 2 | 3 | import slick.dbio.DBIO 4 | import slick.jdbc.PostgresProfile.api._ 5 | 6 | final case class ServiceDockAuthRow(dockAuthId: Int, serviceId: String, registry: String, username: String, token: String, lastUpdated: String) { 7 | def toServiceDockAuth: ServiceDockAuth = ServiceDockAuth(dockAuthId, registry, username, token, lastUpdated) 8 | 9 | // The returning operator is necessary on insert to have it return the id auto-generated, instead of the number of rows inserted 10 | def insert: DBIO[_] = (ServiceDockAuthsTQ returning ServiceDockAuthsTQ.map(_.dockAuthId)) += this 11 | 12 | def update: DBIO[_] = ServiceDockAuthsTQ.getDockAuth(serviceId, dockAuthId).update(this) 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/key/ServiceKey.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service.key 2 | 3 | final case class ServiceKey(key: String, 4 | lastUpdated: String) 5 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/key/ServiceKeyRow.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service.key 2 | 3 | import slick.dbio.DBIO 4 | import slick.jdbc.PostgresProfile.api._ 5 | 6 | final case class ServiceKeyRow(keyId: String, 7 | serviceId: String, 8 | key: String, 9 | lastUpdated: String) { 10 | def toServiceKey: ServiceKey = ServiceKey(key, lastUpdated) 11 | 12 | def upsert: DBIO[_] = ServiceKeysTQ.insertOrUpdate(this) 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/key/ServiceKeys.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service.key 2 | 3 | import org.openhorizon.exchangeapi.table.service.ServicesTQ 4 | import slick.jdbc.PostgresProfile.api._ 5 | import slick.model.ForeignKeyAction 6 | 7 | class ServiceKeys(tag: Tag) extends Table[ServiceKeyRow](tag, "servicekeys") { 8 | def keyId = column[String]("keyid") // key - the key name 9 | def serviceId = column[String]("serviceid") // additional key - the composite orgid/serviceid 10 | def key = column[String]("key") // the actual key content 11 | def lastUpdated = column[String]("lastupdated") 12 | 13 | def * = (keyId, serviceId, key, lastUpdated).<>(ServiceKeyRow.tupled, ServiceKeyRow.unapply) 14 | 15 | def primKey = primaryKey("pk_svck", (keyId, serviceId)) 16 | def service = foreignKey("service_fk", serviceId, ServicesTQ)(_.service, onUpdate = ForeignKeyAction.Cascade, onDelete = ForeignKeyAction.Cascade) 17 | def idx_serv_key_fk_services = index(name = "idx_serv_key_fk_services", on = serviceId, unique = false) 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/key/ServiceKeysTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service.key 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.TableQuery 5 | 6 | object ServiceKeysTQ extends TableQuery(new ServiceKeys(_)) { 7 | def getKeys(serviceId: String): Query[ServiceKeys, ServiceKeyRow, Seq] = this.filter(_.serviceId === serviceId) 8 | 9 | def getKey(serviceId: String, keyId: String): Query[ServiceKeys, ServiceKeyRow, Seq] = this.filter(r => { 10 | r.serviceId === serviceId && r.keyId === keyId 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/policy/ServicePolicies.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service.policy 2 | 3 | import org.openhorizon.exchangeapi.table.service.ServicesTQ 4 | import slick.jdbc.PostgresProfile.api._ 5 | import slick.model.ForeignKeyAction 6 | 7 | 8 | class ServicePolicies(tag: Tag) extends Table[ServicePolicyRow](tag, "servicepolicies") { 9 | def serviceId = column[String]("serviceid", O.PrimaryKey) // the content of this is orgid/service 10 | def label = column[String]("label") 11 | def description = column[String]("description") 12 | def properties = column[String]("properties") 13 | def constraints = column[String]("constraints") 14 | def lastUpdated = column[String]("lastUpdated") 15 | 16 | def * = (serviceId, label, description, properties, constraints, lastUpdated).<>(ServicePolicyRow.tupled, ServicePolicyRow.unapply) 17 | 18 | def service = foreignKey("service_fk", serviceId, ServicesTQ)(_.service, onUpdate = ForeignKeyAction.Cascade, onDelete = ForeignKeyAction.Cascade) 19 | def idx_serv_pol_fk_services = index(name = "idx_serv_pol_fk_services", on = serviceId, unique = false) 20 | } 21 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/policy/ServicePolicy.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service.policy 2 | 3 | import org.openhorizon.exchangeapi.table.service.OneProperty 4 | 5 | final case class ServicePolicy(label: String, 6 | description: String, 7 | properties: List[OneProperty], 8 | constraints: List[String], 9 | lastUpdated: String) 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/table/service/policy/ServicePolicyTQ.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.table.service.policy 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | import slick.lifted.TableQuery 5 | 6 | 7 | object ServicePolicyTQ extends TableQuery(new ServicePolicies(_)) { 8 | def getServicePolicy(serviceId: String): Query[ServicePolicies, ServicePolicyRow, Seq] = this.filter(_.serviceId === serviceId) 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/AccessDeniedRejection.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import org.apache.pekko.http.scaladsl.model.StatusCodes 4 | 5 | //final case class AccessDeniedRejection(apiRespMsg: String) extends ExchangeRejection { 6 | // def httpCode: StatusCodes.ClientError = StatusCodes.Forbidden 7 | // 8 | // def apiRespCode: String = ApiRespType.ACCESS_DENIED 9 | //} 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/AlreadyExists2Rejection.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import org.apache.pekko.http.scaladsl.model.StatusCodes 4 | 5 | final case class AlreadyExists2Rejection(apiRespMsg: String) extends ExchangeRejection { 6 | def httpCode: StatusCodes.ClientError = StatusCodes.Conflict 7 | 8 | def apiRespCode: String = ApiRespType.ALREADY_EXISTS 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/AlreadyExistsRejection.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import org.apache.pekko.http.scaladsl.model.StatusCodes 4 | 5 | //final case class AlreadyExistsRejection(apiRespMsg: String) extends ExchangeRejection { 6 | // def httpCode: StatusCodes.ClientError = StatusCodes.Forbidden 7 | // 8 | // def apiRespCode: String = ApiRespType.ALREADY_EXISTS 9 | //} 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/ApiRespType.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | object ApiRespType { 4 | val BADCREDS: String = ExchMsg.translate("api.bad.creds") 5 | val ACCESS_DENIED: String = ExchMsg.translate("api.access.denied") 6 | val ALREADY_EXISTS: String = ExchMsg.translate("api.already.exists") 7 | val BAD_INPUT: String = ExchMsg.translate("api.invalid.input") 8 | val NOT_FOUND: String = ExchMsg.translate("api.not.found") 9 | val INTERNAL_ERROR: String = ExchMsg.translate("api.internal.error") 10 | val NOT_IMPLEMENTED: String = ExchMsg.translate("api.not.implemented") 11 | val BAD_GW: String = ExchMsg.translate("api.db.connection.error") 12 | val GW_TIMEOUT: String = ExchMsg.translate("api.db.timeout") 13 | val ERROR: String = ExchMsg.translate("error") 14 | val WARNING: String = ExchMsg.translate("warning") 15 | val INFO: String = ExchMsg.translate("info") 16 | val OK: String = ExchMsg.translate("ok") 17 | val TOO_BUSY: String = ExchMsg.translate("too.busy") 18 | } 19 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/ApiResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | /** These are used as the response structure for most PUTs, POSTs, and DELETEs. */ 4 | final case class ApiResponse(code: String, 5 | msg: String) 6 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/AuthRejection.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import org.apache.pekko.http.scaladsl.model.{StatusCode, StatusCodes} 4 | import org.openhorizon.exchangeapi.auth.AuthException 5 | 6 | // Converts an exception into an auth rejection 7 | final case class AuthRejection(t: Throwable) extends ExchangeRejection { 8 | //todo: if a generic Throwable is passed in, maybe use something other than invalid creds 9 | def httpCode: StatusCode = t match { 10 | case e: AuthException => e.httpCode 11 | case _ => StatusCodes.Unauthorized // should never get here 12 | } 13 | 14 | def apiRespCode: String = t match { 15 | case e: AuthException => e.apiResponse 16 | case _ => "invalid-credentials" // should never get here 17 | } 18 | 19 | def apiRespMsg: String = t match { 20 | case e: AuthException => e.getMessage 21 | case _ => "invalid credentials" // should never get here 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/BadCredsRejection.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import org.apache.pekko.http.scaladsl.model.StatusCodes 4 | 5 | //someday: the rest of these rejections are not currently used. Instead the route implementations either do the complete() directly, 6 | // or turn an AuthException into a complete() using its toComplete method. But maybe it is better for the pekko framework to know it is a rejection. 7 | final case class BadCredsRejection(apiRespMsg: String) extends ExchangeRejection { 8 | def httpCode: StatusCodes.ClientError = StatusCodes.Unauthorized 9 | 10 | def apiRespCode: String = ApiRespType.BADCREDS 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/BadGwRejection.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import org.apache.pekko.http.scaladsl.model.StatusCodes 4 | 5 | final case class BadGwRejection(apiRespMsg: String) extends ExchangeRejection { 6 | def httpCode: StatusCodes.ServerError = StatusCodes.BadGateway 7 | 8 | def apiRespCode: String = ApiRespType.BAD_GW 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/BadInputRejection.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import org.apache.pekko.http.scaladsl.model.StatusCodes 4 | 5 | final case class BadInputRejection(apiRespMsg: String) extends ExchangeRejection { 6 | def httpCode: StatusCodes.ClientError = StatusCodes.BadRequest 7 | 8 | def apiRespCode: String = ApiRespType.BAD_INPUT 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/DatabaseConnection.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import slick.jdbc.PostgresProfile.api._ 4 | 5 | case object DatabaseConnection { 6 | private val database: Database = Database.forConfig("exchange-db-connection", Configuration.getConfig) 7 | 8 | def getDatabase: Database = database 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/ExchMsg.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import com.osinka.i18n.{Lang, Messages} 4 | 5 | // Returns a msg from the translated files, with the args substituted 6 | object ExchMsg { 7 | def translate(key: String, args: Any*): String = { 8 | try { 9 | //todo: remove these 2 debug statements 10 | val exchLang: String = getLang 11 | if (exchLang.startsWith("zh") || exchLang.startsWith("pt")) println("using lang for msgs: " + exchLang) 12 | 13 | implicit val userLang: Lang = Lang(exchLang) 14 | if (args.nonEmpty) { 15 | return Messages(key, args: _*) 16 | } 17 | Messages(key) 18 | } catch { 19 | case e: Exception => s"message key '$key' not found in the messages file: ${e.getMessage}" 20 | } 21 | } 22 | 23 | def getLang: String = 24 | try 25 | Configuration.getConfig.getString("api.language") 26 | catch { 27 | case _: Exception => "en" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/ExchangeRejection.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import org.apache.pekko.http.scaladsl.model.StatusCode 4 | import org.apache.pekko.http.scaladsl.server.Rejection 5 | import org.json4s.DefaultFormats 6 | import org.json4s.jackson.Serialization 7 | 8 | trait ExchangeRejection extends Rejection { 9 | private implicit val formats: DefaultFormats.type = DefaultFormats 10 | 11 | def httpCode: StatusCode 12 | 13 | def apiRespCode: String 14 | 15 | def apiRespMsg: String 16 | 17 | def toApiResp: ApiResponse = ApiResponse(apiRespCode, apiRespMsg) 18 | 19 | def toJsonStr: String = Serialization.write(ApiResponse(apiRespCode, apiRespMsg)) 20 | 21 | override def toString: String = s"Rejection http code: $httpCode, message: $apiRespMsg" 22 | } 23 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/GwTimeoutRejection.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import org.apache.pekko.http.scaladsl.model.StatusCodes 4 | 5 | final case class GwTimeoutRejection(apiRespMsg: String) extends ExchangeRejection { 6 | def httpCode: StatusCodes.ServerError = StatusCodes.GatewayTimeout 7 | 8 | def apiRespCode: String = ApiRespType.GW_TIMEOUT 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/InternalErrorRejection.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import org.apache.pekko.http.scaladsl.model.StatusCodes 4 | 5 | final case class InternalErrorRejection(apiRespMsg: String) extends ExchangeRejection { 6 | def httpCode: StatusCodes.ServerError = HttpCode.INTERNAL_ERROR 7 | 8 | def apiRespCode: String = ApiRespType.INTERNAL_ERROR 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/LogLevel.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | object LogLevel { 4 | val OFF = "OFF" 5 | val ERROR = "ERROR" 6 | val WARN = "WARN" 7 | val INFO = "INFO" 8 | val DEBUG = "DEBUG" 9 | val validLevels: Set[String] = Set(OFF, ERROR, WARN, INFO, DEBUG) 10 | } 11 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/NodeAgbotTokenValidation.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import scala.util.matching.Regex 4 | 5 | object NodeAgbotTokenValidation { 6 | def isValid(token: String): Boolean = { 7 | // Check if token is valid 8 | // (?=.*[0-9]) digit must occur at least once 9 | // (?=.*[a-z]) lowercase letter must occur at least once 10 | // (?=.*[A-Z]) uppercase letter must occur at least once 11 | // .{15,} minimum 15 chars 12 | val exchLang: String = getLanguage 13 | val pwRegex: Regex = 14 | if (exchLang.contains("ja") || 15 | exchLang.contains("ko") || 16 | exchLang.contains("zh")) 17 | """^(?=.*[0-9]).{15,}$""".r 18 | else 19 | """^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).{15,}$""".r 20 | val valid: Boolean = token match { 21 | case pwRegex(_*) => true 22 | case _ => false 23 | } 24 | valid 25 | } 26 | 27 | def getLanguage: String = 28 | try 29 | Configuration.getConfig.getString("api.language") 30 | catch { 31 | case _: Exception => "en" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/NotFoundRejection.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | import org.apache.pekko.http.scaladsl.model.StatusCodes 4 | 5 | final case class NotFoundRejection(apiRespMsg: String) extends ExchangeRejection { 6 | def httpCode: StatusCodes.ClientError = StatusCodes.NotFound 7 | 8 | def apiRespCode: String = ApiRespType.NOT_FOUND 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/Nth.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | /** Depending on the given int, returns 1st, 2nd, 3rd, 4th, ... */ 4 | final case class Nth(n: Int) { 5 | override def toString: String = { 6 | n match { 7 | case 1 => s"${n}st" 8 | case 2 => s"${n}nd" 9 | case 3 => s"${n}rd" 10 | case _ => s"${n}th" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/org/openhorizon/exchangeapi/utility/StrConstants.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.utility 2 | 3 | object StrConstants { 4 | val hiddenPw = "***************" 5 | } 6 | -------------------------------------------------------------------------------- /src/test/bash/README.md: -------------------------------------------------------------------------------- 1 | This directory and subdirs contain simple bash scripts running curl for ad hoc tests of the Exchagne API. 2 | For automated tests, see src/test/scala/exchangeapi 3 | 4 | ## Preconditions 5 | 6 | - Install jq (command-line JSON processor) 7 | - Set these environment variables: 8 | - EXCHANGE_USER 9 | - EXCHANGE_PW 10 | - EXCHANGE_ROOTPW 11 | - EXCHANGE_URL_ROOT: e.g. http://localhost:8080 -------------------------------------------------------------------------------- /src/test/bash/agbot.sh: -------------------------------------------------------------------------------- 1 | # Run rest api methods as agbot 2 | source `dirname $0`/functions.sh $1 $2 ${@:3} 3 | 4 | curl $copts -X $method -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_AGBOTAUTH" $EXCHANGE_URL_ROOT/v1/${org}$resource | $parse -------------------------------------------------------------------------------- /src/test/bash/anonymous.sh: -------------------------------------------------------------------------------- 1 | # Run rest api methods as anonymous 2 | source `dirname $0`/functions.sh $1 $2 ${@:3} 3 | 4 | curl $copts -X $method -H 'Accept: application/json' $EXCHANGE_URL_ROOT/v1/${org}$resource | $parse -------------------------------------------------------------------------------- /src/test/bash/frontend.sh: -------------------------------------------------------------------------------- 1 | # Run rest api methods from a simulated front end. Most useful for methods that do not need an input body, like GET and DELETE. 2 | source `dirname $0`/functions.sh $2 $3 ${@:4} 3 | 4 | # Data power calls us similar to: curl -u '{username}:{password}' 'https://{serviceURL}' -H 'type:{subjectType}' -H 'id:{username}' -H 'orgid:{org}' -H 'issuer:IBM_ID' -H 'Content-Type: application/json' 5 | # type: person (user logged into the dashboard), app (API Key), or dev (device/gateway) 6 | idType=$1 7 | if [[ $idType == "person" ]]; then 8 | id="feuser" 9 | elif [[ $idType == "app" ]]; then 10 | id="feapikey" 11 | elif [[ $idType == "dev" ]]; then 12 | id="fenode" 13 | else 14 | echo "Error: unknown front end id type: $idType" 15 | exit 2 16 | fi 17 | 18 | curl $copts -X $method -H 'Accept: application/json' -H "type:$idType" -H "id:$id" -H "orgid:$EXCHANGE_ORG" -H "issuer:IBM_ID" $EXCHANGE_URL_ROOT/v1/${org}$resource | $parse -------------------------------------------------------------------------------- /src/test/bash/functions.sh: -------------------------------------------------------------------------------- 1 | # Meant to be sourced by the exchange manual test scripts 2 | 3 | method=$(echo $1 | awk '{print toupper($0)}') 4 | 5 | resource=${2#/} # remove leading slash in case there, because we will add it below 6 | if [[ ${resource:0:6} == "admin/" || ${resource:0:4} == "orgs" ]]; then 7 | org="" # the admin methods are not under the org resource 8 | else 9 | org="orgs/$HZN_ORG_ID/" 10 | fi 11 | 12 | if [[ -z $parse ]]; then 13 | if [[ $3 == "-r" ]]; then 14 | parse=cat 15 | copts='-sS -w %{http_code}' 16 | elif [[ $3 == "-rr" ]]; then 17 | parse=cat 18 | copts='-sS' 19 | else 20 | parse="jq ." 21 | copts='-sS -w %{http_code}' 22 | fi 23 | else 24 | copts='-s' 25 | fi -------------------------------------------------------------------------------- /src/test/bash/get/admin/dropdb-token/root.sh: -------------------------------------------------------------------------------- 1 | # Gets all users as root 2 | source `dirname $0`/../../../functions.sh GET $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_ROOTPW" $HZN_EXCHANGE_URL/admin/dropdb/token | $parse -------------------------------------------------------------------------------- /src/test/bash/get/admin/gettest/root.sh: -------------------------------------------------------------------------------- 1 | # Gets all users as root 2 | source `dirname $0`/../../functions.sh GET $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' -H "Authorization:Basic root:$EXCHANGE_ROOTPW" $EXCHANGE_URL_ROOT/v1/admin/gettest | $parse -------------------------------------------------------------------------------- /src/test/bash/get/agbots/notthere.sh: -------------------------------------------------------------------------------- 1 | # Tries to get an agbot that does not exist 2 | source `dirname $0`/../../functions.sh GET $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" $EXCHANGE_URL_ROOT/v1/agbots/a9999 | $parse -------------------------------------------------------------------------------- /src/test/bash/get/agreements/agbots-notthere.sh: -------------------------------------------------------------------------------- 1 | # Tries to get an agreement of agbot a1 that does not exit 2 | source `dirname $0`/../../functions.sh GET $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" $EXCHANGE_URL_ROOT/v1/agbots/a1/agreements/9999 | $parse -------------------------------------------------------------------------------- /src/test/bash/get/agreements/nodes-notthere.sh: -------------------------------------------------------------------------------- 1 | # Tries to get an agreement of node 1 that does not exist 2 | source `dirname $0`/../../functions.sh GET $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" $EXCHANGE_URL_ROOT/v1/nodes/1/agreements/9999 | $parse -------------------------------------------------------------------------------- /src/test/bash/get/nodes/1-urlparms-noid.sh: -------------------------------------------------------------------------------- 1 | # Gets node 1 2 | source `dirname $0`/../../functions.sh GET $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' $EXCHANGE_URL_ROOT/v1/nodes/1'?token=abc123' | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/get/nodes/1-urlparms-user.sh: -------------------------------------------------------------------------------- 1 | # Gets node 1 2 | source `dirname $0`/../../functions.sh GET $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' $EXCHANGE_URL_ROOT/v1/nodes/1'?id='$EXCHANGE_USER'&token='$EXCHANGE_PW | $parse -------------------------------------------------------------------------------- /src/test/bash/get/nodes/1-urlparms.sh: -------------------------------------------------------------------------------- 1 | # Gets node 1 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/nodes/n1'?id=n1&token=abc123' | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/get/nodes/all-root-urlparms.sh: -------------------------------------------------------------------------------- 1 | # Gets all nodes as root 2 | source `dirname $0`/../../functions.sh GET $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' $EXCHANGE_URL_ROOT/v1/nodes'?id=root&token='$EXCHANGE_ROOTPW | $parse -------------------------------------------------------------------------------- /src/test/bash/get/nodes/notthere.sh: -------------------------------------------------------------------------------- 1 | # Tries to get a node that does not exist 2 | source `dirname $0`/../../functions.sh GET $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" $EXCHANGE_URL_ROOT/v1/nodes/9999 | $parse -------------------------------------------------------------------------------- /src/test/bash/get/users/all-root-encoded.sh: -------------------------------------------------------------------------------- 1 | # Confirms the user/pw of a user 2 | source `dirname $0`/../../functions.sh GET $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' -H "Authorization:Basic $(echo -n root/root:$EXCHANGE_ROOTPW | base64)" $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/users | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/get/users/user-baduser.sh: -------------------------------------------------------------------------------- 1 | # Tries to get a user with bad user creds 2 | source `dirname $0`/../../functions.sh GET $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' -H "Authorization:Basic baduser:$EXCHANGE_PW" $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER | $parse -------------------------------------------------------------------------------- /src/test/bash/get/users/user-newpw.sh: -------------------------------------------------------------------------------- 1 | # Gets a user 2 | source `dirname $0`/../../functions.sh GET $* 3 | 4 | curl $copts -X GET -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:newpw" $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER | $parse -------------------------------------------------------------------------------- /src/test/bash/https.sh: -------------------------------------------------------------------------------- 1 | # Run rest api methods as user via https. Most useful for methods that do not need an input body, like GET and DELETE. 2 | source `dirname $0`/functions.sh $1 $2 ${@:3} 3 | 4 | HZN_EXCHANGE_URL=https://edge-fab-exchange:8443/v1 5 | CERT_PEM=$(dirname $0)/../../../keys/etc/exchangecert.pem 6 | 7 | #echo curl $copts -X $method --cacert ../../../keys/etc/exchangecert.pem -H 'Accept: application/json' -H "Authorization:Basic $HZN_ORG_ID/$HZN_EXCHANGE_USER_AUTH" $HZN_EXCHANGE_URL/${org}$resource 8 | curl $copts -X $method --cacert $CERT_PEM -H "Authorization:Basic $HZN_ORG_ID/$HZN_EXCHANGE_USER_AUTH" $HZN_EXCHANGE_URL/${org}$resource | $parse 9 | -------------------------------------------------------------------------------- /src/test/bash/node.sh: -------------------------------------------------------------------------------- 1 | # Run rest api methods as node 2 | source `dirname $0`/functions.sh $1 $2 ${@:3} 3 | 4 | curl $copts -X $method -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_NODEAUTH" $EXCHANGE_URL_ROOT/v1/${org}$resource | $parse -------------------------------------------------------------------------------- /src/test/bash/patch/agbots/1-agbot-badinput.sh: -------------------------------------------------------------------------------- 1 | # Update node 1 as node 2 | source `dirname $0`/../../functions.sh PATCH $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_AGBOTAUTH" -d '{ 5 | "bad": "agbot-partial-update" 6 | }' $EXCHANGE_URL_ROOT/v1/agbots/a1 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/agbots/1-agbot-publicKey-blank.sh: -------------------------------------------------------------------------------- 1 | # Update node 1 as node 2 | source `dirname $0`/../../functions.sh PATCH $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_AGBOTAUTH" -d '{ 5 | "publicKey": "" 6 | }' $EXCHANGE_URL_ROOT/v1/agbots/a1 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/agbots/1-agbot-publicKey.sh: -------------------------------------------------------------------------------- 1 | # Update node 1 as node 2 | source `dirname $0`/../../functions.sh PATCH $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "publicKey": "newAGBOTABCDEF" 6 | }' $EXCHANGE_URL_ROOT/v1/agbots/a1 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/agbots/1-agbot-token.sh: -------------------------------------------------------------------------------- 1 | # Update node 1 as node 2 | source `dirname $0`/../../functions.sh PATCH $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_AGBOTAUTH" -d '{ 5 | "token": "abcdef" 6 | }' $EXCHANGE_URL_ROOT/v1/agbots/a1 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/nodes/1-node-badinput.sh: -------------------------------------------------------------------------------- 1 | # Update node 1 as node 2 | source `dirname $0`/../../functions.sh PATCH $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_NODEAUTH" -d '{ 5 | "bad": "rpi1-partial-update" 6 | }' $EXCHANGE_URL_ROOT/v1/nodes/1 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/nodes/1-node-name.sh: -------------------------------------------------------------------------------- 1 | # Update node 1 as node 2 | source `dirname $0`/../../functions.sh PATCH $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "name": "rpi1-partial-update" 6 | }' $EXCHANGE_URL_ROOT/v1/nodes/1 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/nodes/1-node-pattern.sh: -------------------------------------------------------------------------------- 1 | # Update node 1 as node 2 | source `dirname $0`/../../functions.sh PATCH $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_NODEAUTH" -d '{ 5 | "pattern": "'$EXCHANGE_ORG'/p1x" 6 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/nodes/n1 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/nodes/1-node-publicKey-blank.sh: -------------------------------------------------------------------------------- 1 | # Update node 1 as node 2 | source `dirname $0`/../../functions.sh PATCH $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_NODEAUTH" -d '{ 5 | "publicKey": "" 6 | }' $EXCHANGE_URL_ROOT/v1/nodes/1 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/nodes/1-node-publicKey.sh: -------------------------------------------------------------------------------- 1 | # Update node 1 as node 2 | source `dirname $0`/../../functions.sh PATCH $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_NODEAUTH" -d '{ 5 | "publicKey": "newABCDEF" 6 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/nodes/n1 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/pattern/patch.sh: -------------------------------------------------------------------------------- 1 | # Updates a microservice 2 | source `dirname $0`/../../functions.sh PATCH $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "description": "this is now patched" 6 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/patterns/p1 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/services/gps-arch-bad.sh: -------------------------------------------------------------------------------- 1 | # Adds a service 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "arch": "arm" 6 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/services/bluehorizon.network-services-gps_1.2.3_amd64 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/services/gps-sharable-bad.sh: -------------------------------------------------------------------------------- 1 | # Adds a service 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "sharable": "foobar" 6 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/services/bluehorizon.network-services-gps_1.2.3_amd64 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/services/gps.sh: -------------------------------------------------------------------------------- 1 | # Adds a service 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "sharable": "exclusive" 6 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/services/bluehorizon.network-services-gps_1.2.3_amd64 | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/patch/services/location.sh: -------------------------------------------------------------------------------- 1 | # Adds a service 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $HZN_ORG_ID/$HZN_EXCHANGE_USER_AUTH" -d '{ 5 | "requiredServices": [ 6 | { 7 | "url": "https://bluehorizon.network/services/gps", 8 | "org": "'$HZN_ORG_ID'", 9 | "version": "[1.0.0,INFINITY)", 10 | "arch": "amd64" 11 | } 12 | ] 13 | }' $HZN_EXCHANGE_URL/orgs/$HZN_ORG_ID/services/bluehorizon.network-services-location_4.5.6_amd64 | $parse 14 | -------------------------------------------------------------------------------- /src/test/bash/post/admin/dropdb/root.sh: -------------------------------------------------------------------------------- 1 | # Reloads config.json 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_RESET_TOKEN" $HZN_EXCHANGE_URL/admin/dropdb | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/admin/hashpw/root.sh: -------------------------------------------------------------------------------- 1 | # Gets a hash of the specified pw 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root:$EXCHANGE_ROOTPW" -d '{ 5 | "password": "'$EXCHANGE_ROOTPW'" 6 | }' $EXCHANGE_URL_ROOT/v1/admin/hashpw | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/post/admin/hashpw/user.sh: -------------------------------------------------------------------------------- 1 | # Tries to get a hash of a pw as user (not allowed) 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "password": "'$EXCHANGE_ROOTPW'" 6 | }' $EXCHANGE_URL_ROOT/v1/admin/hashpw | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/post/admin/initdb/root.sh: -------------------------------------------------------------------------------- 1 | # Reloads config.json 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_ROOTPW" $HZN_EXCHANGE_URL/admin/initdb | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/admin/reload/root.sh: -------------------------------------------------------------------------------- 1 | # Reloads config.json 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_ROOTPW" $EXCHANGE_URL_ROOT/v1/admin/reload | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/admin/reload/user.sh: -------------------------------------------------------------------------------- 1 | # Tries to reload config.json as a user (not allowed) 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" $EXCHANGE_URL_ROOT/v1/admin/reload | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/agbots/dataheartbeat/123-list.sh: -------------------------------------------------------------------------------- 1 | # Updates the data received timestamp for agreement 123 of abbot a1 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic a1:abcdef" -d '["123"]' $EXCHANGE_URL_ROOT/v1/agbots/a1/dataheartbeat | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/agbots/dataheartbeat/123.sh: -------------------------------------------------------------------------------- 1 | # Updates the data received timestamp for agreement 123 of abbot a1 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic a1:abcdef" $EXCHANGE_URL_ROOT/v1/agbots/a1/dataheartbeat/123 | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/agbots/heartbeat/1-user.sh: -------------------------------------------------------------------------------- 1 | # Sends heartbeat from agbot 1 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" $EXCHANGE_URL_ROOT/v1/agbots/a1/heartbeat | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/agbots/heartbeat/1.sh: -------------------------------------------------------------------------------- 1 | # Sends heartbeat from agbot a1 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic a1:abcdef" $EXCHANGE_URL_ROOT/v1/agbots/a1/heartbeat | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/agbots/isrecentdata/123-list.sh: -------------------------------------------------------------------------------- 1 | # Updates the data received timestamp for agreement 123 of abbot a1 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic a1:abcdef" -d '{"secondsStale":300, "agreementIds":["123"]}' $EXCHANGE_URL_ROOT/v1/agbots/a1/isrecentdata | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/agbots/msgs/a1-msg1.sh: -------------------------------------------------------------------------------- 1 | # Adds agreement 123 of agbot a1 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_NODEAUTH" -d '{ 5 | "message": "how do you do?", 6 | "ttl": 300 7 | }' $EXCHANGE_URL_ROOT/v1/agbots/a1/msgs | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/post/agreements/confirm/123-a2.sh: -------------------------------------------------------------------------------- 1 | # Confirms agreement exists 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic a2:abcdef" -d '{"agreementId":"123"}' $EXCHANGE_URL_ROOT/v1/agreements/confirm | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/agreements/confirm/123-user.sh: -------------------------------------------------------------------------------- 1 | # Confirms this agreement exists 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{"agreementId":"123"}' $EXCHANGE_URL_ROOT/v1/agreements/confirm | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/agreements/confirm/123.sh: -------------------------------------------------------------------------------- 1 | # Confirms agreement exists 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic a1:abcdef" -d '{"agreementId":"123"}' $EXCHANGE_URL_ROOT/v1/agreements/confirm | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/nodes/heartbeat/1-user.sh: -------------------------------------------------------------------------------- 1 | # Sends heartbeat from node 1 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" $EXCHANGE_URL_ROOT/v1/nodes/n1/heartbeat | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/nodes/heartbeat/1.sh: -------------------------------------------------------------------------------- 1 | # Sends heartbeat from node 1 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_NODEAUTH" $EXCHANGE_URL_ROOT/v1/nodes/n1/heartbeat | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/nodes/msgs/1-msg1.sh: -------------------------------------------------------------------------------- 1 | # Adds msg to node 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_AGBOTAUTH" -d '{ 5 | "message": "hey there", 6 | "ttl": 300 7 | }' $EXCHANGE_URL_ROOT/v1/nodes/n1/msgs | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/post/nodes/msgs/1-msg2.sh: -------------------------------------------------------------------------------- 1 | # Adds msg to node 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_AGBOTAUTH" -d '{ 5 | "message": "hello again", 6 | "ttl": 300 7 | }' $EXCHANGE_URL_ROOT/v1/nodes/n1/msgs | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/post/nodes/msgs/2-msg1.sh: -------------------------------------------------------------------------------- 1 | # Adds msg to node 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_AGBOTAUTH" -d '{ 5 | "message": "howdy", 6 | "ttl": 300 7 | }' $EXCHANGE_URL_ROOT/v1/nodes/2/msgs | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/post/orgs/create.sh: -------------------------------------------------------------------------------- 1 | # Adds a microservice 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_ROOTPW" -d '{ 5 | "label": "International Business Machines Inc.", 6 | "description": "blah blah" 7 | }' $EXCHANGE_URL_ROOT/v1/orgs/IBM | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/post/patterns/nodehealth/p1.sh: -------------------------------------------------------------------------------- 1 | # Adds a workload 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_AGBOTAUTH" -d '{ 5 | "lastTime": "2017-11-01T12:25:38.767Z[UTC]" 6 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/patterns/p1/nodehealth | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/post/patterns/p1.sh: -------------------------------------------------------------------------------- 1 | # Adds a pattern 2 | source `dirname $0`/../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "label": "My Pattern", "description": "blah blah", "public": true, 6 | "services": [ 7 | { 8 | "serviceUrl": "https://bluehorizon.network/services/netspeed", 9 | "serviceOrgid": "'$EXCHANGE_ORG'", 10 | "serviceArch": "amd64", 11 | "serviceVersions": [ 12 | { 13 | "version": "1.0.0", 14 | "deployment_overrides": "{\"services\":{\"location\":{\"environment\":[\"USE_NEW_STAGING_URL=false\"]}}}", 15 | "deployment_overrides_signature": "a", 16 | "priority": {}, 17 | "upgradePolicy": {} 18 | } 19 | ], 20 | "dataVerification": {}, 21 | "nodeHealth": { 22 | "missing_heartbeat_interval": 600, 23 | "check_agreement_status": 120 24 | } 25 | } 26 | ], 27 | "agreementProtocols": [{ "name": "Basic" }] 28 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/patterns/p1 | $parse 29 | -------------------------------------------------------------------------------- /src/test/bash/post/patterns/search/location.sh: -------------------------------------------------------------------------------- 1 | # Adds a workload 2 | source `dirname $0`/../../../functions.sh '' '' $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_AGBOTAUTH" -d '{ 5 | "serviceUrl": "https://bluehorizon.network/services/location", 6 | "secondsStale": 0, 7 | "startIndex": 0, 8 | "numEntries": 0 9 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/patterns/p1/search | $parse 10 | -------------------------------------------------------------------------------- /src/test/bash/post/search/devices/netspeed-dave.sh: -------------------------------------------------------------------------------- 1 | # Uses wildcars to searches for all nodes in the exchange 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic a1:abcdef" -d '{ 5 | "desiredServices": [ 6 | { 7 | "url": "https://bluehorizon.network/documentation/netspeed-node-api", 8 | "properties": [ 9 | { 10 | "name": "arch", 11 | "value": "arm", 12 | "propType": "string", 13 | "op": "in" 14 | }, 15 | { 16 | "name": "version", 17 | "value": "1.0.0", 18 | "propType": "version", 19 | "op": "in" 20 | }, 21 | { 22 | "name": "agreementProtocols", 23 | "value": "Citizen Scientist", 24 | "propType": "list", 25 | "op": "in" 26 | } 27 | ] 28 | } 29 | ], 30 | "secondsStale": 0, 31 | "propertiesToReturn": [ 32 | "string" 33 | ], 34 | "startIndex": 0, 35 | "numEntries": 0 36 | }' $EXCHANGE_URL_ROOT/v1/search/nodes | $parse 37 | -------------------------------------------------------------------------------- /src/test/bash/post/search/devices/netspeed-wildcard-agbot.sh: -------------------------------------------------------------------------------- 1 | # Uses wildcars to searches for all nodes in the exchange 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic a1:abcdef" -d '{ 5 | "desiredServices": [ 6 | { 7 | "url": "https://bluehorizon.network/documentation/netspeed-node-api", 8 | "properties": [ 9 | { 10 | "name": "arch", 11 | "value": "*", 12 | "propType": "string", 13 | "op": "in" 14 | }, 15 | { 16 | "name": "agreementProtocols", 17 | "value": "ExchangeManualTest", 18 | "propType": "list", 19 | "op": "in" 20 | }, 21 | { 22 | "name": "version", 23 | "value": "*", 24 | "propType": "version", 25 | "op": "in" 26 | } 27 | ] 28 | } 29 | ], 30 | "secondsStale": 0, 31 | "propertiesToReturn": [ 32 | "string" 33 | ], 34 | "startIndex": 0, 35 | "numEntries": 0 36 | }' $EXCHANGE_URL_ROOT/v1/search/nodes | $parse 37 | -------------------------------------------------------------------------------- /src/test/bash/post/search/devices/netspeed-wildcard.sh: -------------------------------------------------------------------------------- 1 | # Uses wildcars to searches for all nodes in the exchange 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | # "desiredServices": [ 6 | { 7 | "url": "https://bluehorizon.network/documentation/netspeed-node-api", 8 | "properties": [ 9 | { 10 | "name": "arch", 11 | "value": "*", 12 | "propType": "string", 13 | "op": "in" 14 | }, 15 | { 16 | "name": "agreementProtocols", 17 | "value": "ExchangeManualTest", 18 | "propType": "list", 19 | "op": "in" 20 | }, 21 | { 22 | "name": "version", 23 | "value": "*", 24 | "propType": "version", 25 | "op": "in" 26 | } 27 | ] 28 | } 29 | ], 30 | "secondsStale": 0, 31 | "propertiesToReturn": [ 32 | "string" 33 | ], 34 | "startIndex": 0, 35 | "numEntries": 0 36 | }' $EXCHANGE_URL_ROOT/v1/search/nodes | $parse 37 | -------------------------------------------------------------------------------- /src/test/bash/post/search/devices/sdr-noversion.sh: -------------------------------------------------------------------------------- 1 | # Uses wildcars to searches for all nodes in the exchange 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "desiredServices": [ 6 | { 7 | "url": "https://bluehorizon.network/documentation/sdr-node-api", 8 | "properties": [ 9 | { 10 | "name": "arch", 11 | "value": "arm", 12 | "propType": "wildcard", 13 | "op": "in" 14 | }, 15 | { 16 | "name": "agreementProtocols", 17 | "value": "ExchangeManualTest", 18 | "propType": "list", 19 | "op": "in" 20 | } 21 | ] 22 | } 23 | ], 24 | "secondsStale": 0, 25 | "propertiesToReturn": [ 26 | "string" 27 | ], 28 | "startIndex": 0, 29 | "numEntries": 0 30 | }' $EXCHANGE_URL_ROOT/v1/search/nodes | $parse 31 | -------------------------------------------------------------------------------- /src/test/bash/post/search/devices/sdr-wildcard-prod.sh: -------------------------------------------------------------------------------- 1 | # Uses wildcars to searches for all nodes in the exchange 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "desiredServices": [ 6 | { 7 | "url": "https://bluehorizon.network/documentation/sdr-node-api", 8 | "properties": [ 9 | { 10 | "name": "arch", 11 | "value": "arm", 12 | "propType": "wildcard", 13 | "op": "in" 14 | }, 15 | { 16 | "name": "agreementProtocols", 17 | "value": "Citizen Scientist", 18 | "propType": "list", 19 | "op": "in" 20 | }, 21 | { 22 | "name": "version", 23 | "value": "*", 24 | "propType": "version", 25 | "op": "in" 26 | } 27 | ] 28 | } 29 | ], 30 | "secondsStale": 0, 31 | "propertiesToReturn": [ 32 | "string" 33 | ], 34 | "startIndex": 0, 35 | "numEntries": 0 36 | }' $EXCHANGE_URL_ROOT/v1/search/nodes | $parse 37 | -------------------------------------------------------------------------------- /src/test/bash/post/search/devices/sdr-wildcard-stale.sh: -------------------------------------------------------------------------------- 1 | # Uses wildcars to searches for all nodes in the exchange 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "desiredServices": [ 6 | { 7 | "url": "https://bluehorizon.network/documentation/sdr-node-api", 8 | "properties": [ 9 | { 10 | "name": "arch", 11 | "value": "arm", 12 | "propType": "wildcard", 13 | "op": "in" 14 | }, 15 | { 16 | "name": "agreementProtocols", 17 | "value": "ExchangeManualTest", 18 | "propType": "list", 19 | "op": "in" 20 | }, 21 | { 22 | "name": "version", 23 | "value": "*", 24 | "propType": "version", 25 | "op": "in" 26 | } 27 | ] 28 | } 29 | ], 30 | "secondsStale": 300, 31 | "propertiesToReturn": [ 32 | "string" 33 | ], 34 | "startIndex": 0, 35 | "numEntries": 0 36 | }' $EXCHANGE_URL_ROOT/v1/search/nodes | $parse 37 | -------------------------------------------------------------------------------- /src/test/bash/post/search/devices/sdr-wildcard.sh: -------------------------------------------------------------------------------- 1 | # Uses wildcars to searches for all nodes in the exchange 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "desiredServices": [ 6 | { 7 | "url": "https://bluehorizon.network/documentation/sdr-node-api", 8 | "properties": [ 9 | { 10 | "name": "arch", 11 | "value": "arm", 12 | "propType": "wildcard", 13 | "op": "in" 14 | }, 15 | { 16 | "name": "agreementProtocols", 17 | "value": "ExchangeManualTest", 18 | "propType": "list", 19 | "op": "in" 20 | }, 21 | { 22 | "name": "version", 23 | "value": "*", 24 | "propType": "version", 25 | "op": "in" 26 | } 27 | ] 28 | } 29 | ], 30 | "secondsStale": 0, 31 | "propertiesToReturn": [ 32 | "string" 33 | ], 34 | "startIndex": 0, 35 | "numEntries": 0 36 | }' $EXCHANGE_URL_ROOT/v1/search/nodes | $parse 37 | -------------------------------------------------------------------------------- /src/test/bash/post/services/dockauths/gps.sh: -------------------------------------------------------------------------------- 1 | # Adds a service 2 | source `dirname $0`/../../../functions.sh '' '' $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "registry": "registry.ng.bluemix.net", 6 | "token": "blahblah" 7 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/services/bluehorizon.network-services-gps_1.2.3_amd64/dockauths | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/post/services/gps.sh: -------------------------------------------------------------------------------- 1 | # Adds a service 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "label": "GPS for amd64", 6 | "description": "blah blah", 7 | "public": true, 8 | "url": "https://bluehorizon.network/services/gps", 9 | "version": "1.2.3", 10 | "arch": "amd64", 11 | "sharable": "single", 12 | "deployment": "{\"services\":{\"gps\":{\"image\":\"summit.hovitos.engineering/x86/gps:1.2.3\",\"environment\":[\"USE_NEW_STAGING_URL=false\"]}}}", 13 | "deploymentSignature": "EURzSkDyk66qE6esYUDkLWLzM=" 14 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/services | $parse 15 | -------------------------------------------------------------------------------- /src/test/bash/post/users/2-create-admin.sh: -------------------------------------------------------------------------------- 1 | # Adds a user 2 | source `dirname $0`/../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "password": "'$EXCHANGE_PW'", 6 | "admin": false, 7 | "email": "'$EXCHANGE_EMAIL'" 8 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/users/${EXCHANGE_USER}2 | $parse 9 | -------------------------------------------------------------------------------- /src/test/bash/post/users/2-create-badinput.sh: -------------------------------------------------------------------------------- 1 | # Adds user 2 2 | source `dirname $0`/../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{ 5 | "token": "'$EXCHANGE_PW'", 6 | "email": "2@gmail.com" 7 | }' $EXCHANGE_URL_ROOT/v1/users/2 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/post/users/2-create-noemail.sh: -------------------------------------------------------------------------------- 1 | # Tries to add a user w/o an email address (invalid) 2 | source `dirname $0`/../../functions.sh POST $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{ 5 | "password": "'$EXCHANGE_PW'", 6 | "email": "" 7 | }' $EXCHANGE_URL_ROOT/v1/users/2 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/post/users/2-create.sh: -------------------------------------------------------------------------------- 1 | # Adds user 2 2 | source `dirname $0`/../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{ 5 | "password": "'$EXCHANGE_PW'", 6 | "email": "2@gmail.com" 7 | }' $EXCHANGE_URL_ROOT/v1/users/2 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/post/users/3-create-2.sh: -------------------------------------------------------------------------------- 1 | # Tries to create a user - this should fail, because the creating user is not an admin 2 | source `dirname $0`/../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/${EXCHANGE_USER}2:$EXCHANGE_PW" -d '{ 5 | "password": "'$EXCHANGE_PW'", 6 | "admin": false, 7 | "email": "'$EXCHANGE_EMAIL'" 8 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/users/${EXCHANGE_USER}3 | $parse 9 | -------------------------------------------------------------------------------- /src/test/bash/post/users/changepw/user-backtoorig.sh: -------------------------------------------------------------------------------- 1 | # Changes the user's pw using the reset token. Run like: EXCHANGE_RESET_TOKEN="" user.sh 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_RESET_TOKEN" -d '{ 5 | "newPassword": "'$EXCHANGE_PW'" 6 | }' $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER/changepw | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/post/users/changepw/user.sh: -------------------------------------------------------------------------------- 1 | # Changes the user's pw using the reset token. Run like: EXCHANGE_RESET_TOKEN="" user.sh 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_RESET_TOKEN" -d '{ 5 | "newPassword": "newpw" 6 | }' $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER/changepw | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/post/users/confirm/baduser.sh: -------------------------------------------------------------------------------- 1 | # Tries to confirm a user's pw using bad creds 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic 123456789fddasdfddsffdsdfdfssdf" $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/users/$EXCHANGE_USER/confirm | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/users/confirm/user-encoded.sh: -------------------------------------------------------------------------------- 1 | # Confirms the user/pw of a user 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic $(echo -n $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW | base64)" $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/users/$EXCHANGE_USER/confirm | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/users/confirm/user-newpw.sh: -------------------------------------------------------------------------------- 1 | # Confirms the new pw of user (after changing it with a reset token) 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:newpw" $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER/confirm | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/users/confirm/user-urlparms.sh: -------------------------------------------------------------------------------- 1 | # Confirms the user/pw of a user 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER/confirm'?password='$EXCHANGE_PW | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/users/confirm/user-urlparms2.sh: -------------------------------------------------------------------------------- 1 | # Confirms the user/pw of a user 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER/confirm'?username='$EXCHANGE_USER'&password='$EXCHANGE_PW | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/users/confirm/user.sh: -------------------------------------------------------------------------------- 1 | # Confirms the user/pw of a user 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER/confirm | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/users/new-create-admin.sh: -------------------------------------------------------------------------------- 1 | # Adds a user 2 | source `dirname $0`/../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "password": "'$EXCHANGE_NEWPW'", 6 | "admin": false, 7 | "email": "'$EXCHANGE_NEWEMAIL'" 8 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/users/$EXCHANGE_NEWUSER | $parse 9 | -------------------------------------------------------------------------------- /src/test/bash/post/users/reset/anonymous.sh: -------------------------------------------------------------------------------- 1 | # Requests a reset token email using no creds (allowed) 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER/reset | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/users/reset/user-root.sh: -------------------------------------------------------------------------------- 1 | # Requests a reset token email using using root creds 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_ROOTPW" $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER/reset | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/users/reset/user.sh: -------------------------------------------------------------------------------- 1 | # Requests a reset token email using user creds (allowed) 2 | source `dirname $0`/../../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER/reset | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/post/users/user-create-anonymous.sh: -------------------------------------------------------------------------------- 1 | # Adds a user 2 | source `dirname $0`/../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{ 5 | "password": "'$EXCHANGE_PW'", 6 | "admin": false, 7 | "email": "'$EXCHANGE_EMAIL'" 8 | }' $EXCHANGE_URL_ROOT/v1/orgs/public/users/$EXCHANGE_USER | $parse 9 | -------------------------------------------------------------------------------- /src/test/bash/post/users/user-create-frontend.sh: -------------------------------------------------------------------------------- 1 | # Updates the root user 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "type:person" -H "id:feuser" -H "orgid:$EXCHANGE_ORG" -H "issuer:IBM_ID" -d '{ 5 | "password": "notused", 6 | "admin": true, 7 | "email": "'$EXCHANGE_EMAIL'" 8 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/users/feuser | $parse 9 | -------------------------------------------------------------------------------- /src/test/bash/post/users/user-create-root.sh: -------------------------------------------------------------------------------- 1 | # Adds a user 2 | source `dirname $0`/../../functions.sh POST $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_ROOTPW" -d '{ 5 | "password": "'$EXCHANGE_PW'", 6 | "admin": true, 7 | "email": "'$EXCHANGE_EMAIL'" 8 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/users/$EXCHANGE_USER | $parse 9 | -------------------------------------------------------------------------------- /src/test/bash/put/admin/config/maxAgbots.sh: -------------------------------------------------------------------------------- 1 | # Sets 1 config value 2 | source `dirname $0`/../../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root:$EXCHANGE_ROOTPW" -d '{ 5 | "varPath": "api.limits.maxAgbots", 6 | "value": "1" 7 | }' $EXCHANGE_URL_ROOT/v1/admin/config | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/admin/config/maxAgreements.sh: -------------------------------------------------------------------------------- 1 | # Sets 1 config value 2 | source `dirname $0`/../../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root:$EXCHANGE_ROOTPW" -d '{ 5 | "varPath": "api.limits.maxAgreements", 6 | "value": "1" 7 | }' $EXCHANGE_URL_ROOT/v1/admin/config | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/admin/config/maxDevices.sh: -------------------------------------------------------------------------------- 1 | # Sets 1 config value 2 | source `dirname $0`/../../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root:$EXCHANGE_ROOTPW" -d '{ 5 | "varPath": "api.limits.maxnodes", 6 | "value": "1" 7 | }' $EXCHANGE_URL_ROOT/v1/admin/config | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/admin/config/maxMessagesInMailbox.sh: -------------------------------------------------------------------------------- 1 | # Sets 1 config value 2 | source `dirname $0`/../../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root:$EXCHANGE_ROOTPW" -d '{ 5 | "varPath": "api.limits.maxMessagesInMailbox", 6 | "value": "1" 7 | }' $EXCHANGE_URL_ROOT/v1/admin/config | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/admin/loglevel/root.sh: -------------------------------------------------------------------------------- 1 | # Changes the logging level 2 | source `dirname $0`/../../../functions.sh PUT $* 3 | 4 | curl $copts -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root:$EXCHANGE_ROOTPW" -d '{ 5 | "loggingLevel": "INFO" 6 | }' $EXCHANGE_URL_ROOT/v1/admin/loglevel | $parse 7 | -------------------------------------------------------------------------------- /src/test/bash/put/admin/table/users.sh: -------------------------------------------------------------------------------- 1 | # Gets a hash of the specified pw 2 | source `dirname $0`/../../../functions.sh PUT $* 3 | 4 | # Pipe the info into this 5 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_ROOTPW" -d @- $EXCHANGE_URL_ROOT/v1/admin/tables/users | $parse 6 | 7 | # curl -# -w "%{http_code}" -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root:$EXCHANGE_ROOTPW" -d '[ 8 | # { 9 | # "username": "2", 10 | # "password": "$2a$10$0wya.WH8ayVYJEoEBcM3g.SsjCmrVpR6tU.RFurYC9W3vK481nybC", 11 | # "email": "2@gmail.com", 12 | # "lastUpdated": "2016-12-02T13:12:25.030Z[UTC]" 13 | # }, 14 | # { 15 | # "username": "bp", 16 | # "password": "$2a$10$xNMVEfKCivXDr/d6pwuUCedRTt.puudl8PCSLjGuv32Ar4drafYW.", 17 | # "email": "bruceandml@gmail.com", 18 | # "lastUpdated": "2016-12-02T13:14:30.031Z[UTC]" 19 | # } 20 | # ]' $EXCHANGE_URL_ROOT/v1/admin/tables/users | $parse 21 | -------------------------------------------------------------------------------- /src/test/bash/put/agbots/a1-compatible.sh: -------------------------------------------------------------------------------- 1 | # Adds agbot a1 to exchange 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "token": "abcdef", 6 | "name": "agbot1", 7 | "msgEndPoint": "whisper-id" 8 | }' $EXCHANGE_URL_ROOT/v1/agbots/a1 | $parse 9 | -------------------------------------------------------------------------------- /src/test/bash/put/agbots/a1-frontend.sh: -------------------------------------------------------------------------------- 1 | # Adds agbot a1 to exchange 2 | source `dirname $0`/../../functions.sh GET $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "type:person" -H "id:feuser" -H "orgid:$EXCHANGE_ORG" -H "issuer:IBM_ID" -d '{ 5 | "token": "abcdef", 6 | "name": "fe-agbot", 7 | "patterns": [{ "orgid": "myorg", "pattern": "mypattern" }], 8 | "msgEndPoint": "whisper-id", 9 | "publicKey": "AGBOTABC" 10 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/agbots/feagbot | $parse 11 | -------------------------------------------------------------------------------- /src/test/bash/put/agbots/a1-root.sh: -------------------------------------------------------------------------------- 1 | # Adds agbot a1 to exchange 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_ROOTPW" -d '{ 5 | "token": "abcdef", 6 | "name": "agbot1", 7 | "msgEndPoint": "", 8 | "publicKey": "AGBOTABC" 9 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/agbots/a1 | $parse 10 | -------------------------------------------------------------------------------- /src/test/bash/put/agbots/a1.sh: -------------------------------------------------------------------------------- 1 | # Adds agbot a1 to exchange 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "token": "abcdef", 6 | "name": "agbot1", 7 | "msgEndPoint": "", 8 | "publicKey": "AGBOTABC" 9 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/agbots/a1 | $parse 10 | -------------------------------------------------------------------------------- /src/test/bash/put/agbots/a2-root.sh: -------------------------------------------------------------------------------- 1 | # Adds agbot a2 as root 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_ROOTPW" -d '{ 5 | "token": "abcdef", 6 | "name": "agbot2-asroot", 7 | "patterns": [{ "orgid": "myorg", "pattern": "mypattern" }], 8 | "msgEndPoint": "whisper-id", 9 | "publicKey": "AGBOTDEF" 10 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/agbots/a2 | $parse 11 | -------------------------------------------------------------------------------- /src/test/bash/put/agbots/a2-user.sh: -------------------------------------------------------------------------------- 1 | # Adds agbot a2 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "token": "abcdef", 6 | "name": "agbot2", 7 | "msgEndPoint": "whisper-id", 8 | "publicKey": "AGBOTDEF" 9 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/agbots/a2 | $parse 10 | -------------------------------------------------------------------------------- /src/test/bash/put/agbots/a3.sh: -------------------------------------------------------------------------------- 1 | # Adds agbot a3 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "token": "abcdef", 6 | "name": "agbot3", 7 | "msgEndPoint": "whisper-id", 8 | "publicKey": "AGBOTDEF" 9 | }' $EXCHANGE_URL_ROOT/v1/agbots/a3 | $parse 10 | -------------------------------------------------------------------------------- /src/test/bash/put/agreements/123-agbot-user.sh: -------------------------------------------------------------------------------- 1 | # Adds agreement 123 of agbot a1 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "workload": "sdr-arm.json", 6 | "state": "finalized" 7 | }' $EXCHANGE_URL_ROOT/v1/agbots/a1/agreements/123 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/agreements/123-agbot.sh: -------------------------------------------------------------------------------- 1 | # Adds agreement 123 of agbot a1 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic a1:abcdef" -d '{ 5 | "workload": "sdr-arm.json", 6 | "state": "negotiating" 7 | }' $EXCHANGE_URL_ROOT/v1/agbots/a1/agreements/123 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/agreements/123-node.sh: -------------------------------------------------------------------------------- 1 | # Adds agreement 123 of node 1 as the node 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic 1:abc123" -d '{ 5 | "microservices": ["https://bluehorizon.network/documentation/sdr-node-api"], 6 | "state": "negotiating" 7 | }' $EXCHANGE_URL_ROOT/v1/nodes/1/agreements/123 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/agreements/456-agbot.sh: -------------------------------------------------------------------------------- 1 | # Adds agreement 456 of agbot a1 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic a1:abcdef" -d '{ 5 | "workload": "sdr-arm.json", 6 | "state": "negotiating" 7 | }' $EXCHANGE_URL_ROOT/v1/agbots/a1/agreements/456 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/agreements/456-node.sh: -------------------------------------------------------------------------------- 1 | # Adds agreement 456 of node 2 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "microservice": "https://bluehorizon.network/documentation/netspeed-node-api", 6 | "state": "negotiating" 7 | }' $EXCHANGE_URL_ROOT/v1/nodes/1/agreements/456 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/agreements/789-agbot.sh: -------------------------------------------------------------------------------- 1 | # Adds agreement 789 of agbot a1 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic a1:abcdef" -d '{ 5 | "workload": "sdr-arm.json", 6 | "state": "negotiating" 7 | }' $EXCHANGE_URL_ROOT/v1/agbots/a1/agreements/789 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/agreements/789-node.sh: -------------------------------------------------------------------------------- 1 | # Adds agreement 789 of node 1 as the node 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic 1:abc123" -d '{ 5 | "microservice": "https://bluehorizon.network/documentation/sdr-node-api", 6 | "state": "negotiating" 7 | }' $EXCHANGE_URL_ROOT/v1/nodes/1/agreements/789 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/nodes/status/1-node.sh: -------------------------------------------------------------------------------- 1 | # Update node 1 as node 2 | source `dirname $0`/../../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_NODEAUTH" -d '{ 5 | "connectivity": { 6 | "firmware.bluehorizon.network": true, 7 | "images.bluehorizon.network": true 8 | }, 9 | "services": [ 10 | { 11 | "agreementId": "78d7912aafb6c11b7a776f77d958519a6dc718b9bd3da36a1442ebb18fe9da30", 12 | "serviceUrl":"https://bluehorizon.network/workloads/location", 13 | "orgid":"ling.com", 14 | "version":"1.2", 15 | "arch":"amd64", 16 | "containers": [ 17 | { 18 | "name": "/dc23c045eb64e1637d027c4b0236512e89b2fddd3f06290c7b2354421d9d8e0d-location", 19 | "image": "summit.hovitos.engineering/x86/location:v1.2", 20 | "created": 1506086099, 21 | "state": "running" 22 | } 23 | ] 24 | } 25 | ] 26 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/nodes/n1/status | $parse 27 | -------------------------------------------------------------------------------- /src/test/bash/put/nodes/weird-user.sh: -------------------------------------------------------------------------------- 1 | # Updates node 1 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "token": "abc123", 6 | "name": "rpi1", 7 | "pattern": "'$EXCHANGE_ORG'/mypat", 8 | "desiredServices": [], 9 | "msgEndPoint": "whisper-id", 10 | "softwareVersions": {}, 11 | "publicKey": "ABC" 12 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/nodes/my@node | $parse 13 | -------------------------------------------------------------------------------- /src/test/bash/put/patterns/p1-no-nodehealth.sh: -------------------------------------------------------------------------------- 1 | # Adds a workload 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "label": "My Pattern", "description": "blah blah", "public": true, 6 | "workloads": [ 7 | { 8 | "workloadUrl": "https://bluehorizon.network/workloads/netspeed", 9 | "workloadOrgid": "'$EXCHANGE_ORG'", 10 | "workloadArch": "amd64", 11 | "workloadVersions": [ 12 | { 13 | "version": "1.0.0", 14 | "deployment_overrides": "{\"services\":{\"location\":{\"environment\":[\"USE_NEW_STAGING_URL=false\"]}}}", 15 | "deployment_overrides_signature": "a", 16 | "priority": {}, 17 | "upgradePolicy": {} 18 | } 19 | ], 20 | "dataVerification": {} 21 | } 22 | ], 23 | "agreementProtocols": [{ "name": "Basic" }] 24 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/patterns/p1 | $parse 25 | 26 | # "nodeHealth": { "missing_heartbeat_interval": 600, "check_agreement_status": 120 } 27 | -------------------------------------------------------------------------------- /src/test/bash/put/patterns/p1.sh: -------------------------------------------------------------------------------- 1 | # Adds a workload 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "label": "My Pattern", "description": "blah blah", "public": true, 6 | "workloads": [ 7 | { 8 | "workloadUrl": "https://bluehorizon.network/workloads/netspeed", 9 | "workloadOrgid": "'$EXCHANGE_ORG'", 10 | "workloadArch": "amd64", 11 | "workloadVersions": [ 12 | { 13 | "version": "1.0.0", 14 | "deployment_overrides": "{\"services\":{\"location\":{\"environment\":[\"USE_NEW_STAGING_URL=false\"]}}}", 15 | "deployment_overrides_signature": "a", 16 | "priority": {}, 17 | "upgradePolicy": {} 18 | } 19 | ], 20 | "dataVerification": {}, 21 | "nodeHealth": { "missing_heartbeat_interval": 600, "check_agreement_status": 120 } 22 | } 23 | ], 24 | "agreementProtocols": [{ "name": "Basic" }] 25 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/patterns/p1 | $parse 26 | -------------------------------------------------------------------------------- /src/test/bash/put/services/dockauths/gps-1.sh: -------------------------------------------------------------------------------- 1 | # Adds a service 2 | source `dirname $0`/../../../functions.sh '' '' $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "registry": "registry.ng.bluemix.net", 6 | "token": "blahblah1" 7 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/services/bluehorizon.network-services-gps_1.2.3_amd64/dockauths/1 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/services/gps-arch-bad.sh: -------------------------------------------------------------------------------- 1 | # Adds a service 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "label": "Location for amd64", 6 | "description": "updated sharable attribute", 7 | "public": true, 8 | "url": "https://bluehorizon.network/services/gps", 9 | "version": "1.2.3", 10 | "arch": "arm", 11 | "sharable": "multiple", 12 | "deployment": "{\"services\":{\"gps\":{\"image\":\"summit.hovitos.engineering/x86/gps:1.2.3\",\"environment\":[\"USE_NEW_STAGING_URL=false\"]}}}", 13 | "deploymentSignature": "EURzSkDyk66qE6esYUDkLWLzM=" 14 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/services/bluehorizon.network-services-gps_1.2.3_amd64 | $parse 15 | -------------------------------------------------------------------------------- /src/test/bash/put/services/gps-sharable-bad.sh: -------------------------------------------------------------------------------- 1 | # Adds a service 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "label": "Location for amd64", 6 | "description": "updated sharable attribute", 7 | "public": true, 8 | "url": "https://bluehorizon.network/services/gps", 9 | "version": "1.2.3", 10 | "arch": "amd64", 11 | "sharable": "foobar", 12 | "deployment": "{\"services\":{\"gps\":{\"image\":\"summit.hovitos.engineering/x86/gps:1.2.3\",\"environment\":[\"USE_NEW_STAGING_URL=false\"]}}}", 13 | "deploymentSignature": "EURzSkDyk66qE6esYUDkLWLzM=" 14 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/services/bluehorizon.network-services-gps_1.2.3_amd64 | $parse 15 | -------------------------------------------------------------------------------- /src/test/bash/put/services/gps.sh: -------------------------------------------------------------------------------- 1 | # Adds a service 2 | source `dirname $0`/../../functions.sh '' '' $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "label": "Location for amd64", 6 | "description": "updated sharable attribute", 7 | "public": true, 8 | "url": "https://bluehorizon.network/services/gps", 9 | "version": "1.2.3", 10 | "arch": "amd64", 11 | "sharable": "multiple", 12 | "deployment": "{\"services\":{\"gps\":{\"image\":\"summit.hovitos.engineering/x86/gps:1.2.3\",\"environment\":[\"USE_NEW_STAGING_URL=false\"]}}}", 13 | "deploymentSignature": "EURzSkDyk66qE6esYUDkLWLzM=" 14 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/services/bluehorizon.network-services-gps_1.2.3_amd64 | $parse 15 | -------------------------------------------------------------------------------- /src/test/bash/put/services/keys/key.sh: -------------------------------------------------------------------------------- 1 | # Adds a service 2 | source `dirname $0`/../../../functions.sh '' '' $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: text/plain' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/$EXCHANGE_USER:$EXCHANGE_PW" -d '-----BEGIN CERTIFICATE----- 5 | MIII+jCCBOKgAwIBAgIUEfeMrmSFxCUKATcNPcowfs/lU9owDQYJKoZIhvcNAQEL 6 | BQAwJjEMMAoGA1UEChMDaWJtMRYwFAYDVQQDDA1icEB1cy5pYm0uY29tMB4XDTE4 7 | MDEwMjAxNDkyMFoXDTIyMDEwMjEzNDgzMFowJjEMMAoGA1UEChMDaWJtMRYwFAYD 8 | VQQDDA1icEB1cy5pYm0uY29tMIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKC 9 | -----END CERTIFICATE----- 10 | ' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/services/bluehorizon.network-services-gps_1.2.3_amd64/keys/mykey3.pem | $parse 11 | -------------------------------------------------------------------------------- /src/test/bash/put/users/2-create-root.sh: -------------------------------------------------------------------------------- 1 | # Adds user 2 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_ROOTPW" -d '{ 5 | "password": "'$EXCHANGE_PW'", 6 | "email": "2@gmail.com" 7 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/users/${EXCHANGE_USER}2 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/users/2-update-root.sh: -------------------------------------------------------------------------------- 1 | # Updates the root email address 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root:$EXCHANGE_ROOTPW" -d '{ 5 | "password": "'$EXCHANGE_PW'", 6 | "email": "2-updated@gmail.com" 7 | }' $EXCHANGE_URL_ROOT/v1/users/2 | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/users/root-root.sh: -------------------------------------------------------------------------------- 1 | # Updates the root email address 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root:$EXCHANGE_ROOTPW" -d '{ 5 | "password": "'$EXCHANGE_ROOTPW'", 6 | "email": "somerealemail@root.com" 7 | }' $EXCHANGE_URL_ROOT/v1/users/root | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/users/root-user.sh: -------------------------------------------------------------------------------- 1 | # Updates the root email address 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "password": "'$EXCHANGE_ROOTPW'", 6 | "email": "thisshouldnotwork@root.com" 7 | }' $EXCHANGE_URL_ROOT/v1/users/root | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/users/user-create-root.sh: -------------------------------------------------------------------------------- 1 | # Updates the root user 2 | source `dirname $0`/../../functions.sh POST $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_ROOTPW" -d '{ 5 | "password": "'$EXCHANGE_PW'", 6 | "email": "'$EXCHANGE_EMAIL'" 7 | }' $EXCHANGE_URL_ROOT/v1/orgs/$EXCHANGE_ORG/users/$EXCHANGE_USER | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/users/user-update-email.sh: -------------------------------------------------------------------------------- 1 | # Updates user 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "password": "", 6 | "email": "brucemp7@gmail.com" 7 | }' $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/users/user-update-root.sh: -------------------------------------------------------------------------------- 1 | # Updates the root email address 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic root:$EXCHANGE_ROOTPW" -d '{ 5 | "password": "'$EXCHANGE_PW'", 6 | "email": "'$EXCHANGE_EMAIL'" 7 | }' $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/put/users/user-update.sh: -------------------------------------------------------------------------------- 1 | # Updates user 2 | source `dirname $0`/../../functions.sh PUT $* 3 | 4 | curl $copts -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_USER:$EXCHANGE_PW" -d '{ 5 | "password": "'$EXCHANGE_PW'", 6 | "email": "'$EXCHANGE_EMAIL'" 7 | }' $EXCHANGE_URL_ROOT/v1/users/$EXCHANGE_USER | $parse 8 | -------------------------------------------------------------------------------- /src/test/bash/root.sh: -------------------------------------------------------------------------------- 1 | # Run rest api methods as root 2 | source `dirname $0`/functions.sh $1 $2 ${@:3} 3 | 4 | curl $copts -X $method -H 'Accept: application/json' -H "Authorization:Basic root/root:$EXCHANGE_ROOTPW" $HZN_EXCHANGE_URL/${org}$resource | $parse 5 | -------------------------------------------------------------------------------- /src/test/bash/scale/summarize.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Reduce/summarize the node output files from scaledriver.sh 4 | 5 | if [[ "$1" == "-h" ]]; then 6 | echo "Usage: $(basename $0)" 7 | exit 1 8 | fi 9 | 10 | # default of where to write the summary or error msgs. Can be overridden 11 | EX_PERF_REPORT_DIR="${EX_PERF_REPORT_DIR:-/tmp/exchangePerf}" 12 | 13 | dir=`dirname $0` 14 | 15 | function checkexitcode { 16 | if [[ $1 == 0 ]]; then return; fi 17 | # write error msg to both the summary file and stderr 18 | echo "Summarize:===============> command $2 failed with exit code $1, exiting." 19 | exit 3 20 | #if [[ "$3" != 'continue' ]]; then exit $1; fi 21 | } 22 | 23 | #cd $EX_PERF_REPORT_DIR 24 | 25 | # Show the agbot full summary files 26 | head -n 100 $EX_PERF_REPORT_DIR/*/agbot/*.summary 27 | checkexitcode $? "head -n 100 $EX_PERF_REPORT_DIR/*/agbot/*.summary" 28 | 29 | # Show just the critical lines from the node summaries, grouped by host 30 | for d in $EX_PERF_REPORT_DIR/*/node; do 31 | echo '' 32 | grep -v -E "^(Simulated |Start time: )" $d/*.summary 33 | checkexitcode $? "grep -v -E \"^(Simulated |Start time: )\" $d/*.summary" 34 | done 35 | -------------------------------------------------------------------------------- /src/test/bash/user.sh: -------------------------------------------------------------------------------- 1 | # Run rest api methods as user. Most useful for methods that do not need an input body, like GET and DELETE. 2 | source `dirname $0`/functions.sh $1 $2 ${@:3} 3 | 4 | #echo curl $copts -X $method -H 'Accept: application/json' -H "Authorization:Basic $HZN_ORG_ID/$HZN_EXCHANGE_USER_AUTH" $HZN_EXCHANGE_URL/${org}$resource 5 | curl $copts -X $method -H "Authorization:Basic $HZN_ORG_ID/$HZN_EXCHANGE_USER_AUTH" $HZN_EXCHANGE_URL/${org}$resource | $parse 6 | -------------------------------------------------------------------------------- /src/test/bash/user2.sh: -------------------------------------------------------------------------------- 1 | # Run rest api methods as user 2. Most useful for methods that do not need an input body, like GET and DELETE. 2 | source `dirname $0`/functions.sh $1 $2 ${@:3} 3 | 4 | curl $copts -X $method -H 'Accept: application/json' -H "Authorization:Basic $EXCHANGE_ORG/${EXCHANGE_USER}2:$EXCHANGE_PW" $EXCHANGE_URL_ROOT/v1/${org}$resource | $parse -------------------------------------------------------------------------------- /src/test/go/.gitignore: -------------------------------------------------------------------------------- 1 | darwin/ 2 | linux/ 3 | -------------------------------------------------------------------------------- /src/test/java/org/openhorizon/exchangeapi/annotation/AdminStatusTest.java: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | import org.scalatest.TagAnnotation; 8 | 9 | @TagAnnotation 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Target({ElementType.METHOD, ElementType.TYPE}) 12 | public @interface AdminStatusTest {} 13 | -------------------------------------------------------------------------------- /src/test/scala/org/openhorizon/exchangeapi/route/agent/TestAgentConfigMgmt.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.agent 2 | 3 | import org.scalatest.Suites 4 | 5 | // Run the following test suites sequentially, in order. 6 | class TestAgentConfigMgmt extends Suites ( 7 | new TestDeleteAgentConfigMgmt, 8 | new TestGetAgentConfigMgmt, 9 | new TestPutAgentConfigMgmt 10 | ) 11 | -------------------------------------------------------------------------------- /src/test/scala/org/openhorizon/exchangeapi/route/user/TestGetUsersResponse.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.route.user 2 | 3 | /** 4 | * Json4s cannot serialize nested case class structures from Json to Scala. These test variants are standard classes. 5 | * We can get away with this as the content of these classes is not used in the runtime, and we are parsing 6 | * from Strings. 7 | */ 8 | 9 | class TestUser(val admin: Boolean = false, 10 | val email: String = "", 11 | val hubAdmin: Boolean = false, 12 | val lastUpdated: String, 13 | val password: String = "", 14 | val updatedBy: String = "") 15 | 16 | class TestGetUsersResponse(val users: Map[String, TestUser] = Map.empty[String, TestUser], 17 | val lastIndex: Int = 0) 18 | -------------------------------------------------------------------------------- /src/test/scala/org/openhorizon/exchangeapi/tag/AdminStatusTest.scala: -------------------------------------------------------------------------------- 1 | package org.openhorizon.exchangeapi.tag 2 | 3 | import org.scalatest.Tag 4 | 5 | object AdminStatusTest extends Tag("org.openhorizon.exchangeapi.tag.AdminStatusTest") 6 | --------------------------------------------------------------------------------