|
| 1 | +import { useQuery } from '@tanstack/react-query' |
| 2 | +import { |
| 3 | + GetRuntimeRoflAppsIdInstancesRak, |
| 4 | + GetRuntimeRoflmarketInstances, |
| 5 | + GetRuntimeRoflmarketProvidersAddress, |
| 6 | + RoflMarketInstance, |
| 7 | +} from '../nexus/api' |
| 8 | +import { isMachineRemoved } from '../components/MachineStatusIcon/isMachineRemoved' |
| 9 | +import { RoflmarketDeployment } from '@oasisprotocol/client-rt/dist/types' |
| 10 | +import { useRoflAppBackendAuthContext } from '../contexts/RoflAppBackendAuth/hooks' |
| 11 | +import { downloadArtifact } from './api' |
| 12 | +import { parsePublishedPortsFromCompose } from './parsePublishedPortsFromCompose' |
| 13 | + |
| 14 | +const MetadataKeySchedulerRAK = 'net.oasis.scheduler.rak' |
| 15 | +const MetadataKeyProxyDomain = 'net.oasis.proxy.domain' |
| 16 | +const MetadataKeyProxyCustomDomains = 'net.oasis.proxy.custom_domains' |
| 17 | + |
| 18 | +// Try to match Go code https://github.com/oasisprotocol/cli/blob/61749d6/cmd/rofl/build/validate.go#L26-L44 |
| 19 | +// PortMapping represents a port mapping. |
| 20 | +interface PortMapping { |
| 21 | + // ServiceName is the name of the service. |
| 22 | + ServiceName: string |
| 23 | + // Port is the port number. |
| 24 | + Port: string |
| 25 | + // ProxyMode is the proxy mode for the port. |
| 26 | + ProxyMode: string |
| 27 | + // GenericDomain is the generic domain name. |
| 28 | + GenericDomain: string |
| 29 | + // CustomDomain is the custom domain name (if any). |
| 30 | + CustomDomain?: string |
| 31 | +} |
| 32 | + |
| 33 | +// AppExtraConfig represents extra configuration for the ROFL app. |
| 34 | +interface AppExtraConfig { |
| 35 | + // Ports are the port mappings exposed by the app. |
| 36 | + Ports: PortMapping[] |
| 37 | +} |
| 38 | + |
| 39 | +/** Proxy Domains */ |
| 40 | +export function useRoflAppDomains(network: 'mainnet' | 'testnet', appID: string) { |
| 41 | + const paratime = 'sapphire' as const |
| 42 | + const { token } = useRoflAppBackendAuthContext() |
| 43 | + |
| 44 | + const query = useQuery({ |
| 45 | + queryKey: ['useRoflAppDomains', network, appID, paratime], |
| 46 | + queryFn: async () => { |
| 47 | + const composeYaml = await downloadArtifact(`${appID}-compose-yaml`, token || '').catch(() => undefined) |
| 48 | + const publishedPortsFromCompose = composeYaml ? parsePublishedPortsFromCompose(composeYaml) : [] |
| 49 | + const extraCfg: AppExtraConfig | undefined = publishedPortsFromCompose?.length |
| 50 | + ? { Ports: publishedPortsFromCompose } |
| 51 | + : undefined |
| 52 | + |
| 53 | + const appMachines = (await GetRuntimeRoflmarketInstances(network, paratime, { deployed_app_id: appID })) |
| 54 | + .data.instances |
| 55 | + |
| 56 | + const appDomains: { ServiceName: string; Domain: string }[] = [] |
| 57 | + for (const insDsc of appMachines.filter(machine => !isMachineRemoved(machine))) { |
| 58 | + // Try to match Go code https://github.com/oasisprotocol/cli/blob/1cc571e/cmd/rofl/machine/show.go#L102-L109 |
| 59 | + const machineID = insDsc.id |
| 60 | + const providerAddr = insDsc.provider |
| 61 | + |
| 62 | + const providerDsc = (await GetRuntimeRoflmarketProvidersAddress(network, paratime, providerAddr)).data |
| 63 | + |
| 64 | + const schedulerRAK = insDsc.metadata[MetadataKeySchedulerRAK] as string | undefined |
| 65 | + if (!schedulerRAK) return [] |
| 66 | + const schedulerDsc = ( |
| 67 | + await GetRuntimeRoflAppsIdInstancesRak(network, paratime, providerDsc.scheduler, schedulerRAK) |
| 68 | + ).data |
| 69 | + |
| 70 | + const proxyDomain1 = schedulerDsc?.metadata?.[MetadataKeyProxyDomain] as string | undefined |
| 71 | + if (!proxyDomain1) return [] |
| 72 | + const numericMachineID = BigInt('0x' + machineID) |
| 73 | + const proxyDomain2 = 'm' + numericMachineID + '.' + proxyDomain1 |
| 74 | + |
| 75 | + appDomains.push(...showMachinePorts(extraCfg ?? impliedExtraCfg(insDsc), appID, insDsc, proxyDomain2)) |
| 76 | + } |
| 77 | + |
| 78 | + return appDomains |
| 79 | + }, |
| 80 | + }) |
| 81 | + |
| 82 | + return query |
| 83 | +} |
| 84 | + |
| 85 | +// Try to match Go code https://github.com/oasisprotocol/cli/blob/1cc571e/cmd/rofl/machine/show.go#L195-L221 |
| 86 | +function showMachinePorts( |
| 87 | + extraCfg: AppExtraConfig, |
| 88 | + _appID: string, |
| 89 | + _insDsc: RoflMarketInstance, |
| 90 | + domain: string, |
| 91 | +) { |
| 92 | + return extraCfg.Ports.map(p => { |
| 93 | + const genericDomain = p.GenericDomain + '.' + domain |
| 94 | + // TODO: DomainVerificationToken |
| 95 | + return { |
| 96 | + ServiceName: p.ServiceName, |
| 97 | + Domain: 'https://' + (p.CustomDomain ?? genericDomain), |
| 98 | + } |
| 99 | + }) |
| 100 | +} |
| 101 | + |
| 102 | +function impliedExtraCfg(insDsc: RoflMarketInstance): AppExtraConfig { |
| 103 | + const customDomains = (insDsc.deployment as unknown as RoflmarketDeployment).metadata?.[ |
| 104 | + MetadataKeyProxyCustomDomains |
| 105 | + ] as string | undefined |
| 106 | + |
| 107 | + return { |
| 108 | + Ports: [ |
| 109 | + // https://github.com/oasisprotocol/oasis-sdk/blob/777bcc4/rofl-scheduler/src/proxy/mod.rs#L231 |
| 110 | + ...(customDomains?.split(' ') || []).map( |
| 111 | + (CustomDomain): PortMapping => ({ |
| 112 | + ServiceName: '', |
| 113 | + Port: '<unknown port>', |
| 114 | + GenericDomain: 'p<unknown port>', |
| 115 | + CustomDomain: CustomDomain, |
| 116 | + ProxyMode: 'terminate-tls', |
| 117 | + }), |
| 118 | + ), |
| 119 | + { |
| 120 | + ServiceName: '', |
| 121 | + Port: '<exposed ports>', |
| 122 | + GenericDomain: 'p<exposed ports>', |
| 123 | + ProxyMode: 'terminate-tls', |
| 124 | + }, |
| 125 | + ], |
| 126 | + } |
| 127 | +} |
0 commit comments