Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
9d52c62335 | |||
971abd19c9 | |||
084a11d7ed | |||
8f49f0cb4f | |||
320b3ed9eb | |||
7cd6bc0e33 | |||
a218805f27 | |||
6f56304e07 | |||
4eb62200e8 | |||
c105596455 | |||
5aa136b8d9 | |||
240516520a | |||
4e1f9464fe | |||
41f9f93d1c | |||
c502d410b1 | |||
53f96095c7 | |||
d212dfb9f9 | |||
0ec665516d | |||
acc642adf9 | |||
a6521708f7 |
@ -6,8 +6,8 @@ on:
|
|||||||
- '**'
|
- '**'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
|
||||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
|
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
|
||||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||||
@ -27,7 +27,7 @@ jobs:
|
|||||||
- name: Install pnpm and npmci
|
- name: Install pnpm and npmci
|
||||||
run: |
|
run: |
|
||||||
pnpm install -g pnpm
|
pnpm install -g pnpm
|
||||||
pnpm install -g @shipzone/npmci
|
pnpm install -g @ship.zone/npmci
|
||||||
npmci npm prepare
|
npmci npm prepare
|
||||||
|
|
||||||
- name: Audit production dependencies
|
- name: Audit production dependencies
|
||||||
@ -54,7 +54,7 @@ jobs:
|
|||||||
- name: Prepare
|
- name: Prepare
|
||||||
run: |
|
run: |
|
||||||
pnpm install -g pnpm
|
pnpm install -g pnpm
|
||||||
pnpm install -g @shipzone/npmci
|
pnpm install -g @ship.zone/npmci
|
||||||
npmci npm prepare
|
npmci npm prepare
|
||||||
|
|
||||||
- name: Test stable
|
- name: Test stable
|
||||||
|
@ -6,8 +6,8 @@ on:
|
|||||||
- '*'
|
- '*'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
|
||||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
|
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
|
||||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||||
@ -27,7 +27,7 @@ jobs:
|
|||||||
- name: Prepare
|
- name: Prepare
|
||||||
run: |
|
run: |
|
||||||
pnpm install -g pnpm
|
pnpm install -g pnpm
|
||||||
pnpm install -g @shipzone/npmci
|
pnpm install -g @ship.zone/npmci
|
||||||
npmci npm prepare
|
npmci npm prepare
|
||||||
|
|
||||||
- name: Audit production dependencies
|
- name: Audit production dependencies
|
||||||
@ -54,7 +54,7 @@ jobs:
|
|||||||
- name: Prepare
|
- name: Prepare
|
||||||
run: |
|
run: |
|
||||||
pnpm install -g pnpm
|
pnpm install -g pnpm
|
||||||
pnpm install -g @shipzone/npmci
|
pnpm install -g @ship.zone/npmci
|
||||||
npmci npm prepare
|
npmci npm prepare
|
||||||
|
|
||||||
- name: Test stable
|
- name: Test stable
|
||||||
@ -74,7 +74,7 @@ jobs:
|
|||||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: registry.gitlab.com/hosttoday/ht-docker-dbase:npmci
|
image: code.foss.global/hosttoday/ht-docker-dbase:npmci
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@ -82,15 +82,15 @@ jobs:
|
|||||||
- name: Prepare
|
- name: Prepare
|
||||||
run: |
|
run: |
|
||||||
pnpm install -g pnpm
|
pnpm install -g pnpm
|
||||||
pnpm install -g @shipzone/npmci
|
pnpm install -g @ship.zone/npmci
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
run: |
|
run: |
|
||||||
npmci docker login
|
npmci docker login
|
||||||
npmci docker build
|
npmci docker build
|
||||||
npmci docker test
|
npmci docker test
|
||||||
# npmci docker push gitea.lossless.digital
|
# npmci docker push
|
||||||
npmci docker push dockerregistry.lossless.digital
|
npmci docker push
|
||||||
|
|
||||||
metadata:
|
metadata:
|
||||||
needs: test
|
needs: test
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# gitzone dockerfile_service
|
# gitzone dockerfile_service
|
||||||
## STAGE 1 // BUILD
|
## STAGE 1 // BUILD
|
||||||
FROM registry.gitlab.com/hosttoday/ht-docker-node:npmci as node1
|
FROM code.foss.global/hosttoday/ht-docker-node:npmci as node1
|
||||||
COPY ./ /app
|
COPY ./ /app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ARG NPMCI_TOKEN_NPM2
|
ARG NPMCI_TOKEN_NPM2
|
||||||
@ -12,7 +12,7 @@ RUN pnpm run build
|
|||||||
|
|
||||||
# gitzone dockerfile_service
|
# gitzone dockerfile_service
|
||||||
## STAGE 2 // install production
|
## STAGE 2 // install production
|
||||||
FROM registry.gitlab.com/hosttoday/ht-docker-node:npmci as node2
|
FROM code.foss.global/hosttoday/ht-docker-node:npmci as node2
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=node1 /app /app
|
COPY --from=node1 /app /app
|
||||||
RUN rm -rf .pnpm-store
|
RUN rm -rf .pnpm-store
|
||||||
@ -24,7 +24,7 @@ RUN rm -rf node_modules/ && pnpm install --prod
|
|||||||
|
|
||||||
|
|
||||||
## STAGE 3 // rebuild dependencies for alpine
|
## STAGE 3 // rebuild dependencies for alpine
|
||||||
FROM registry.gitlab.com/hosttoday/ht-docker-node:alpinenpmci as node3
|
FROM code.foss.global/hosttoday/ht-docker-node:alpinenpmci as node3
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=node2 /app /app
|
COPY --from=node2 /app /app
|
||||||
ARG NPMCI_TOKEN_NPM2
|
ARG NPMCI_TOKEN_NPM2
|
||||||
@ -34,7 +34,7 @@ RUN pnpm config set store-dir .pnpm-store
|
|||||||
RUN pnpm rebuild -r
|
RUN pnpm rebuild -r
|
||||||
|
|
||||||
## STAGE 4 // the final production image with all dependencies in place
|
## STAGE 4 // the final production image with all dependencies in place
|
||||||
FROM registry.gitlab.com/hosttoday/ht-docker-node:alpine as node4
|
FROM code.foss.global/hosttoday/ht-docker-node:alpine as node4
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=node3 /app /app
|
COPY --from=node3 /app /app
|
||||||
|
|
||||||
|
114
changelog.md
Normal file
114
changelog.md
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 2024-10-28 - 1.2.5 - fix(build)
|
||||||
|
Updated devDependencies for tspublish and removed buildDocs script
|
||||||
|
|
||||||
|
- devDependencies updated: @git.zone/tspublish to version ^1.5.4
|
||||||
|
- Removed: buildDocs script from the scripts section
|
||||||
|
|
||||||
|
## 2024-10-27 - 1.2.4 - fix(ci)
|
||||||
|
Fix Docker images and npm registry URL in CI workflows
|
||||||
|
|
||||||
|
- Updated Docker image registry URL from 'registry.gitlab.com' to 'code.foss.global'.
|
||||||
|
- Fixed npmci package installation path from '@shipzone/npmci' to '@ship.zone/npmci'.
|
||||||
|
|
||||||
|
## 2024-10-23 - 1.2.3 - fix(cli)
|
||||||
|
Set up CLI client definition and registry configuration
|
||||||
|
|
||||||
|
- Added a console log message for CLI identification.
|
||||||
|
- Defined package name for CLI client.
|
||||||
|
- Configured npm registries for package distribution.
|
||||||
|
|
||||||
|
## 2024-10-23 - 1.2.2 - fix(docs)
|
||||||
|
Updated documentation with clearer usage instructions and examples.
|
||||||
|
|
||||||
|
- Refined setup guides in README.
|
||||||
|
- Added more detailed examples in code snippets.
|
||||||
|
- Clarified cloud service integration instructions.
|
||||||
|
|
||||||
|
## 2024-10-23 - 1.2.1 - fix(core)
|
||||||
|
Fixed startup issue for the Cloudly instance
|
||||||
|
|
||||||
|
|
||||||
|
## 2024-10-21 - 1.2.0 - feat(cli)
|
||||||
|
Add tspublish.json for CLI client and interfaces
|
||||||
|
|
||||||
|
- Added registration details for publishing CLI client (@serve.zone/cli)
|
||||||
|
- Specified npm and custom registries in the tspublish.json for better publish control
|
||||||
|
- Updated dependency version for @git.zone/tspublish in package.json
|
||||||
|
|
||||||
|
## 2024-10-21 - 1.1.9 - fix(build)
|
||||||
|
Update Node types and other dependencies, add tspublish.json for api client
|
||||||
|
|
||||||
|
- Updated Node types devDependency to version ^22.7.7 from ^22.7.5.
|
||||||
|
- Updated smartbucket dependency to version ^3.0.23 from ^3.0.22.
|
||||||
|
- Added tspublish configuration file to the api client.
|
||||||
|
- Fixed the npm publish script in package.json.
|
||||||
|
|
||||||
|
## 2024-10-16 - 1.1.8 - fix(big fix upgrade)
|
||||||
|
fix: update dependency versions and address type errors
|
||||||
|
|
||||||
|
- Updated all listed dependencies in the package.json to their specified ranges.
|
||||||
|
- Fixed type mismatches and added missing imports in various TypeScript files.
|
||||||
|
- Refined existing tests and added a new helper to manage Docker image streams.
|
||||||
|
|
||||||
|
## 2024-08-25 - 1.1.7 - fix(deps)
|
||||||
|
Update dependencies to latest versions
|
||||||
|
|
||||||
|
- Updated @git.zone/tsbuild from ^2.1.80 to ^2.1.84
|
||||||
|
- Updated @push.rocks/tapbundle from ^5.0.23 to ^5.0.24
|
||||||
|
- Updated @types/node from ^20.14.6 to ^22.5.0
|
||||||
|
- Updated @apiclient.xyz/docker from ^1.2.2 to ^1.2.3
|
||||||
|
- Updated @design.estate/dees-catalog from ^1.0.289 to ^1.1.6
|
||||||
|
- Updated @design.estate/dees-element from ^2.0.34 to ^2.0.36
|
||||||
|
- Updated @git.zone/tsrun from ^1.2.37 to ^1.2.49
|
||||||
|
- Updated @push.rocks/smartbucket from ^3.0.20 to ^3.0.22
|
||||||
|
- Updated @push.rocks/smartpromise from ^4.0.3 to ^4.0.4
|
||||||
|
- Updated @serve.zone/interfaces from ^1.0.74 to ^1.0.78
|
||||||
|
- Updated @tsclass/tsclass from ^4.0.60 to ^4.1.2
|
||||||
|
|
||||||
|
## 2024-06-20 - 1.1.6 - Updates
|
||||||
|
Routine updates and fixes.
|
||||||
|
|
||||||
|
- (fix) core: update
|
||||||
|
|
||||||
|
## 2024-06-13 - 1.1.4 - Service Management Preparation
|
||||||
|
Incorporated updates and service management preparations.
|
||||||
|
|
||||||
|
- (fix) core: update
|
||||||
|
- (feat) prepare service management
|
||||||
|
|
||||||
|
## 2024-06-05 - 1.1.3 - CI Integration Improvement
|
||||||
|
Structural improvements and better CI integration preparation.
|
||||||
|
|
||||||
|
- (fix) structure: improve structure, prepare better CI integration
|
||||||
|
|
||||||
|
## 2024-06-02 - 1.1.2 - Image Manager Update
|
||||||
|
Prepared proper storage and retrieval of container images.
|
||||||
|
|
||||||
|
- (fix) imagemanager: prepare proper storage and retrieval of container images
|
||||||
|
|
||||||
|
## 2024-06-01 - 1.1.0 - Image Registry Work
|
||||||
|
Initiated work on image registry.
|
||||||
|
|
||||||
|
- (fix) image registry: start work on image registry
|
||||||
|
|
||||||
|
## 2024-05-30 - 1.0.216 - Enhanced Smartguards
|
||||||
|
Enhanced smartguards to verify action authorization.
|
||||||
|
|
||||||
|
- (feat) guards: use better smartguards to verify action authorization
|
||||||
|
|
||||||
|
## 2024-05-28 - 1.0.215 - Unified Package Update
|
||||||
|
Updated package unification for cloudly + API + CLI.
|
||||||
|
|
||||||
|
- (fix) switch to unified package for cloudly + API + CLI: update
|
||||||
|
|
||||||
|
## 2024-05-05 - 1.0.214 - Core Updates
|
||||||
|
Routine core updates.
|
||||||
|
|
||||||
|
- (fix) core: update
|
||||||
|
|
||||||
|
## 2024-04-20 - 1.0.213 - Core Update
|
||||||
|
Routine core updates.
|
||||||
|
|
||||||
|
- (fix) core: update
|
@ -16,23 +16,23 @@
|
|||||||
"githost": "gitlab.com",
|
"githost": "gitlab.com",
|
||||||
"gitscope": "servezone/private",
|
"gitscope": "servezone/private",
|
||||||
"gitrepo": "cloudly",
|
"gitrepo": "cloudly",
|
||||||
"description": "A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and integrate robust configuration and API management capabilities.",
|
"description": "A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.",
|
||||||
"npmPackagename": "@serve.zone/cloudly",
|
"npmPackagename": "@serve.zone/cloudly",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cloud management",
|
"cloud management",
|
||||||
"multi-cloud",
|
"multi-cloud management",
|
||||||
"Docker Swarmkit",
|
"Docker Swarmkit",
|
||||||
|
"container orchestration",
|
||||||
|
"cloud services",
|
||||||
"DigitalOcean",
|
"DigitalOcean",
|
||||||
"Hetzner Cloud",
|
"Hetzner Cloud",
|
||||||
"Cloudflare",
|
"Cloudflare",
|
||||||
"container orchestration",
|
|
||||||
"configuration management",
|
"configuration management",
|
||||||
"SSL management",
|
"SSL management",
|
||||||
"API integration",
|
"API integration",
|
||||||
"TypeScript",
|
"TypeScript",
|
||||||
"node.js",
|
"node.js",
|
||||||
"cloud integration",
|
|
||||||
"infrastructure automation",
|
"infrastructure automation",
|
||||||
"devOps",
|
"devOps",
|
||||||
"cloud API client",
|
"cloud API client",
|
||||||
@ -42,7 +42,7 @@
|
|||||||
"task scheduling",
|
"task scheduling",
|
||||||
"frontend",
|
"frontend",
|
||||||
"backend",
|
"backend",
|
||||||
"cli",
|
"CLI",
|
||||||
"web interface",
|
"web interface",
|
||||||
"cloud providers",
|
"cloud providers",
|
||||||
"security",
|
"security",
|
||||||
|
61
package.json
61
package.json
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "@serve.zone/cloudly",
|
"name": "@serve.zone/cloudly",
|
||||||
"version": "1.1.5",
|
"version": "1.2.5",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and integrate robust configuration and API management capabilities.",
|
"description": "A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./dist/index.js",
|
".": "./dist/index.js",
|
||||||
@ -18,58 +18,61 @@
|
|||||||
"start": "node cli.js",
|
"start": "node cli.js",
|
||||||
"startTs": "node cli.ts.js",
|
"startTs": "node cli.ts.js",
|
||||||
"watch": "tswatch website",
|
"watch": "tswatch website",
|
||||||
"localPublish": "gitzone commit"
|
"publish": "tspublish"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.1.80",
|
"@git.zone/tsbuild": "^2.1.85",
|
||||||
"@git.zone/tsbundle": "^2.0.15",
|
"@git.zone/tsbundle": "^2.1.0",
|
||||||
|
"@git.zone/tspublish": "^1.5.4",
|
||||||
"@git.zone/tstest": "^1.0.90",
|
"@git.zone/tstest": "^1.0.90",
|
||||||
"@git.zone/tswatch": "^2.0.23",
|
"@git.zone/tswatch": "^2.0.25",
|
||||||
"@push.rocks/tapbundle": "^5.0.23",
|
"@push.rocks/tapbundle": "^5.3.0",
|
||||||
"@types/node": "^20.14.6"
|
"@types/node": "^22.8.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@api.global/typedrequest": "3.0.30",
|
"@api.global/typedrequest": "3.1.10",
|
||||||
"@api.global/typedserver": "^3.0.50",
|
"@api.global/typedrequest-interfaces": "^3.0.19",
|
||||||
|
"@api.global/typedserver": "^3.0.51",
|
||||||
"@api.global/typedsocket": "^3.0.1",
|
"@api.global/typedsocket": "^3.0.1",
|
||||||
"@apiclient.xyz/cloudflare": "^6.0.1",
|
"@apiclient.xyz/cloudflare": "^6.0.1",
|
||||||
"@apiclient.xyz/docker": "^1.2.2",
|
"@apiclient.xyz/docker": "^1.2.7",
|
||||||
"@apiclient.xyz/hetznercloud": "^1.2.0",
|
"@apiclient.xyz/hetznercloud": "^1.2.0",
|
||||||
"@apiclient.xyz/slack": "^3.0.9",
|
"@apiclient.xyz/slack": "^3.0.9",
|
||||||
"@design.estate/dees-catalog": "^1.0.289",
|
"@design.estate/dees-catalog": "^1.2.0",
|
||||||
"@design.estate/dees-domtools": "^2.0.57",
|
"@design.estate/dees-domtools": "^2.0.64",
|
||||||
"@design.estate/dees-element": "^2.0.34",
|
"@design.estate/dees-element": "^2.0.39",
|
||||||
"@git.zone/tsrun": "^1.2.37",
|
"@git.zone/tsrun": "^1.3.3",
|
||||||
"@push.rocks/early": "^4.0.3",
|
"@push.rocks/early": "^4.0.3",
|
||||||
"@push.rocks/npmextra": "^5.0.23",
|
"@push.rocks/npmextra": "^5.0.23",
|
||||||
"@push.rocks/projectinfo": "^5.0.1",
|
"@push.rocks/projectinfo": "^5.0.1",
|
||||||
"@push.rocks/qenv": "^6.0.5",
|
"@push.rocks/qenv": "^6.0.5",
|
||||||
"@push.rocks/smartacme": "^5.0.0",
|
"@push.rocks/smartacme": "^5.0.0",
|
||||||
"@push.rocks/smartbucket": "^3.0.20",
|
"@push.rocks/smartbucket": "^3.0.23",
|
||||||
"@push.rocks/smartcli": "^4.0.11",
|
"@push.rocks/smartcli": "^4.0.11",
|
||||||
"@push.rocks/smartclickhouse": "^2.0.17",
|
"@push.rocks/smartclickhouse": "^2.0.17",
|
||||||
"@push.rocks/smartdata": "^5.2.6",
|
"@push.rocks/smartdata": "^5.2.10",
|
||||||
"@push.rocks/smartdelay": "^3.0.5",
|
"@push.rocks/smartdelay": "^3.0.5",
|
||||||
"@push.rocks/smartexit": "^1.0.23",
|
"@push.rocks/smartexit": "^1.0.23",
|
||||||
"@push.rocks/smartfile": "^11.0.20",
|
"@push.rocks/smartexpect": "^1.2.1",
|
||||||
"@push.rocks/smartguard": "^3.0.2",
|
"@push.rocks/smartfile": "^11.0.21",
|
||||||
|
"@push.rocks/smartguard": "^3.1.0",
|
||||||
"@push.rocks/smartjson": "^5.0.19",
|
"@push.rocks/smartjson": "^5.0.19",
|
||||||
"@push.rocks/smartjwt": "^2.0.4",
|
"@push.rocks/smartjwt": "^2.2.1",
|
||||||
"@push.rocks/smartlog": "^3.0.7",
|
"@push.rocks/smartlog": "^3.0.7",
|
||||||
"@push.rocks/smartlog-destination-clickhouse": "^1.0.13",
|
"@push.rocks/smartlog-destination-clickhouse": "^1.0.13",
|
||||||
|
"@push.rocks/smartlog-interfaces": "^3.0.2",
|
||||||
"@push.rocks/smartpath": "^5.0.18",
|
"@push.rocks/smartpath": "^5.0.18",
|
||||||
"@push.rocks/smartpromise": "^4.0.3",
|
"@push.rocks/smartpromise": "^4.0.4",
|
||||||
"@push.rocks/smartrequest": "^2.0.22",
|
"@push.rocks/smartrequest": "^2.0.22",
|
||||||
"@push.rocks/smartrx": "^3.0.7",
|
"@push.rocks/smartrx": "^3.0.7",
|
||||||
"@push.rocks/smartssh": "^2.0.1",
|
"@push.rocks/smartssh": "^2.0.1",
|
||||||
"@push.rocks/smartstate": "^2.0.17",
|
"@push.rocks/smartstate": "^2.0.19",
|
||||||
"@push.rocks/smartstream": "^3.0.44",
|
"@push.rocks/smartstream": "^3.2.4",
|
||||||
"@push.rocks/smartstring": "^4.0.15",
|
"@push.rocks/smartstring": "^4.0.15",
|
||||||
"@push.rocks/smartunique": "^3.0.9",
|
"@push.rocks/smartunique": "^3.0.9",
|
||||||
"@push.rocks/taskbuffer": "^3.0.2",
|
"@push.rocks/taskbuffer": "^3.0.2",
|
||||||
"@push.rocks/webjwt": "^1.0.9",
|
"@push.rocks/webjwt": "^1.0.9",
|
||||||
"@serve.zone/interfaces": "^1.0.74",
|
"@tsclass/tsclass": "^4.1.2"
|
||||||
"@tsclass/tsclass": "^4.0.60"
|
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"ts/**/*",
|
"ts/**/*",
|
||||||
@ -96,18 +99,18 @@
|
|||||||
"homepage": "https://gitlab.com/servezone/private/cloudly#readme",
|
"homepage": "https://gitlab.com/servezone/private/cloudly#readme",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cloud management",
|
"cloud management",
|
||||||
"multi-cloud",
|
"multi-cloud management",
|
||||||
"Docker Swarmkit",
|
"Docker Swarmkit",
|
||||||
|
"container orchestration",
|
||||||
|
"cloud services",
|
||||||
"DigitalOcean",
|
"DigitalOcean",
|
||||||
"Hetzner Cloud",
|
"Hetzner Cloud",
|
||||||
"Cloudflare",
|
"Cloudflare",
|
||||||
"container orchestration",
|
|
||||||
"configuration management",
|
"configuration management",
|
||||||
"SSL management",
|
"SSL management",
|
||||||
"API integration",
|
"API integration",
|
||||||
"TypeScript",
|
"TypeScript",
|
||||||
"node.js",
|
"node.js",
|
||||||
"cloud integration",
|
|
||||||
"infrastructure automation",
|
"infrastructure automation",
|
||||||
"devOps",
|
"devOps",
|
||||||
"cloud API client",
|
"cloud API client",
|
||||||
@ -117,7 +120,7 @@
|
|||||||
"task scheduling",
|
"task scheduling",
|
||||||
"frontend",
|
"frontend",
|
||||||
"backend",
|
"backend",
|
||||||
"cli",
|
"CLI",
|
||||||
"web interface",
|
"web interface",
|
||||||
"cloud providers",
|
"cloud providers",
|
||||||
"security",
|
"security",
|
||||||
|
13051
pnpm-lock.yaml
generated
13051
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -8,3 +8,4 @@
|
|||||||
`code.foss.global/serve.zone/cloudly:latest`
|
`code.foss.global/serve.zone/cloudly:latest`
|
||||||
|
|
||||||
- Note: the exports are defined in the package.json.
|
- Note: the exports are defined in the package.json.
|
||||||
|
- For now, cloud wise only the setup with cloudron and hetzner cloud is supported.
|
@ -1,6 +1,6 @@
|
|||||||
# @serve.zone/cloudly
|
# @serve.zone/cloudly
|
||||||
|
|
||||||
A comprehensive multi-cloud manager leveraging Docker Swarmkit for orchestrating containerized applications and integrating various cloud services like DigitalOcean, Hetzner Cloud, and Cloudflare, with robust configuration and API management capabilities.
|
A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and integrate robust configuration and API management capabilities.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
27
test/helpers/cloudlyfactory.ts
Normal file
27
test/helpers/cloudlyfactory.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { Qenv } from '@push.rocks/qenv';
|
||||||
|
const testQenv = new Qenv('./', './.nogit/');
|
||||||
|
|
||||||
|
import * as cloudly from '../../ts/index.js';
|
||||||
|
|
||||||
|
export const createCloudly = async () => {
|
||||||
|
const cloudlyConfig: cloudly.ICloudlyConfig = {
|
||||||
|
cfToken: await testQenv.getEnvVarOnDemand('CF_TOKEN'),
|
||||||
|
environment: 'integration',
|
||||||
|
letsEncryptEmail: await testQenv.getEnvVarOnDemand('LETSENCRYPT_EMAIL'),
|
||||||
|
publicUrl: await testQenv.getEnvVarOnDemand('SERVEZONE_URL'),
|
||||||
|
publicPort: await testQenv.getEnvVarOnDemand('SERVEZONE_PORT'),
|
||||||
|
mongoDescriptor: {
|
||||||
|
mongoDbName: await testQenv.getEnvVarOnDemand('MONGODB_DATABASE'),
|
||||||
|
mongoDbUser: await testQenv.getEnvVarOnDemand('MONGODB_USER'),
|
||||||
|
mongoDbPass: await testQenv.getEnvVarOnDemand('MONGODB_PASSWORD'),
|
||||||
|
mongoDbUrl: await testQenv.getEnvVarOnDemand('MONGODB_URL'),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const cloudlyInstance = new cloudly.Cloudly();
|
||||||
|
return cloudlyInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getEnvVarOnDemand = async (envVarName: string) => {
|
||||||
|
return testQenv.getEnvVarOnDemand(envVarName);
|
||||||
|
}
|
||||||
|
|
9
test/helpers/docker.ts
Normal file
9
test/helpers/docker.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import * as smartstream from '@push.rocks/smartstream';
|
||||||
|
import * as smartpath from '@push.rocks/smartpath';
|
||||||
|
|
||||||
|
export const getAlpineImageReadableStream = async () => {
|
||||||
|
const currentDir = smartpath.get.dirnameFromImportMetaUrl(import.meta.url);
|
||||||
|
const imagePath = smartpath.join(currentDir, '../../.nogit/testfiles/alpine.tar');
|
||||||
|
const readableStream = smartstream.nodewebhelpers.createWebReadableStreamFromFile(imagePath);
|
||||||
|
return readableStream;
|
||||||
|
}
|
2
test/helpers/index.ts
Normal file
2
test/helpers/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './cloudlyfactory.js';
|
||||||
|
export * from './docker.js';
|
@ -1,24 +1,80 @@
|
|||||||
import { tap, expect } from '@push.rocks/tapbundle';
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
import * as helpers from './helpers/index.js';
|
||||||
|
|
||||||
|
import * as cloudly from '../ts/index.js';
|
||||||
import * as cloudlyApiClient from '../ts_apiclient/index.js';
|
import * as cloudlyApiClient from '../ts_apiclient/index.js';
|
||||||
|
import { Image } from '../ts_apiclient/classes.image.js';
|
||||||
|
|
||||||
|
let testCloudly: cloudly.Cloudly;
|
||||||
let testClient: cloudlyApiClient.CloudlyApiClient;
|
let testClient: cloudlyApiClient.CloudlyApiClient;
|
||||||
|
|
||||||
|
tap.preTask('should start cloudly', async () => {
|
||||||
|
testCloudly = await helpers.createCloudly();
|
||||||
|
await testCloudly.start();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.preTask('should create a new machine user for testing', async () => {
|
||||||
|
const machineUser = new testCloudly.authManager.CUser();
|
||||||
|
machineUser.id = await testCloudly.authManager.CUser.getNewId();
|
||||||
|
machineUser.data = {
|
||||||
|
type: 'machine',
|
||||||
|
username: 'test',
|
||||||
|
password: 'test',
|
||||||
|
tokens: [{
|
||||||
|
token: 'test',
|
||||||
|
expiresAt: Date.now() + 3600 * 1000 * 24 * 365,
|
||||||
|
assignedRoles: ['admin'],
|
||||||
|
}],
|
||||||
|
role: 'admin',
|
||||||
|
};
|
||||||
|
await machineUser.save();
|
||||||
|
});
|
||||||
|
|
||||||
tap.test('should create a new cloudlyApiClient', async () => {
|
tap.test('should create a new cloudlyApiClient', async () => {
|
||||||
testClient = new cloudlyApiClient.CloudlyApiClient({
|
testClient = new cloudlyApiClient.CloudlyApiClient({
|
||||||
registerAs: 'api',
|
registerAs: 'api',
|
||||||
cloudlyUrl: 'http://localhost:3000',
|
cloudlyUrl: `http://localhost:${await helpers.getEnvVarOnDemand('SERVEZONE_PORT')}`,
|
||||||
});
|
});
|
||||||
await testClient.start();
|
await testClient.start();
|
||||||
expect(testClient).toBeTruthy();
|
expect(testClient).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should trigger a server action', async () => {
|
tap.test('create a new machine user', async () => {
|
||||||
|
const machineUser = await testCloudly.authManager.CUser.createMachineUser('test', 'api');
|
||||||
|
machineUser.data.tokens.push({
|
||||||
|
token: 'test',
|
||||||
|
expiresAt: Date.now() + 3600 * 1000 * 24 * 365,
|
||||||
|
assignedRoles: ['api'],
|
||||||
|
})
|
||||||
|
await machineUser.save();
|
||||||
})
|
})
|
||||||
|
|
||||||
tap.test('should stop the apiclient', async () => {
|
tap.test('should get an identity', async () => {
|
||||||
|
const identity = await testClient.getIdentityByToken('test');
|
||||||
|
expect(identity).toBeTruthy();
|
||||||
|
console.log(identity);
|
||||||
|
});
|
||||||
|
|
||||||
|
let image: Image;
|
||||||
|
tap.test('should create and upload an image', async () => {
|
||||||
|
image = await testClient.images.createImage({
|
||||||
|
name: 'test',
|
||||||
|
description: 'test'
|
||||||
|
});
|
||||||
|
console.log('created image: ', image);
|
||||||
|
expect(image).toBeInstanceOf(Image);
|
||||||
|
})
|
||||||
|
|
||||||
|
tap.test('should upload an image version', async () => {
|
||||||
|
const imageStream = await helpers.getAlpineImageReadableStream();
|
||||||
|
|
||||||
|
await image.pushImageVersion('v1.0.0', imageStream);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should stop the apiclient', async (toolsArg) => {
|
||||||
|
await toolsArg.delayFor(10000);
|
||||||
await testClient.stop();
|
await testClient.stop();
|
||||||
|
await testCloudly.stop();
|
||||||
})
|
})
|
||||||
|
|
||||||
export default tap.start();
|
export default tap.start();
|
21
test/test.ts
21
test/test.ts
@ -1,28 +1,11 @@
|
|||||||
import { expect, tap } from '@push.rocks/tapbundle';
|
import { expect, tap } from '@push.rocks/tapbundle';
|
||||||
import { Qenv } from '@push.rocks/qenv';
|
import * as helpers from './helpers/index.js';
|
||||||
const testQenv = new Qenv('./', './.nogit/');
|
|
||||||
process.env.TESTING_CLOUDLY = 'true';
|
|
||||||
|
|
||||||
delete process.env.CLI_CALL;
|
|
||||||
|
|
||||||
import * as cloudly from '../ts/index.js';
|
import * as cloudly from '../ts/index.js';
|
||||||
|
|
||||||
let testCloudly: cloudly.Cloudly;
|
let testCloudly: cloudly.Cloudly;
|
||||||
tap.test('first test', async () => {
|
tap.test('first test', async () => {
|
||||||
const cloudlyConfig: cloudly.ICloudlyConfig = {
|
testCloudly = await helpers.createCloudly();
|
||||||
cfToken: await testQenv.getEnvVarOnDemand('CF_TOKEN'),
|
|
||||||
environment: 'integration',
|
|
||||||
letsEncryptEmail: await testQenv.getEnvVarOnDemand('LETSENCRYPT_EMAIL'),
|
|
||||||
publicUrl: await testQenv.getEnvVarOnDemand('SERVEZONE_URL'),
|
|
||||||
publicPort: await testQenv.getEnvVarOnDemand('SERVEZONE_PORT'),
|
|
||||||
mongoDescriptor: {
|
|
||||||
mongoDbName: await testQenv.getEnvVarOnDemand('MONGODB_DATABASE'),
|
|
||||||
mongoDbUser: await testQenv.getEnvVarOnDemand('MONGODB_USER'),
|
|
||||||
mongoDbPass: await testQenv.getEnvVarOnDemand('MONGODB_PASSWORD'),
|
|
||||||
mongoDbUrl: await testQenv.getEnvVarOnDemand('MONGODB_URL'),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
testCloudly = new cloudly.Cloudly();
|
|
||||||
expect(testCloudly).toBeInstanceOf(cloudly.Cloudly);
|
expect(testCloudly).toBeInstanceOf(cloudly.Cloudly);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* autocreated commitinfo by @pushrocks/commitinfo
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/cloudly',
|
name: '@serve.zone/cloudly',
|
||||||
version: '1.1.5',
|
version: '1.2.5',
|
||||||
description: 'A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and integrate robust configuration and API management capabilities.'
|
description: 'A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.'
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ export const getUsers = async (cloudlyRef: Cloudly) => {
|
|||||||
users.push({
|
users.push({
|
||||||
id: 'envadmin',
|
id: 'envadmin',
|
||||||
data: {
|
data: {
|
||||||
|
type: 'human',
|
||||||
username: envAdminUser.split(':')[0],
|
username: envAdminUser.split(':')[0],
|
||||||
password: envAdminUser.split(':')[1],
|
password: envAdminUser.split(':')[1],
|
||||||
role: 'admin',
|
role: 'admin',
|
||||||
|
@ -17,7 +17,7 @@ import { MongodbConnector } from './connector.mongodb/connector.js';
|
|||||||
import { CloudlyCoreflowManager } from './manager.coreflow/coreflowmanager.js';
|
import { CloudlyCoreflowManager } from './manager.coreflow/coreflowmanager.js';
|
||||||
import { ClusterManager } from './manager.cluster/classes.clustermanager.js';
|
import { ClusterManager } from './manager.cluster/classes.clustermanager.js';
|
||||||
import { CloudlyTaskmanager } from './manager.task/taskmanager.js';
|
import { CloudlyTaskmanager } from './manager.task/taskmanager.js';
|
||||||
import { CloudlySecretManager } from './manager.secret/classes.secretmanager.js'
|
import { CloudlySecretManager } from './manager.secret/classes.secretmanager.js';
|
||||||
import { CloudlyServerManager } from './manager.server/classes.servermanager.js';
|
import { CloudlyServerManager } from './manager.server/classes.servermanager.js';
|
||||||
import { ExternalApiManager } from './manager.status/statusmanager.js';
|
import { ExternalApiManager } from './manager.status/statusmanager.js';
|
||||||
import { ImageManager } from './manager.image/classes.imagemanager.js';
|
import { ImageManager } from './manager.image/classes.imagemanager.js';
|
||||||
|
@ -9,15 +9,16 @@ import type { Cloudly } from './classes.cloudly.js';
|
|||||||
export class CloudlyConfig {
|
export class CloudlyConfig {
|
||||||
public cloudlyRef: Cloudly;
|
public cloudlyRef: Cloudly;
|
||||||
public appData: plugins.npmextra.AppData<plugins.servezoneInterfaces.data.ICloudlyConfig>;
|
public appData: plugins.npmextra.AppData<plugins.servezoneInterfaces.data.ICloudlyConfig>;
|
||||||
public data: plugins.servezoneInterfaces.data.ICloudlyConfig
|
public data: plugins.servezoneInterfaces.data.ICloudlyConfig;
|
||||||
|
|
||||||
|
|
||||||
constructor(cloudlyRefArg: Cloudly) {
|
constructor(cloudlyRefArg: Cloudly) {
|
||||||
this.cloudlyRef = cloudlyRefArg;
|
this.cloudlyRef = cloudlyRefArg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async init() {
|
public async init() {
|
||||||
this.appData = await plugins.npmextra.AppData.createAndInit<plugins.servezoneInterfaces.data.ICloudlyConfig>({
|
this.appData =
|
||||||
|
await plugins.npmextra.AppData.createAndInit<plugins.servezoneInterfaces.data.ICloudlyConfig>(
|
||||||
|
{
|
||||||
envMapping: {
|
envMapping: {
|
||||||
cfToken: 'CF_TOKEN',
|
cfToken: 'CF_TOKEN',
|
||||||
environment: 'SERVEZONE_ENVIRONMENT' as 'production' | 'integration',
|
environment: 'SERVEZONE_ENVIRONMENT' as 'production' | 'integration',
|
||||||
@ -39,7 +40,8 @@ export class CloudlyConfig {
|
|||||||
port: 'S3_PORT', // Note: This will remain as a string. Ensure to parse it to an integer where it's used.
|
port: 'S3_PORT', // Note: This will remain as a string. Ensure to parse it to an integer where it's used.
|
||||||
useSsl: true,
|
useSsl: true,
|
||||||
},
|
},
|
||||||
sslMode: 'SERVEZONE_SSLMODE' as plugins.servezoneInterfaces.data.ICloudlyConfig['sslMode'],
|
sslMode:
|
||||||
|
'SERVEZONE_SSLMODE' as plugins.servezoneInterfaces.data.ICloudlyConfig['sslMode'],
|
||||||
servezoneAdminaccount: 'SERVEZONE_ADMINACCOUNT',
|
servezoneAdminaccount: 'SERVEZONE_ADMINACCOUNT',
|
||||||
},
|
},
|
||||||
requiredKeys: [
|
requiredKeys: [
|
||||||
@ -52,7 +54,8 @@ export class CloudlyConfig {
|
|||||||
'environment',
|
'environment',
|
||||||
'mongoDescriptor',
|
'mongoDescriptor',
|
||||||
],
|
],
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const kvStore = await this.appData.getKvStore();
|
const kvStore = await this.appData.getKvStore();
|
||||||
|
|
||||||
|
@ -45,16 +45,16 @@ export class CloudlyServer {
|
|||||||
logger.log('info', `Using letsencrypt for ssl mode. Trying to obtain a certificate...`);
|
logger.log('info', `Using letsencrypt for ssl mode. Trying to obtain a certificate...`);
|
||||||
logger.log('info', `This might take 10 minutes...`);
|
logger.log('info', `This might take 10 minutes...`);
|
||||||
sslCert = await this.cloudlyRef.letsencryptConnector.getCertificateForDomain(
|
sslCert = await this.cloudlyRef.letsencryptConnector.getCertificateForDomain(
|
||||||
this.cloudlyRef.config.data.publicUrl
|
this.cloudlyRef.config.data.publicUrl,
|
||||||
);
|
);
|
||||||
logger.log(
|
logger.log(
|
||||||
'success',
|
'success',
|
||||||
`Successfully obtained certificate for cloudly domain ${this.cloudlyRef.config.data.publicUrl}`
|
`Successfully obtained certificate for cloudly domain ${this.cloudlyRef.config.data.publicUrl}`,
|
||||||
);
|
);
|
||||||
} else if (this.cloudlyRef.config.data.sslMode === 'external') {
|
} else if (this.cloudlyRef.config.data.sslMode === 'external') {
|
||||||
logger.log(
|
logger.log(
|
||||||
'info',
|
'info',
|
||||||
`Using external certificate for ssl mode, meaning cloudly is not in charge of ssl termination.`
|
`Using external certificate for ssl mode, meaning cloudly is not in charge of ssl termination.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ export class CloudlyServer {
|
|||||||
this.typedServer.typedrouter.addTypedRouter(this.typedrouter);
|
this.typedServer.typedrouter.addTypedRouter(this.typedrouter);
|
||||||
this.typedServer.server.addRoute(
|
this.typedServer.server.addRoute(
|
||||||
'/curlfresh/:scriptname',
|
'/curlfresh/:scriptname',
|
||||||
this.cloudlyRef.serverManager.curlfreshInstance.handler
|
this.cloudlyRef.serverManager.curlfreshInstance.handler,
|
||||||
);
|
);
|
||||||
await this.typedServer.start();
|
await this.typedServer.start();
|
||||||
}
|
}
|
||||||
|
@ -24,19 +24,19 @@ export class LetsencryptConnector {
|
|||||||
environment: this.cloudlyRef.config.data.environment,
|
environment: this.cloudlyRef.config.data.environment,
|
||||||
setChallenge: async (dnsChallenge) => {
|
setChallenge: async (dnsChallenge) => {
|
||||||
await this.cloudlyRef.cloudflareConnector.cloudflare.convenience.acmeSetDnsChallenge(
|
await this.cloudlyRef.cloudflareConnector.cloudflare.convenience.acmeSetDnsChallenge(
|
||||||
dnsChallenge
|
dnsChallenge,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
removeChallenge: async (dnsChallenge) => {
|
removeChallenge: async (dnsChallenge) => {
|
||||||
await this.cloudlyRef.cloudflareConnector.cloudflare.convenience.acmeRemoveDnsChallenge(
|
await this.cloudlyRef.cloudflareConnector.cloudflare.convenience.acmeRemoveDnsChallenge(
|
||||||
dnsChallenge
|
dnsChallenge,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
mongoDescriptor: this.cloudlyRef.config.data.mongoDescriptor,
|
mongoDescriptor: this.cloudlyRef.config.data.mongoDescriptor,
|
||||||
});
|
});
|
||||||
await this.smartacme.init().catch(err => {
|
await this.smartacme.start().catch((err) => {
|
||||||
console.error('error in init', err);
|
console.error('error in init', err);
|
||||||
console.log(`trying again in a few minutes`)
|
console.log(`trying again in a few minutes`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,9 @@ export class MongodbConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async init() {
|
public async init() {
|
||||||
this.smartdataDb = new plugins.smartdata.SmartdataDb(this.cloudlyRef.config.data.mongoDescriptor);
|
this.smartdataDb = new plugins.smartdata.SmartdataDb(
|
||||||
|
this.cloudlyRef.config.data.mongoDescriptor,
|
||||||
|
);
|
||||||
await this.smartdataDb.init();
|
await this.smartdataDb.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import { logger } from './logger.js';
|
|||||||
const cloudlyQenv = new plugins.qenv.Qenv(paths.packageDir, paths.nogitDir, true);
|
const cloudlyQenv = new plugins.qenv.Qenv(paths.packageDir, paths.nogitDir, true);
|
||||||
early.stop();
|
early.stop();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* starts the cloudly instance
|
* starts the cloudly instance
|
||||||
*/
|
*/
|
||||||
@ -17,7 +16,7 @@ const runCli = async () => {
|
|||||||
|
|
||||||
logger.log(
|
logger.log(
|
||||||
'info',
|
'info',
|
||||||
`running in environment ${await cloudlyQenv.getEnvVarOnDemand('SERVEZONE_ENVIRONMENT')}`
|
`running in environment ${await cloudlyQenv.getEnvVarOnDemand('SERVEZONE_ENVIRONMENT')}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await cloudlyInstance.start();
|
await cloudlyInstance.start();
|
||||||
@ -27,4 +26,4 @@ const runCli = async () => {
|
|||||||
|
|
||||||
export { runCli, Cloudly };
|
export { runCli, Cloudly };
|
||||||
type ICloudlyConfig = plugins.servezoneInterfaces.data.ICloudlyConfig;
|
type ICloudlyConfig = plugins.servezoneInterfaces.data.ICloudlyConfig;
|
||||||
export { type ICloudlyConfig }
|
export { type ICloudlyConfig };
|
||||||
|
@ -9,8 +9,8 @@ export const logger = new plugins.smartlog.Smartlog({
|
|||||||
zone: null,
|
zone: null,
|
||||||
companyunit: null,
|
companyunit: null,
|
||||||
containerName: null,
|
containerName: null,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
logger.enableConsole({
|
logger.enableConsole({
|
||||||
captureAll: false
|
captureAll: false,
|
||||||
});
|
});
|
||||||
|
@ -5,14 +5,14 @@ import { logger } from '../logger.js';
|
|||||||
import { Authorization } from './classes.authorization.js';
|
import { Authorization } from './classes.authorization.js';
|
||||||
import { User } from './classes.user.js';
|
import { User } from './classes.user.js';
|
||||||
|
|
||||||
|
|
||||||
export interface IJwtData {
|
export interface IJwtData {
|
||||||
userId: string;
|
userId: string;
|
||||||
status: 'loggedIn' | 'loggedOut';
|
status: 'loggedIn' | 'loggedOut';
|
||||||
|
expiresAt: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CloudlyAuthManager {
|
export class CloudlyAuthManager {
|
||||||
cloudlyRef: Cloudly
|
cloudlyRef: Cloudly;
|
||||||
public get db() {
|
public get db() {
|
||||||
return this.cloudlyRef.mongodbConnector.smartdataDb;
|
return this.cloudlyRef.mongodbConnector.smartdataDb;
|
||||||
}
|
}
|
||||||
@ -27,18 +27,24 @@ export class CloudlyAuthManager {
|
|||||||
this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter);
|
this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async createNewSecureToken() {
|
||||||
|
return plugins.smartunique.uniSimple('secureToken', 64);
|
||||||
|
}
|
||||||
|
|
||||||
public async start() {
|
public async start() {
|
||||||
// lets setup the smartjwtInstance
|
// lets setup the smartjwtInstance
|
||||||
this.smartjwtInstance = new plugins.smartjwt.SmartJwt();
|
this.smartjwtInstance = new plugins.smartjwt.SmartJwt();
|
||||||
await this.smartjwtInstance.init();
|
await this.smartjwtInstance.init();
|
||||||
const kvStore = await this.cloudlyRef.config.appData.getKvStore();
|
const kvStore = await this.cloudlyRef.config.appData.getKvStore();
|
||||||
|
|
||||||
const existingJwtKeys: plugins.tsclass.network.IJwtKeypair = await kvStore.readKey('jwtKeys');
|
const existingJwtKeys: plugins.tsclass.network.IJwtKeypair = (await kvStore.readKey(
|
||||||
|
'jwtKeypair',
|
||||||
|
)) as plugins.tsclass.network.IJwtKeypair;
|
||||||
|
|
||||||
if (!existingJwtKeys) {
|
if (!existingJwtKeys) {
|
||||||
await this.smartjwtInstance.createNewKeyPair();
|
await this.smartjwtInstance.createNewKeyPair();
|
||||||
const newJwtKeys = this.smartjwtInstance.getKeyPairAsJson();
|
const newJwtKeys = this.smartjwtInstance.getKeyPairAsJson();
|
||||||
await kvStore.writeKey('jwtKeys', newJwtKeys);
|
await kvStore.writeKey('jwtKeypair', newJwtKeys);
|
||||||
} else {
|
} else {
|
||||||
this.smartjwtInstance.setKeyPairAsJson(existingJwtKeys);
|
this.smartjwtInstance.setKeyPairAsJson(existingJwtKeys);
|
||||||
}
|
}
|
||||||
@ -48,34 +54,84 @@ export class CloudlyAuthManager {
|
|||||||
'adminLoginWithUsernameAndPassword',
|
'adminLoginWithUsernameAndPassword',
|
||||||
async (dataArg) => {
|
async (dataArg) => {
|
||||||
let jwt: string;
|
let jwt: string;
|
||||||
|
let expiresAtTimestamp: number = Date.now() + 3600 * 1000 * 24 * 7;
|
||||||
const user = await User.findUserByUsernameAndPassword(dataArg.username, dataArg.password);
|
const user = await User.findUserByUsernameAndPassword(dataArg.username, dataArg.password);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
logger.log('warn', 'login failed');
|
logger.log('warn', 'login failed');
|
||||||
|
throw new plugins.typedrequest.TypedResponseError('login failed');
|
||||||
} else {
|
} else {
|
||||||
jwt = await this.smartjwtInstance.createJWT({
|
jwt = await this.smartjwtInstance.createJWT({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
status: 'loggedIn',
|
status: 'loggedIn',
|
||||||
|
expiresAt: expiresAtTimestamp,
|
||||||
});
|
});
|
||||||
logger.log('success', 'login successful');
|
logger.log('success', 'login successful');
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
identity: {
|
||||||
jwt,
|
jwt,
|
||||||
|
userId: user.id,
|
||||||
|
name: user.data.username,
|
||||||
|
expiresAt: expiresAtTimestamp,
|
||||||
|
role: user.data.role,
|
||||||
|
type: user.data.type,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async stop () {}
|
public async stop() {}
|
||||||
|
|
||||||
public adminJwtGuard = new plugins.smartguard.Guard<{jwt: string}>(async (dataArg) => {
|
public validIdentityGuard = new plugins.smartguard.Guard<{
|
||||||
const jwt = dataArg.jwt;
|
identity: plugins.servezoneInterfaces.data.IIdentity;
|
||||||
|
}>(
|
||||||
|
async (dataArg) => {
|
||||||
|
const jwt = dataArg.identity.jwt;
|
||||||
const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt);
|
const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt);
|
||||||
const user = await this.CUser.getInstance({id: jwtData.userId});
|
const expired = jwtData.expiresAt < Date.now();
|
||||||
|
plugins.smartexpect
|
||||||
|
.expect(jwtData.status)
|
||||||
|
.setFailMessage('user not logged in')
|
||||||
|
.toEqual('loggedIn');
|
||||||
|
plugins.smartexpect.expect(expired).setFailMessage(`jwt expired`).toBeFalse();
|
||||||
|
plugins.smartexpect
|
||||||
|
.expect(dataArg.identity.expiresAt)
|
||||||
|
.setFailMessage(
|
||||||
|
`expiresAt >>identity valid until:${dataArg.identity.expiresAt}, but jwt says: ${jwtData.expiresAt}<< has been tampered with`,
|
||||||
|
)
|
||||||
|
.toEqual(jwtData.expiresAt);
|
||||||
|
plugins.smartexpect
|
||||||
|
.expect(dataArg.identity.userId)
|
||||||
|
.setFailMessage('userId has been tampered with')
|
||||||
|
.toEqual(jwtData.userId);
|
||||||
|
if (expired) {
|
||||||
|
throw new Error('identity is expired');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
failedHint: 'identity is not valid.',
|
||||||
|
name: 'validIdentityGuard',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
public adminIdentityGuard = new plugins.smartguard.Guard<{
|
||||||
|
identity: plugins.servezoneInterfaces.data.IIdentity;
|
||||||
|
}>(
|
||||||
|
async (dataArg) => {
|
||||||
|
await plugins.smartguard.passGuardsOrReject(dataArg, [this.validIdentityGuard]);
|
||||||
|
const jwt = dataArg.identity.jwt;
|
||||||
|
const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt);
|
||||||
|
const user = await this.CUser.getInstance({ id: jwtData.userId });
|
||||||
const isAdminBool = user.data.role === 'admin';
|
const isAdminBool = user.data.role === 'admin';
|
||||||
console.log(`user is admin: ${isAdminBool}`);
|
console.log(`user is admin: ${isAdminBool}`);
|
||||||
return isAdminBool;
|
return isAdminBool;
|
||||||
}, {
|
},
|
||||||
failedHint: 'user is not admin.'
|
{
|
||||||
})
|
failedHint: 'user is not admin.',
|
||||||
|
name: 'adminIdentityGuard',
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
@ -1,6 +1,4 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
@plugins.smartdata.managed()
|
@plugins.smartdata.managed()
|
||||||
export class Authorization extends plugins.smartdata.SmartDataDbDoc<Authorization, Authorization> {
|
export class Authorization extends plugins.smartdata.SmartDataDbDoc<Authorization, Authorization> {}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -5,6 +5,28 @@ export class User extends plugins.smartdata.SmartDataDbDoc<
|
|||||||
User,
|
User,
|
||||||
plugins.servezoneInterfaces.data.IUser
|
plugins.servezoneInterfaces.data.IUser
|
||||||
> {
|
> {
|
||||||
|
/**
|
||||||
|
* creates a machine user
|
||||||
|
*/
|
||||||
|
public static async createMachineUser(userNameArg: string, roleArg: 'api' | 'cluster') {
|
||||||
|
const user = new User();
|
||||||
|
user.id = await User.getNewId();
|
||||||
|
user.data = {
|
||||||
|
type: 'machine',
|
||||||
|
username: userNameArg,
|
||||||
|
tokens: [
|
||||||
|
{
|
||||||
|
token: 'machineUser',
|
||||||
|
expiresAt: Date.now() + 3600 * 1000 * 24 * 365,
|
||||||
|
assignedRoles: ['admin'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
role: 'api',
|
||||||
|
};
|
||||||
|
await user.save();
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
public static async findUserByUsernameAndPassword(usernameArg: string, passwordArg: string) {
|
public static async findUserByUsernameAndPassword(usernameArg: string, passwordArg: string) {
|
||||||
return await User.getInstance({
|
return await User.getInstance({
|
||||||
data: {
|
data: {
|
||||||
@ -14,14 +36,17 @@ export class User extends plugins.smartdata.SmartDataDbDoc<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor(optionsArg?: plugins.servezoneInterfaces.data.IUser) {
|
||||||
|
super();
|
||||||
|
if (optionsArg) {
|
||||||
|
Object.assign(this, optionsArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// INSTANCE
|
// INSTANCE
|
||||||
@plugins.smartdata.unI()
|
@plugins.smartdata.unI()
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@plugins.smartdata.svDb()
|
@plugins.smartdata.svDb()
|
||||||
public data: {
|
public data: plugins.servezoneInterfaces.data.IUser['data'];
|
||||||
role: 'admin' | 'user';
|
|
||||||
username: string;
|
|
||||||
password: string;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
export class Cert extends plugins.smartdata.SmartDataDbDoc<> {
|
export class Cert extends plugins.smartdata.SmartDataDbDoc<Cert, Cert> {}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -4,11 +4,12 @@ import * as plugins from '../plugins.js';
|
|||||||
* cluster defines a swarmkit cluster
|
* cluster defines a swarmkit cluster
|
||||||
*/
|
*/
|
||||||
@plugins.smartdata.managed()
|
@plugins.smartdata.managed()
|
||||||
export class Cluster extends plugins.smartdata.SmartDataDbDoc<Cluster, plugins.servezoneInterfaces.data.ICluster> {
|
export class Cluster extends plugins.smartdata.SmartDataDbDoc<
|
||||||
|
Cluster,
|
||||||
|
plugins.servezoneInterfaces.data.ICluster
|
||||||
|
> {
|
||||||
// STATIC
|
// STATIC
|
||||||
public static async fromConfigObject(
|
public static async fromConfigObject(configObjectArg: plugins.servezoneInterfaces.data.ICluster) {
|
||||||
configObjectArg: plugins.servezoneInterfaces.data.ICluster
|
|
||||||
) {
|
|
||||||
const newCluster = new Cluster();
|
const newCluster = new Cluster();
|
||||||
Object.assign(newCluster, configObjectArg);
|
Object.assign(newCluster, configObjectArg);
|
||||||
return newCluster;
|
return newCluster;
|
||||||
|
@ -4,6 +4,7 @@ import { Cloudly } from '../classes.cloudly.js';
|
|||||||
import { logger } from '../logger.js';
|
import { logger } from '../logger.js';
|
||||||
|
|
||||||
import { Cluster } from './classes.cluster.js';
|
import { Cluster } from './classes.cluster.js';
|
||||||
|
import { data } from '@serve.zone/interfaces';
|
||||||
|
|
||||||
export class ClusterManager {
|
export class ClusterManager {
|
||||||
public ready = plugins.smartpromise.defer();
|
public ready = plugins.smartpromise.defer();
|
||||||
@ -22,12 +23,12 @@ export class ClusterManager {
|
|||||||
|
|
||||||
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_CreateCluster>(
|
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_CreateCluster>(
|
||||||
new plugins.typedrequest.TypedHandler('createCluster', async (dataArg) => {
|
new plugins.typedrequest.TypedHandler('createCluster', async (dataArg) => {
|
||||||
const cluster = await this.storeCluster({
|
// TODO: guards
|
||||||
|
const cluster = await this.createCluster({
|
||||||
id: plugins.smartunique.uniSimple('cluster'),
|
id: plugins.smartunique.uniSimple('cluster'),
|
||||||
data: {
|
data: {
|
||||||
|
userId: null, // this is created by the createCluster method
|
||||||
name: dataArg.clusterName,
|
name: dataArg.clusterName,
|
||||||
jumpCode: plugins.smartunique.uniSimple('cluster'),
|
|
||||||
jumpCodeUsedAt: null,
|
|
||||||
acmeInfo: null,
|
acmeInfo: null,
|
||||||
cloudlyUrl: `https://${this.cloudlyRef.config.data.publicUrl}:${this.cloudlyRef.config.data.publicPort}/`,
|
cloudlyUrl: `https://${this.cloudlyRef.config.data.publicUrl}:${this.cloudlyRef.config.data.publicPort}/`,
|
||||||
servers: [],
|
servers: [],
|
||||||
@ -39,7 +40,7 @@ export class ClusterManager {
|
|||||||
return {
|
return {
|
||||||
clusterConfig: await cluster.createSavableObject(),
|
clusterConfig: await cluster.createSavableObject(),
|
||||||
};
|
};
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_GetAllClusters>(
|
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_GetAllClusters>(
|
||||||
@ -48,21 +49,21 @@ export class ClusterManager {
|
|||||||
const clusters = await this.getAllClusters();
|
const clusters = await this.getAllClusters();
|
||||||
return {
|
return {
|
||||||
clusters: await Promise.all(
|
clusters: await Promise.all(
|
||||||
clusters.map((clusterArg) => clusterArg.createSavableObject())
|
clusters.map((clusterArg) => clusterArg.createSavableObject()),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// delete cluster
|
// delete cluster
|
||||||
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_DeleteCluster>(
|
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_DeleteCluster>(
|
||||||
new plugins.typedrequest.TypedHandler('deleteCluster', async (reqDataArg, toolsArg) => {
|
new plugins.typedrequest.TypedHandler('deleteCluster', async (reqDataArg, toolsArg) => {
|
||||||
await toolsArg.passGuards([this.cloudlyRef.authManager.adminJwtGuard], reqDataArg);
|
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqDataArg);
|
||||||
await this.deleteCluster(reqDataArg.clusterId);
|
await this.deleteCluster(reqDataArg.clusterId);
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
};
|
};
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,25 +81,22 @@ export class ClusterManager {
|
|||||||
// TODO: implement getclusterConfigByServerIp
|
// TODO: implement getclusterConfigByServerIp
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getClusterConfigBy_JumpCode(jumpCodeArg: string) {
|
public async getClusterBy_UserId(userIdArg: string) {
|
||||||
await this.ready.promise;
|
await this.ready.promise;
|
||||||
|
|
||||||
return await Cluster.getInstance({
|
return await Cluster.getInstance({
|
||||||
data: {
|
data: {
|
||||||
jumpCode: jumpCodeArg,
|
userId: userIdArg,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getClusterConfigBy_ClusterIdentifier(
|
public async getClusterBy_Identity(clusterIdentity: plugins.servezoneInterfaces.data.IIdentity) {
|
||||||
clusterIdentifier: plugins.servezoneInterfaces.data.IClusterIdentifier
|
|
||||||
) {
|
|
||||||
await this.ready.promise;
|
await this.ready.promise;
|
||||||
|
|
||||||
return await Cluster.getInstance({
|
return await Cluster.getInstance({
|
||||||
id: clusterIdentifier.clusterId,
|
|
||||||
data: {
|
data: {
|
||||||
name: clusterIdentifier.clusterName,
|
userId: clusterIdentity.userId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -124,17 +122,32 @@ export class ClusterManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* allows storage of a config
|
* creates a cluster (and a new user for it) and saves it
|
||||||
* @param configName
|
* @param configName
|
||||||
* @param configObjectArg
|
* @param configObjectArg
|
||||||
*/
|
*/
|
||||||
public async storeCluster(configObjectArg: plugins.servezoneInterfaces.data.ICluster) {
|
public async createCluster(configObjectArg: plugins.servezoneInterfaces.data.ICluster) {
|
||||||
let clusterInstance = await Cluster.getInstance({ id: configObjectArg.id });
|
// TODO: guards
|
||||||
if (!clusterInstance) {
|
// lets create the cluster user
|
||||||
clusterInstance = await Cluster.fromConfigObject(configObjectArg);
|
const clusterUser = new this.cloudlyRef.authManager.CUser({
|
||||||
} else {
|
id: await this.cloudlyRef.authManager.CUser.getNewId(),
|
||||||
Object.assign(clusterInstance, configObjectArg);
|
data: {
|
||||||
}
|
role: 'cluster',
|
||||||
|
type: 'machine',
|
||||||
|
tokens: [
|
||||||
|
{
|
||||||
|
expiresAt: Date.now() + 3600 * 1000 * 24 * 365,
|
||||||
|
assignedRoles: ['cluster'],
|
||||||
|
token: await this.cloudlyRef.authManager.createNewSecureToken(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await clusterUser.save();
|
||||||
|
Object.assign(configObjectArg, {
|
||||||
|
userId: clusterUser.id,
|
||||||
|
});
|
||||||
|
const clusterInstance = await Cluster.fromConfigObject(configObjectArg);
|
||||||
await clusterInstance.save();
|
await clusterInstance.save();
|
||||||
return clusterInstance;
|
return clusterInstance;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
import { Cloudly } from '../classes.cloudly.js';
|
import { Cloudly } from '../classes.cloudly.js';
|
||||||
|
import type { Cluster } from '../manager.cluster/classes.cluster.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* in charge of talking to coreflow services on clusters
|
* in charge of talking to coreflow services on clusters
|
||||||
@ -13,28 +14,54 @@ export class CloudlyCoreflowManager {
|
|||||||
this.cloudlyRef = cloudlyRefArg;
|
this.cloudlyRef = cloudlyRefArg;
|
||||||
this.cloudlyRef.typedrouter.addTypedRouter(this.typedRouter);
|
this.cloudlyRef.typedrouter.addTypedRouter(this.typedRouter);
|
||||||
|
|
||||||
this.typedRouter.addTypedHandler<plugins.servezoneInterfaces.requests.identity.IRequest_Any_Cloudly_CoreflowManager_GetIdentityByJumpCode>(
|
this.typedRouter.addTypedHandler<plugins.servezoneInterfaces.requests.identity.IRequest_Any_Cloudly_CoreflowManager_GetIdentityByToken>(
|
||||||
new plugins.typedrequest.TypedHandler('getIdentityByJumpCode', async (requestData) => {
|
new plugins.typedrequest.TypedHandler('getIdentityByToken', async (requestData) => {
|
||||||
const clusterConfig =
|
const user = await this.cloudlyRef.authManager.CUser.getInstance({
|
||||||
await this.cloudlyRef.clusterManager.getClusterConfigBy_JumpCode(
|
data: {
|
||||||
requestData.jumpCode
|
tokens: [
|
||||||
|
{
|
||||||
|
token: requestData.token,
|
||||||
|
},
|
||||||
|
], // find the proper user here.
|
||||||
|
} as any,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw new plugins.typedrequest.TypedResponseError(
|
||||||
|
'The supplied token is not valid. No matching user found.',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!clusterConfig) {
|
|
||||||
throw new plugins.typedrequest.TypedResponseError('The supplied jumpCode is not valid.');
|
|
||||||
}
|
}
|
||||||
|
if (user.data.type !== 'machine') {
|
||||||
|
throw new plugins.typedrequest.TypedResponseError(
|
||||||
|
'The supplied token is not valid. The user is not a machine.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let cluster: Cluster;
|
||||||
|
if (user.data.role === 'cluster') {
|
||||||
|
cluster = await this.cloudlyRef.clusterManager.getClusterBy_UserId(user.id);
|
||||||
|
}
|
||||||
|
const expiryTimestamp = Date.now() + 3600 * 1000 * 24 * 365;
|
||||||
return {
|
return {
|
||||||
clusterIdentifier: {
|
identity: {
|
||||||
clusterId: clusterConfig.id,
|
name: user.data.username,
|
||||||
clusterName: clusterConfig.data.name,
|
role: user.data.role,
|
||||||
|
type: 'machine', // if someone authenticates by token, they are a machine, no matter what.
|
||||||
|
userId: user.id,
|
||||||
|
expiresAt: expiryTimestamp,
|
||||||
|
...(cluster
|
||||||
|
? {
|
||||||
|
clusterId: cluster.id,
|
||||||
|
clusterName: cluster.data.name,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
jwt: await this.cloudlyRef.authManager.smartjwtInstance.createJWT({
|
jwt: await this.cloudlyRef.authManager.smartjwtInstance.createJWT({
|
||||||
status: 'loggedIn',
|
status: 'loggedIn',
|
||||||
userId: 'cluster:' + clusterConfig.id, // TODO: create real users for clusters
|
userId: user.id,
|
||||||
})
|
expiresAt: expiryTimestamp,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// lets enable the getting of cluster configs
|
// lets enable the getting of cluster configs
|
||||||
@ -42,37 +69,34 @@ export class CloudlyCoreflowManager {
|
|||||||
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.config.IRequest_Any_Cloudly_GetClusterConfig>(
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.config.IRequest_Any_Cloudly_GetClusterConfig>(
|
||||||
'getClusterConfig',
|
'getClusterConfig',
|
||||||
async (dataArg) => {
|
async (dataArg) => {
|
||||||
const clusterIdentifier = dataArg.clusterIdentifier;
|
const identity = dataArg.identity;
|
||||||
console.log('trying to get clusterConfigSet');
|
console.log('trying to get clusterConfigSet');
|
||||||
console.log(dataArg);
|
console.log(dataArg);
|
||||||
const clusterConfigSet =
|
const cluster = await this.cloudlyRef.clusterManager.getClusterBy_Identity(identity);
|
||||||
await this.cloudlyRef.clusterManager.getClusterConfigBy_ClusterIdentifier(
|
|
||||||
clusterIdentifier
|
|
||||||
);
|
|
||||||
console.log('got cluster config and sending it back to coreflow');
|
console.log('got cluster config and sending it back to coreflow');
|
||||||
return {
|
return {
|
||||||
configData: await clusterConfigSet.createSavableObject(),
|
configData: await cluster.createSavableObject(),
|
||||||
deploymentDirectives: [],
|
deploymentDirectives: [],
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// lets enable getting of certificates
|
// lets enable getting of certificates
|
||||||
this.typedRouter.addTypedHandler(
|
this.typedRouter.addTypedHandler(
|
||||||
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.certificate.IRequest_Any_Cloudly_GetSslCertificate>(
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.certificate.IRequest_Any_Cloudly_GetCertificateForDomain>(
|
||||||
'getSslCertificate',
|
'getCertificateForDomain',
|
||||||
async (dataArg) => {
|
async (dataArg) => {
|
||||||
console.log(`got request for certificate ${dataArg.requiredCertName}`);
|
console.log(`incoming API request for certificate ${dataArg.domainName}`);
|
||||||
const cert = await this.cloudlyRef.letsencryptConnector.getCertificateForDomain(
|
const cert = await this.cloudlyRef.letsencryptConnector.getCertificateForDomain(
|
||||||
dataArg.requiredCertName
|
dataArg.domainName,
|
||||||
);
|
);
|
||||||
console.log(`got certificate ready for reponse ${dataArg.requiredCertName}`);
|
console.log(`got certificate ready for reponse ${dataArg.domainName}`);
|
||||||
return {
|
return {
|
||||||
certificate: await cert.createSavableObject(),
|
certificate: await cert.createSavableObject(),
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,14 @@ import * as plugins from '../plugins.js';
|
|||||||
import type { ImageManager } from './classes.imagemanager.js';
|
import type { ImageManager } from './classes.imagemanager.js';
|
||||||
|
|
||||||
@plugins.smartdata.managed()
|
@plugins.smartdata.managed()
|
||||||
export class Image extends plugins.smartdata.SmartDataDbDoc<Image, plugins.servezoneInterfaces.data.IImage, ImageManager> {
|
export class Image extends plugins.smartdata.SmartDataDbDoc<
|
||||||
public static async create(imageDataArg: Partial<plugins.servezoneInterfaces.data.IImage['data']>) {
|
Image,
|
||||||
|
plugins.servezoneInterfaces.data.IImage,
|
||||||
|
ImageManager
|
||||||
|
> {
|
||||||
|
public static async create(
|
||||||
|
imageDataArg: Partial<plugins.servezoneInterfaces.data.IImage['data']>,
|
||||||
|
) {
|
||||||
const image = new Image();
|
const image = new Image();
|
||||||
image.id = await this.getNewId();
|
image.id = await this.getNewId();
|
||||||
console.log(imageDataArg);
|
console.log(imageDataArg);
|
||||||
@ -14,7 +20,7 @@ export class Image extends plugins.smartdata.SmartDataDbDoc<Image, plugins.serve
|
|||||||
versions: [],
|
versions: [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
console.log((Image as any).saveableProperties)
|
console.log((Image as any).saveableProperties);
|
||||||
await image.save();
|
await image.save();
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
@ -32,6 +38,10 @@ export class Image extends plugins.smartdata.SmartDataDbDoc<Image, plugins.serve
|
|||||||
* note: this is relative to the storage method defined by the imageManager
|
* note: this is relative to the storage method defined by the imageManager
|
||||||
*/
|
*/
|
||||||
public async getStoragePath(versionStringArg: string) {
|
public async getStoragePath(versionStringArg: string) {
|
||||||
return `${this.data.name}:${versionStringArg}`.replace('/', '__')
|
return `${this.data.name}:${versionStringArg}`.replace('/', '__');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getWriteStream() {}
|
||||||
|
|
||||||
|
public async getReadStream() {}
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import type { Cloudly } from '../classes.cloudly.js';
|
import type { Cloudly } from '../classes.cloudly.js';
|
||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as paths from '../paths.js';
|
||||||
|
|
||||||
import { Image } from './classes.image.js';
|
import { Image } from './classes.image.js';
|
||||||
|
|
||||||
@ -16,7 +17,6 @@ export class ImageManager {
|
|||||||
|
|
||||||
public CImage = plugins.smartdata.setDefaultManagerForDoc(this, Image);
|
public CImage = plugins.smartdata.setDefaultManagerForDoc(this, Image);
|
||||||
|
|
||||||
|
|
||||||
constructor(cloudlyRefArg: Cloudly) {
|
constructor(cloudlyRefArg: Cloudly) {
|
||||||
this.cloudlyRef = cloudlyRefArg;
|
this.cloudlyRef = cloudlyRefArg;
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ export class ImageManager {
|
|||||||
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_CreateImage>(
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_CreateImage>(
|
||||||
'createImage',
|
'createImage',
|
||||||
async (reqArg, toolsArg) => {
|
async (reqArg, toolsArg) => {
|
||||||
await toolsArg.passGuards([this.cloudlyRef.authManager.adminJwtGuard], reqArg);
|
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqArg);
|
||||||
const image = await this.CImage.create({
|
const image = await this.CImage.create({
|
||||||
name: reqArg.name,
|
name: reqArg.name,
|
||||||
description: reqArg.description,
|
description: reqArg.description,
|
||||||
@ -35,58 +35,92 @@ export class ImageManager {
|
|||||||
return {
|
return {
|
||||||
image: await image.createSavableObject(),
|
image: await image.createSavableObject(),
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
)
|
);
|
||||||
|
|
||||||
|
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_GetImage>(
|
||||||
|
new plugins.typedrequest.TypedHandler('getImage', async (reqArg, toolsArg) => {
|
||||||
|
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqArg);
|
||||||
|
const image = await this.CImage.getInstance({
|
||||||
|
id: reqArg.imageId,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
image: await image.createSavableObject(),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
this.typedrouter.addTypedHandler(
|
this.typedrouter.addTypedHandler(
|
||||||
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_DeleteImage>(
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_DeleteImage>(
|
||||||
'deleteImage',
|
'deleteImage',
|
||||||
async (reqArg, toolsArg) => {
|
async (reqArg, toolsArg) => {
|
||||||
await toolsArg.passGuards([this.cloudlyRef.authManager.adminJwtGuard], reqArg);
|
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqArg);
|
||||||
const image = await this.CImage.getInstance({
|
const image = await this.CImage.getInstance({
|
||||||
id: reqArg.imageId,
|
id: reqArg.imageId,
|
||||||
});
|
});
|
||||||
await image.delete();
|
await image.delete();
|
||||||
return {};
|
return {};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.typedrouter.addTypedHandler(
|
this.typedrouter.addTypedHandler(
|
||||||
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_GetAllImages>(
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_GetAllImages>(
|
||||||
'getAllImages',
|
'getAllImages',
|
||||||
async (requestArg, toolsArg) => {
|
async (requestArg, toolsArg) => {
|
||||||
await toolsArg.passGuards([this.cloudlyRef.authManager.adminJwtGuard], requestArg);
|
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], requestArg);
|
||||||
const images = await this.CImage.getInstances({});
|
const images = await this.CImage.getInstances({});
|
||||||
return {
|
return {
|
||||||
images: await Promise.all(
|
images: await Promise.all(
|
||||||
images.map((image) => {
|
images.map((image) => {
|
||||||
return image.createSavableObject();
|
return image.createSavableObject();
|
||||||
})
|
}),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.typedrouter.addTypedHandler(
|
this.typedrouter.addTypedHandler(
|
||||||
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_PushImageVersion>(
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_PushImageVersion>(
|
||||||
'pushImageVersion',
|
'pushImageVersion',
|
||||||
async (reqArg, toolsArg) => {
|
async (reqArg, toolsArg) => {
|
||||||
const image = await this.CImage.getInstance({
|
await plugins.smartguard.passGuardsOrReject(reqArg, [
|
||||||
|
this.cloudlyRef.authManager.validIdentityGuard,
|
||||||
|
]);
|
||||||
|
const refImage = await this.CImage.getInstance({
|
||||||
id: reqArg.imageId,
|
id: reqArg.imageId,
|
||||||
});
|
});
|
||||||
if (!image) {
|
if (!refImage) {
|
||||||
throw new plugins.typedrequest.TypedResponseError('Image not found');
|
throw new plugins.typedrequest.TypedResponseError('Image not found');
|
||||||
}
|
}
|
||||||
const imageVersion = reqArg.versionString;
|
const imageVersion = reqArg.versionString;
|
||||||
|
console.log(
|
||||||
|
`got request to push image version ${imageVersion} for image ${refImage.data.name}`,
|
||||||
|
);
|
||||||
const imagePushStream = reqArg.imageStream;
|
const imagePushStream = reqArg.imageStream;
|
||||||
|
(async () => {
|
||||||
|
const smartWebDuplex = new plugins.smartstream.webstream.WebDuplexStream<
|
||||||
|
Uint8Array,
|
||||||
|
Uint8Array
|
||||||
|
>({
|
||||||
|
writeFunction: async (chunkArg, toolsArg) => {
|
||||||
|
console.log(chunkArg);
|
||||||
|
return chunkArg;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
imagePushStream.writeToWebstream(smartWebDuplex.writable);
|
||||||
|
await this.dockerImageStore.storeImage(
|
||||||
|
refImage.id,
|
||||||
|
plugins.smartstream.SmartDuplex.fromWebReadableStream(smartWebDuplex.readable),
|
||||||
|
);
|
||||||
|
})();
|
||||||
return {
|
return {
|
||||||
allowed: true,
|
allowed: true,
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.typedrouter.addTypedHandler(
|
this.typedrouter.addTypedHandler(
|
||||||
@ -96,31 +130,44 @@ export class ImageManager {
|
|||||||
const image = await this.CImage.getInstance({
|
const image = await this.CImage.getInstance({
|
||||||
id: reqArg.imageId,
|
id: reqArg.imageId,
|
||||||
});
|
});
|
||||||
const imageVersion = image.data.versions.find((version) => version.versionString === reqArg.versionString);
|
const imageVersion = image.data.versions.find(
|
||||||
const readable = this.imageDir.fastGetStream({
|
(version) => version.versionString === reqArg.versionString,
|
||||||
|
);
|
||||||
|
const readable = this.imageDir.fastGetStream(
|
||||||
|
{
|
||||||
path: await image.getStoragePath(reqArg.versionString),
|
path: await image.getStoragePath(reqArg.versionString),
|
||||||
}, 'webstream');
|
},
|
||||||
|
'webstream',
|
||||||
|
);
|
||||||
const imageVirtualStream = new plugins.typedrequest.VirtualStream();
|
const imageVirtualStream = new plugins.typedrequest.VirtualStream();
|
||||||
return {
|
return {
|
||||||
imageStream: imageVirtualStream,
|
imageStream: imageVirtualStream,
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async start() {
|
public async start() {
|
||||||
|
// lets setup s3
|
||||||
const s3Descriptor: plugins.tsclass.storage.IS3Descriptor =
|
const s3Descriptor: plugins.tsclass.storage.IS3Descriptor =
|
||||||
await this.cloudlyRef.config.appData.waitForAndGetKey('s3Descriptor');
|
await this.cloudlyRef.config.appData.waitForAndGetKey('s3Descriptor');
|
||||||
console.log(this.cloudlyRef.config.data.s3Descriptor);
|
console.log(this.cloudlyRef.config.data.s3Descriptor);
|
||||||
this.smartbucketInstance = new plugins.smartbucket.SmartBucket(
|
this.smartbucketInstance = new plugins.smartbucket.SmartBucket(
|
||||||
this.cloudlyRef.config.data.s3Descriptor
|
this.cloudlyRef.config.data.s3Descriptor,
|
||||||
);
|
);
|
||||||
const bucket = await this.smartbucketInstance.getBucketByName('cloudly-test');
|
const bucket = await this.smartbucketInstance.getBucketByName('cloudly-test');
|
||||||
await bucket.fastPut({ path: 'test/test.txt', contents: 'hello' });
|
await bucket.fastPut({ path: 'images/00init', contents: 'init' });
|
||||||
|
|
||||||
this.imageDir = await bucket.getDirectoryFromPath({
|
this.imageDir = await bucket.getDirectoryFromPath({
|
||||||
path: 'images',
|
path: '/images',
|
||||||
|
});
|
||||||
|
|
||||||
|
// lets setup dockerstore
|
||||||
|
await plugins.smartfile.fs.ensureDir(paths.dockerImageStoreDir);
|
||||||
|
this.dockerImageStore = new plugins.docker.DockerImageStore({
|
||||||
|
localDirPath: paths.dockerImageStoreDir,
|
||||||
|
bucketDir: this.imageDir,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ export class SecretBundle extends plugins.smartdata.SmartDataDbDoc<
|
|||||||
secretGroups.push(
|
secretGroups.push(
|
||||||
await SecretGroup.getInstance({
|
await SecretGroup.getInstance({
|
||||||
id: secretGroupId,
|
id: secretGroupId,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return secretGroups;
|
return secretGroups;
|
||||||
|
@ -39,24 +39,24 @@ export class CloudlySecretManager {
|
|||||||
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_GetConfigBundlesAndSecretGroups>(
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_GetConfigBundlesAndSecretGroups>(
|
||||||
'adminGetConfigBundlesAndSecretGroups',
|
'adminGetConfigBundlesAndSecretGroups',
|
||||||
async (dataArg, toolsArg) => {
|
async (dataArg, toolsArg) => {
|
||||||
await toolsArg.passGuards([this.cloudlyRef.authManager.adminJwtGuard], dataArg);
|
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg);
|
||||||
dataArg.jwt
|
dataArg.identity.jwt;
|
||||||
const secretBundles = await SecretBundle.getInstances({});
|
const secretBundles = await SecretBundle.getInstances({});
|
||||||
const secretGroups = await SecretGroup.getInstances({});
|
const secretGroups = await SecretGroup.getInstances({});
|
||||||
return {
|
return {
|
||||||
secretBundles: [
|
secretBundles: [
|
||||||
...(await Promise.all(
|
...(await Promise.all(
|
||||||
secretBundles.map((configBundle) => configBundle.createSavableObject())
|
secretBundles.map((configBundle) => configBundle.createSavableObject()),
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
secretGroups: [
|
secretGroups: [
|
||||||
...(await Promise.all(
|
...(await Promise.all(
|
||||||
secretGroups.map((secretGroup) => secretGroup.createSavableObject())
|
secretGroups.map((secretGroup) => secretGroup.createSavableObject()),
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_CreateConfigBundlesAndSecretGroups>(
|
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_CreateConfigBundlesAndSecretGroups>(
|
||||||
@ -72,8 +72,8 @@ export class CloudlySecretManager {
|
|||||||
return {
|
return {
|
||||||
ok: true,
|
ok: true,
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.typedrouter.addTypedHandler(
|
this.typedrouter.addTypedHandler(
|
||||||
@ -96,8 +96,8 @@ export class CloudlySecretManager {
|
|||||||
return {
|
return {
|
||||||
ok: true,
|
ok: true,
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// lets add typedrouter routes for accessing the configvailt from apps
|
// lets add typedrouter routes for accessing the configvailt from apps
|
||||||
@ -116,19 +116,19 @@ export class CloudlySecretManager {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const authorization = await wantedBundle.getAuthorizationFromAuthKey(
|
const authorization = await wantedBundle.getAuthorizationFromAuthKey(
|
||||||
dataArg.authorization
|
dataArg.authorization,
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
envBundle: {
|
envBundle: {
|
||||||
configKeyValueObject: await wantedBundle.getKeyValueObjectForEnvironment(
|
configKeyValueObject: await wantedBundle.getKeyValueObjectForEnvironment(
|
||||||
authorization.environment
|
authorization.environment,
|
||||||
),
|
),
|
||||||
environment: authorization.environment,
|
environment: authorization.environment,
|
||||||
timeSensitive: false,
|
timeSensitive: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import type { CloudlyServerManager } from './classes.servermanager.js';
|
|||||||
export class CurlFresh {
|
export class CurlFresh {
|
||||||
public optionsArg = {
|
public optionsArg = {
|
||||||
npmRegistry: 'https://registry.npmjs.org',
|
npmRegistry: 'https://registry.npmjs.org',
|
||||||
}
|
};
|
||||||
public scripts = {
|
public scripts = {
|
||||||
'setup.sh': `#!/bin/bash
|
'setup.sh': `#!/bin/bash
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ bash -c "spark installdaemon"
|
|||||||
public handler = new plugins.typedserver.servertools.Handler('ALL', async (req, res) => {
|
public handler = new plugins.typedserver.servertools.Handler('ALL', async (req, res) => {
|
||||||
logger.log('info', 'curlfresh handler called. a server might be coming online soon :)');
|
logger.log('info', 'curlfresh handler called. a server might be coming online soon :)');
|
||||||
const scriptname = req.params.scriptname;
|
const scriptname = req.params.scriptname;
|
||||||
switch(scriptname) {
|
switch (scriptname) {
|
||||||
case 'setup.sh':
|
case 'setup.sh':
|
||||||
logger.log('info', 'sending setup.sh');
|
logger.log('info', 'sending setup.sh');
|
||||||
res.type('application/x-sh');
|
res.type('application/x-sh');
|
||||||
@ -66,7 +66,8 @@ bash -c "spark installdaemon"
|
|||||||
this.serverManagerRef = serverManagerRefArg;
|
this.serverManagerRef = serverManagerRefArg;
|
||||||
}
|
}
|
||||||
public async getServerUserData(): Promise<string> {
|
public async getServerUserData(): Promise<string> {
|
||||||
const sslMode = await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('sslMode');
|
const sslMode =
|
||||||
|
await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('sslMode');
|
||||||
let protocol: 'http' | 'https';
|
let protocol: 'http' | 'https';
|
||||||
if (sslMode === 'none') {
|
if (sslMode === 'none') {
|
||||||
protocol = 'http';
|
protocol = 'http';
|
||||||
@ -74,14 +75,16 @@ bash -c "spark installdaemon"
|
|||||||
protocol = 'https';
|
protocol = 'https';
|
||||||
}
|
}
|
||||||
|
|
||||||
const domain = await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('publicUrl');
|
const domain =
|
||||||
const port = await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('publicPort');
|
await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('publicUrl');
|
||||||
|
const port =
|
||||||
|
await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('publicPort');
|
||||||
|
|
||||||
const serverUserData = `#cloud-config
|
const serverUserData = `#cloud-config
|
||||||
runcmd:
|
runcmd:
|
||||||
- curl -o- ${protocol}://${domain}:${port}/curlfresh/setup.sh | sh
|
- curl -o- ${protocol}://${domain}:${port}/curlfresh/setup.sh | sh
|
||||||
`
|
`;
|
||||||
console.log(serverUserData);
|
console.log(serverUserData);
|
||||||
return serverUserData;
|
return serverUserData;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,13 @@ import * as plugins from '../plugins.js';
|
|||||||
* cluster defines a swarmkit cluster
|
* cluster defines a swarmkit cluster
|
||||||
*/
|
*/
|
||||||
@plugins.smartdata.Manager()
|
@plugins.smartdata.Manager()
|
||||||
export class Server extends plugins.smartdata.SmartDataDbDoc<Server, plugins.servezoneInterfaces.data.IServer> {
|
export class Server extends plugins.smartdata.SmartDataDbDoc<
|
||||||
|
Server,
|
||||||
|
plugins.servezoneInterfaces.data.IServer
|
||||||
|
> {
|
||||||
// STATIC
|
// STATIC
|
||||||
public static async createFromHetznerServer(
|
public static async createFromHetznerServer(
|
||||||
hetznerServerArg: plugins.hetznercloud.HetznerServer
|
hetznerServerArg: plugins.hetznercloud.HetznerServer,
|
||||||
) {
|
) {
|
||||||
const newServer = new Server();
|
const newServer = new Server();
|
||||||
newServer.id = plugins.smartunique.shortId(8);
|
newServer.id = plugins.smartunique.shortId(8);
|
||||||
@ -16,7 +19,7 @@ export class Server extends plugins.smartdata.SmartDataDbDoc<Server, plugins.ser
|
|||||||
requiredDebianPackages: [],
|
requiredDebianPackages: [],
|
||||||
sshKeys: [],
|
sshKeys: [],
|
||||||
type: 'hetzner',
|
type: 'hetzner',
|
||||||
}
|
};
|
||||||
Object.assign(newServer, { data });
|
Object.assign(newServer, { data });
|
||||||
await newServer.save();
|
await newServer.save();
|
||||||
return newServer;
|
return newServer;
|
||||||
|
@ -29,17 +29,19 @@ export class CloudlyServerManager {
|
|||||||
const serverId = requestData.serverId;
|
const serverId = requestData.serverId;
|
||||||
const server = await this.CServer.getInstance({
|
const server = await this.CServer.getInstance({
|
||||||
id: serverId,
|
id: serverId,
|
||||||
})
|
});
|
||||||
return {
|
return {
|
||||||
configData: await server.createSavableObject(),
|
configData: await server.createSavableObject(),
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async start() {
|
public async start() {
|
||||||
this.hetznerAccount = new plugins.hetznercloud.HetznerAccount(this.cloudlyRef.config.data.hetznerToken);
|
this.hetznerAccount = new plugins.hetznercloud.HetznerAccount(
|
||||||
|
this.cloudlyRef.config.data.hetznerToken,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async stop() {}
|
public async stop() {}
|
||||||
@ -66,16 +68,18 @@ export class CloudlyServerManager {
|
|||||||
clusterId: cluster.id,
|
clusterId: cluster.id,
|
||||||
priority: '1',
|
priority: '1',
|
||||||
},
|
},
|
||||||
userData: await this.curlfreshInstance.getServerUserData()
|
userData: await this.curlfreshInstance.getServerUserData(),
|
||||||
});
|
});
|
||||||
const newServer = await Server.createFromHetznerServer(server);
|
const newServer = await Server.createFromHetznerServer(server);
|
||||||
console.log(`cluster created new server for cluster ${cluster.id}`);
|
console.log(`cluster created new server for cluster ${cluster.id}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`cluster ${cluster.id} already has servers. Making sure that they actually exist in the real world...`);
|
console.log(
|
||||||
|
`cluster ${cluster.id} already has servers. Making sure that they actually exist in the real world...`,
|
||||||
|
);
|
||||||
// if there is a server, make sure that it exists
|
// if there is a server, make sure that it exists
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
const hetznerServer = await this.hetznerAccount.getServersByLabel({
|
const hetznerServer = await this.hetznerAccount.getServersByLabel({
|
||||||
'clusterId': cluster.id
|
clusterId: cluster.id,
|
||||||
});
|
});
|
||||||
if (!hetznerServer) {
|
if (!hetznerServer) {
|
||||||
console.log(`server ${server.id} does not exist in the real world. Creating it now...`);
|
console.log(`server ${server.id} does not exist in the real world. Creating it now...`);
|
||||||
@ -86,7 +90,7 @@ export class CloudlyServerManager {
|
|||||||
labels: {
|
labels: {
|
||||||
clusterId: cluster.id,
|
clusterId: cluster.id,
|
||||||
priority: '1',
|
priority: '1',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const newServer = await Server.createFromHetznerServer(hetznerServer);
|
const newServer = await Server.createFromHetznerServer(hetznerServer);
|
||||||
}
|
}
|
||||||
@ -99,7 +103,7 @@ export class CloudlyServerManager {
|
|||||||
const results = await this.CServer.getInstances({
|
const results = await this.CServer.getInstances({
|
||||||
data: {
|
data: {
|
||||||
assignedClusterId: clusterArg.id,
|
assignedClusterId: clusterArg.id,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import { ServiceManager } from './classes.servicemanager.js';
|
||||||
|
|
||||||
export class Service extends plugins.smartdata.SmartDataDbDoc<Service, plugins.servezoneInterfaces.data.IService, ServiceManager> {
|
export class Service extends plugins.smartdata.SmartDataDbDoc<
|
||||||
|
Service,
|
||||||
|
plugins.servezoneInterfaces.data.IService,
|
||||||
|
ServiceManager
|
||||||
|
> {
|
||||||
@plugins.smartdata.svDb()
|
@plugins.smartdata.svDb()
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
||||||
@plugins.smartdata.svDb()
|
@plugins.smartdata.svDb()
|
||||||
public data: plugins.servezoneInterfaces.data.IService['data'];
|
public data: plugins.servezoneInterfaces.data.IService['data'];
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -16,7 +16,7 @@ export class ExternalApiManager {
|
|||||||
return {
|
return {
|
||||||
networkNodes,
|
networkNodes,
|
||||||
};
|
};
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import * as plugins from './plugins.js';
|
import * as plugins from './plugins.js';
|
||||||
|
|
||||||
export const packageDir = plugins.path.join(plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url), '../');
|
export const packageDir = plugins.path.join(
|
||||||
|
plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
|
||||||
|
'../',
|
||||||
|
);
|
||||||
export const nogitDir = plugins.path.join(packageDir, '.nogit/');
|
export const nogitDir = plugins.path.join(packageDir, '.nogit/');
|
||||||
|
export const dockerImageStoreDir = plugins.path.join(nogitDir, './dockerimagestore/');
|
||||||
export const distServeDir = plugins.path.join(packageDir, './dist_serve');
|
export const distServeDir = plugins.path.join(packageDir, './dist_serve');
|
||||||
|
@ -33,6 +33,7 @@ import * as smartclickhouse from '@push.rocks/smartclickhouse';
|
|||||||
import * as smartdata from '@push.rocks/smartdata';
|
import * as smartdata from '@push.rocks/smartdata';
|
||||||
import * as smartdelay from '@push.rocks/smartdelay';
|
import * as smartdelay from '@push.rocks/smartdelay';
|
||||||
import * as smartexit from '@push.rocks/smartexit';
|
import * as smartexit from '@push.rocks/smartexit';
|
||||||
|
import * as smartexpect from '@push.rocks/smartexpect';
|
||||||
import * as smartfile from '@push.rocks/smartfile';
|
import * as smartfile from '@push.rocks/smartfile';
|
||||||
import * as smartguard from '@push.rocks/smartguard';
|
import * as smartguard from '@push.rocks/smartguard';
|
||||||
import * as smartjson from '@push.rocks/smartjson';
|
import * as smartjson from '@push.rocks/smartjson';
|
||||||
@ -42,6 +43,7 @@ import * as smartpath from '@push.rocks/smartpath';
|
|||||||
import * as smartpromise from '@push.rocks/smartpromise';
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
import * as smartrequest from '@push.rocks/smartrequest';
|
import * as smartrequest from '@push.rocks/smartrequest';
|
||||||
import * as smartssh from '@push.rocks/smartssh';
|
import * as smartssh from '@push.rocks/smartssh';
|
||||||
|
import * as smartstream from '@push.rocks/smartstream';
|
||||||
import * as smartstring from '@push.rocks/smartstring';
|
import * as smartstring from '@push.rocks/smartstring';
|
||||||
import * as smartunique from '@push.rocks/smartunique';
|
import * as smartunique from '@push.rocks/smartunique';
|
||||||
import * as taskbuffer from '@push.rocks/taskbuffer';
|
import * as taskbuffer from '@push.rocks/taskbuffer';
|
||||||
@ -57,6 +59,7 @@ export {
|
|||||||
smartclickhouse,
|
smartclickhouse,
|
||||||
smartdata,
|
smartdata,
|
||||||
smartexit,
|
smartexit,
|
||||||
|
smartexpect,
|
||||||
smartdelay,
|
smartdelay,
|
||||||
smartfile,
|
smartfile,
|
||||||
smartguard,
|
smartguard,
|
||||||
@ -67,6 +70,7 @@ export {
|
|||||||
smartpromise,
|
smartpromise,
|
||||||
smartrequest,
|
smartrequest,
|
||||||
smartssh,
|
smartssh,
|
||||||
|
smartstream,
|
||||||
smartstring,
|
smartstring,
|
||||||
smartunique,
|
smartunique,
|
||||||
taskbuffer,
|
taskbuffer,
|
||||||
|
@ -55,7 +55,7 @@ export class CloudlyApiClient {
|
|||||||
this.cloudlyUrl
|
this.cloudlyUrl
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
`CloudlyCluent connected to cloudly at ${this.cloudlyUrl}. Remember to get an identity.`
|
`CloudlyClient connected to cloudly at ${this.cloudlyUrl}. Remember to get an identity.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,57 +63,69 @@ export class CloudlyApiClient {
|
|||||||
await this.typedsocketClient.stop();
|
await this.typedsocketClient.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public identity: plugins.servezoneInterfaces.data.IClusterIdentifier;
|
public identity: plugins.servezoneInterfaces.data.IIdentity;
|
||||||
public async getIdentityByJumpCode(
|
public async getIdentityByToken(
|
||||||
jumpCodeArg: string,
|
token: string,
|
||||||
tagConnection = false,
|
optionsArg?: {
|
||||||
statefullIdentity = true
|
tagConnection?: boolean;
|
||||||
): Promise<plugins.servezoneInterfaces.data.IClusterIdentifier> {
|
statefullIdentity?: boolean;
|
||||||
|
}
|
||||||
|
): Promise<plugins.servezoneInterfaces.data.IIdentity> {
|
||||||
|
optionsArg = Object.assign({}, {
|
||||||
|
tagConnection: false,
|
||||||
|
statefullIdentity: true,
|
||||||
|
}, optionsArg);
|
||||||
|
|
||||||
const identityRequest =
|
const identityRequest =
|
||||||
this.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.identity.IRequest_Any_Cloudly_CoreflowManager_GetIdentityByJumpCode>(
|
this.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.identity.IRequest_Any_Cloudly_CoreflowManager_GetIdentityByToken>(
|
||||||
'getIdentityByJumpCode'
|
'getIdentityByToken'
|
||||||
);
|
);
|
||||||
console.log(`trying to get identity from cloudly with supplied jumpCodeArg: ${jumpCodeArg}`);
|
console.log(`trying to get identity from cloudly with supplied jumpCodeArg: ${token}`);
|
||||||
const response = await identityRequest.fire({
|
const response = await identityRequest.fire({
|
||||||
jumpCode: jumpCodeArg,
|
token: token,
|
||||||
});
|
});
|
||||||
console.log('got identity response');
|
console.log('got identity response');
|
||||||
const identity = response.clusterIdentifier;
|
const identity = response.identity;
|
||||||
|
|
||||||
if (tagConnection) {
|
if (optionsArg.tagConnection) {
|
||||||
this.typedsocketClient.addTag('identity', identity);
|
this.typedsocketClient.addTag('identity', identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (statefullIdentity) {
|
if (optionsArg.statefullIdentity) {
|
||||||
this.identity = identity;
|
this.identity = identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return identity;
|
return identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* will use statefull identity by default
|
||||||
|
*/
|
||||||
public async getClusterConfigFromCloudlyByIdentity(
|
public async getClusterConfigFromCloudlyByIdentity(
|
||||||
identityArg: plugins.servezoneInterfaces.data.IClusterIdentifier
|
identityArg: plugins.servezoneInterfaces.data.IIdentity = this.identity
|
||||||
): Promise<plugins.servezoneInterfaces.data.ICluster> {
|
): Promise<plugins.servezoneInterfaces.data.ICluster> {
|
||||||
const clusterConfigRequest =
|
const clusterConfigRequest =
|
||||||
this.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.config.IRequest_Any_Cloudly_GetClusterConfig>(
|
this.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.config.IRequest_Any_Cloudly_GetClusterConfig>(
|
||||||
'getClusterConfig'
|
'getClusterConfig'
|
||||||
);
|
);
|
||||||
const response = await clusterConfigRequest.fire({
|
const response = await clusterConfigRequest.fire({
|
||||||
jwt: '',
|
identity: identityArg,
|
||||||
clusterIdentifier: identityArg,
|
|
||||||
});
|
});
|
||||||
return response.configData;
|
return response.configData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* will use statefull identity by default
|
||||||
|
*/
|
||||||
public async getServerConfigFromCloudlyByIdentity(
|
public async getServerConfigFromCloudlyByIdentity(
|
||||||
identityArg: plugins.servezoneInterfaces.data.IClusterIdentifier
|
identityArg: plugins.servezoneInterfaces.data.IIdentity = this.identity
|
||||||
): Promise<plugins.servezoneInterfaces.data.IServer> {
|
): Promise<plugins.servezoneInterfaces.data.IServer> {
|
||||||
const serverConfigRequest =
|
const serverConfigRequest =
|
||||||
this.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.config.IRequest_Any_Cloudly_GetServerConfig>(
|
this.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.config.IRequest_Any_Cloudly_GetServerConfig>(
|
||||||
'getServerConfig'
|
'getServerConfig'
|
||||||
);
|
);
|
||||||
const response = await serverConfigRequest.fire({
|
const response = await serverConfigRequest.fire({
|
||||||
jwt: '', // TODO: do proper auth here
|
identity: identityArg,
|
||||||
serverId: '', // TODO: get server id here
|
serverId: '', // TODO: get server id here
|
||||||
});
|
});
|
||||||
return response.configData;
|
return response.configData;
|
||||||
@ -121,25 +133,35 @@ export class CloudlyApiClient {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* gets a certificate for a domain used by a service
|
* gets a certificate for a domain used by a service
|
||||||
* @param serviceNameArg
|
|
||||||
* @param domainNameArg
|
|
||||||
*/
|
*/
|
||||||
public async getCertificateForDomainOverHttps(
|
public async getCertificateForDomain(optionsArg: {
|
||||||
domainNameArg: string
|
domainName: string;
|
||||||
): Promise<plugins.tsclass.network.ICert> {
|
type: plugins.servezoneInterfaces.requests.certificate.IRequest_Any_Cloudly_GetCertificateForDomain['request']['type'];
|
||||||
|
identity?: plugins.servezoneInterfaces.data.IIdentity;
|
||||||
|
}): Promise<plugins.tsclass.network.ICert> {
|
||||||
|
optionsArg.identity = optionsArg.identity || this.identity;
|
||||||
|
if (!optionsArg.identity) {
|
||||||
|
throw new Error('identity is required. Either provide one or login first.');
|
||||||
|
}
|
||||||
const typedCertificateRequest =
|
const typedCertificateRequest =
|
||||||
this.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.certificate.IRequest_Any_Cloudly_GetSslCertificate>(
|
this.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.certificate.IRequest_Any_Cloudly_GetCertificateForDomain>(
|
||||||
'getSslCertificate'
|
'getCertificateForDomain'
|
||||||
);
|
);
|
||||||
const typedResponse = await typedCertificateRequest.fire({
|
const typedResponse = await typedCertificateRequest.fire({
|
||||||
authToken: '', // do proper auth here
|
identity: this.identity, // do proper auth here
|
||||||
requiredCertName: domainNameArg,
|
domainName: optionsArg.domainName,
|
||||||
|
type: optionsArg.type,
|
||||||
});
|
});
|
||||||
return typedResponse.certificate;
|
return typedResponse.certificate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public images = {
|
||||||
// Images
|
// Images
|
||||||
public async getImages() {
|
getImages: async () => {
|
||||||
return Image.getImages(this);
|
return Image.getImages(this);
|
||||||
|
},
|
||||||
|
createImage: async (optionsArg: Parameters<typeof Image.createImage>[1]) => {
|
||||||
|
return Image.createImage(this, optionsArg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ export class Image implements plugins.servezoneInterfaces.data.IImage {
|
|||||||
'getAllImages'
|
'getAllImages'
|
||||||
);
|
);
|
||||||
const response = await getAllImagesTR.fire({
|
const response = await getAllImagesTR.fire({
|
||||||
jwt: cloudlyClientRef.identity.jwt,
|
identity: cloudlyClientRef.identity,
|
||||||
});
|
});
|
||||||
const resultImages: Image[] = [];
|
const resultImages: Image[] = [];
|
||||||
for (const image of response.images) {
|
for (const image of response.images) {
|
||||||
@ -18,6 +18,23 @@ export class Image implements plugins.servezoneInterfaces.data.IImage {
|
|||||||
return resultImages;
|
return resultImages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates a new image
|
||||||
|
*/
|
||||||
|
public static async createImage(cloudlyClientRef: CloudlyApiClient, imageDataArg: Partial<plugins.servezoneInterfaces.data.IImage['data']>) {
|
||||||
|
const createImageTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.image.IRequest_CreateImage>(
|
||||||
|
'createImage'
|
||||||
|
);
|
||||||
|
const response = await createImageTR.fire({
|
||||||
|
identity: cloudlyClientRef.identity,
|
||||||
|
name: imageDataArg.name,
|
||||||
|
description: imageDataArg.description,
|
||||||
|
});
|
||||||
|
const newImage = new Image(cloudlyClientRef);
|
||||||
|
Object.assign(newImage, response.image);
|
||||||
|
return newImage;
|
||||||
|
}
|
||||||
|
|
||||||
// INSTANCE
|
// INSTANCE
|
||||||
cloudlyClientRef: CloudlyApiClient;
|
cloudlyClientRef: CloudlyApiClient;
|
||||||
|
|
||||||
@ -32,11 +49,11 @@ export class Image implements plugins.servezoneInterfaces.data.IImage {
|
|||||||
* updates the image data
|
* updates the image data
|
||||||
*/
|
*/
|
||||||
public async update() {
|
public async update() {
|
||||||
const getVersionsTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.image.IRequest_GetImageMetadata>(
|
const getVersionsTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.image.IRequest_GetImage>(
|
||||||
'getImageMetadata'
|
'getImage'
|
||||||
);
|
);
|
||||||
const response = await getVersionsTR.fire({
|
const response = await getVersionsTR.fire({
|
||||||
jwt: this.cloudlyClientRef.identity.jwt,
|
identity: this.cloudlyClientRef.identity,
|
||||||
imageId: this.id,
|
imageId: this.id,
|
||||||
});
|
});
|
||||||
Object.assign(this, response.image);
|
Object.assign(this, response.image);
|
||||||
@ -49,18 +66,17 @@ export class Image implements plugins.servezoneInterfaces.data.IImage {
|
|||||||
*/
|
*/
|
||||||
public async pushImageVersion(imageVersion: string, imageReadableArg: ReadableStream<Uint8Array>): Promise<void> {
|
public async pushImageVersion(imageVersion: string, imageReadableArg: ReadableStream<Uint8Array>): Promise<void> {
|
||||||
const done = plugins.smartpromise.defer();
|
const done = plugins.smartpromise.defer();
|
||||||
const pullImageTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.image.IRequest_PushImageVersion>(
|
const pushImageTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.image.IRequest_PushImageVersion>(
|
||||||
'pushImageVersion'
|
'pushImageVersion'
|
||||||
);
|
);
|
||||||
const virtualStream = new plugins.typedrequest.VirtualStream();
|
const virtualStream = new plugins.typedrequest.VirtualStream();
|
||||||
const response = await pullImageTR.fire({
|
const response = await pushImageTR.fire({
|
||||||
jwt: this.cloudlyClientRef.identity.jwt,
|
identity: this.cloudlyClientRef.identity,
|
||||||
imageId: this.id,
|
imageId: this.id,
|
||||||
versionString: '',
|
versionString: '',
|
||||||
imageStream: virtualStream,
|
imageStream: virtualStream,
|
||||||
});
|
});
|
||||||
await virtualStream.readFromWebstream(imageReadableArg);
|
await virtualStream.readFromWebstream(imageReadableArg);
|
||||||
await done.promise;
|
|
||||||
await this.update();
|
await this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -72,7 +88,7 @@ export class Image implements plugins.servezoneInterfaces.data.IImage {
|
|||||||
'pullImageVersion'
|
'pullImageVersion'
|
||||||
);
|
);
|
||||||
const response = await pullImageTR.fire({
|
const response = await pullImageTR.fire({
|
||||||
jwt: this.cloudlyClientRef.identity.jwt,
|
identity: this.cloudlyClientRef.identity,
|
||||||
imageId: this.id,
|
imageId: this.id,
|
||||||
versionString: versionStringArg,
|
versionString: versionStringArg,
|
||||||
});
|
});
|
||||||
|
16
ts_apiclient/tspublish.json
Normal file
16
ts_apiclient/tspublish.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "@serve.zone/api",
|
||||||
|
"dependencies": [
|
||||||
|
"@serve.zone/interfaces",
|
||||||
|
"@push.rocks/smartpromise",
|
||||||
|
"@push.rocks/smartrx",
|
||||||
|
"@push.rocks/smartstream",
|
||||||
|
"@api.global/typedrequest",
|
||||||
|
"@api.global/typedsocket",
|
||||||
|
"@tsclass/tsclass"
|
||||||
|
],
|
||||||
|
"registries": [
|
||||||
|
"registry.npmjs.org:public",
|
||||||
|
"verdaccio.lossless.digital:public"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
console.log('this is the cli client.');
|
8
ts_cliclient/tspublish.json
Normal file
8
ts_cliclient/tspublish.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "@serve.zone/cli",
|
||||||
|
"dependencies": [],
|
||||||
|
"registries": [
|
||||||
|
"registry.npmjs.org:public",
|
||||||
|
"verdaccio.lossless.digital:public"
|
||||||
|
]
|
||||||
|
}
|
8
ts_interfaces/00_commitinfo_data.ts
Normal file
8
ts_interfaces/00_commitinfo_data.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
|
*/
|
||||||
|
export const commitinfo = {
|
||||||
|
name: '@serve.zone/interfaces',
|
||||||
|
version: '1.1.2',
|
||||||
|
description: 'interfaces for working with containers'
|
||||||
|
}
|
16
ts_interfaces/data/cloudlyconfig.ts
Normal file
16
ts_interfaces/data/cloudlyconfig.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export interface ICloudlyConfig {
|
||||||
|
cfToken?: string;
|
||||||
|
hetznerToken?: string;
|
||||||
|
environment?: 'production' | 'integration';
|
||||||
|
letsEncryptEmail?: string;
|
||||||
|
letsEncryptPrivateKey?: string;
|
||||||
|
jwtKeypair?: plugins.tsclass.network.IJwtKeypair;
|
||||||
|
mongoDescriptor?: plugins.tsclass.database.IMongoDescriptor;
|
||||||
|
s3Descriptor?: plugins.tsclass.storage.IS3Descriptor;
|
||||||
|
publicUrl?: string;
|
||||||
|
publicPort?: string;
|
||||||
|
sslMode?: 'none' | 'letsencrypt' | 'external';
|
||||||
|
servezoneAdminaccount?: string;
|
||||||
|
}
|
36
ts_interfaces/data/cluster.ts
Normal file
36
ts_interfaces/data/cluster.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
import { type IDockerRegistryInfo } from '../data/docker.js';
|
||||||
|
import type { IServer } from './server.js';
|
||||||
|
|
||||||
|
export interface ICluster {
|
||||||
|
id: string;
|
||||||
|
data: {
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a cluster has a machine user that governs access rights.
|
||||||
|
*/
|
||||||
|
userId: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* how can the cluster reach cloudly
|
||||||
|
*/
|
||||||
|
cloudlyUrl?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* what servers are expected to be part of the cluster
|
||||||
|
*/
|
||||||
|
servers: IServer[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ACME info. This is used to get SSL certificates.
|
||||||
|
*/
|
||||||
|
acmeInfo: {
|
||||||
|
serverAddress: string;
|
||||||
|
serverSecret: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
sshKeys: plugins.tsclass.network.ISshKey[];
|
||||||
|
};
|
||||||
|
}
|
1
ts_interfaces/data/config.ts
Normal file
1
ts_interfaces/data/config.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type TConfigType = 'server' | 'cluster' | 'coreflow' | 'service';
|
14
ts_interfaces/data/deployment.ts
Normal file
14
ts_interfaces/data/deployment.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* results from a DeploymentDirective
|
||||||
|
* tracks the status of a deployment
|
||||||
|
*/
|
||||||
|
export interface IDeployment {
|
||||||
|
id: string;
|
||||||
|
deploymentDirectiveId: string;
|
||||||
|
affectedServiceIds: string[];
|
||||||
|
usedImageId: string;
|
||||||
|
deploymentLog: string[];
|
||||||
|
status: 'scheduled' | 'running' | 'deployed' | 'failed';
|
||||||
|
}
|
14
ts_interfaces/data/deploymentdirective.ts
Normal file
14
ts_interfaces/data/deploymentdirective.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import type { IServiceRessources } from "./docker.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used for tellilng a cluster about a disired deployment
|
||||||
|
* and specifies its configuration
|
||||||
|
*/
|
||||||
|
export interface IDeploymentDirective {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
imageClaim: string;
|
||||||
|
ports: { hostPort: number; containerPort: number }[];
|
||||||
|
environment: { [key: string]: string };
|
||||||
|
resources?: IServiceRessources;
|
||||||
|
}
|
15
ts_interfaces/data/docker.ts
Normal file
15
ts_interfaces/data/docker.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export interface IDockerRegistryInfo {
|
||||||
|
serveraddress: string;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IServiceRessources {
|
||||||
|
cpuLimit?: number;
|
||||||
|
cpuReservation?: number;
|
||||||
|
memorySizeLimitMB?: number;
|
||||||
|
memorySizeReservationMB?: number;
|
||||||
|
volumeMounts?: plugins.tsclass.container.IVolumeMount[];
|
||||||
|
}
|
6
ts_interfaces/data/env.ts
Normal file
6
ts_interfaces/data/env.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
export interface IEnvBundle {
|
||||||
|
environment: string;
|
||||||
|
timeSensitive: boolean;
|
||||||
|
configKeyValueObject: {[key: string]: string};
|
||||||
|
}
|
11
ts_interfaces/data/event.ts
Normal file
11
ts_interfaces/data/event.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export interface IEvent_Cloudly_ContainerVersionNotification
|
||||||
|
extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedEvent<plugins.tsclass.container.IContainer>,
|
||||||
|
IEvent_Cloudly_ContainerVersionNotification
|
||||||
|
> {
|
||||||
|
name: 'newContainerVersion';
|
||||||
|
uniqueEventId: string;
|
||||||
|
payload: plugins.tsclass.container.IContainer;
|
||||||
|
}
|
15
ts_interfaces/data/image.ts
Normal file
15
ts_interfaces/data/image.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export interface IImage {
|
||||||
|
id: string;
|
||||||
|
data: {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
versions: Array<{
|
||||||
|
versionString: string;
|
||||||
|
storagePath?: string;
|
||||||
|
size: number;
|
||||||
|
createdAt: number;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
}
|
17
ts_interfaces/data/index.ts
Normal file
17
ts_interfaces/data/index.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
export * from './cloudlyconfig.js';
|
||||||
|
export * from './cluster.js';
|
||||||
|
export * from './config.js';
|
||||||
|
export * from './deployment.js';
|
||||||
|
export * from './deploymentdirective.js';
|
||||||
|
export * from './docker.js';
|
||||||
|
export * from './env.js';
|
||||||
|
export * from './event.js';
|
||||||
|
export * from './image.js';
|
||||||
|
export * from './secretbundle.js';
|
||||||
|
export * from './secretgroup.js'
|
||||||
|
export * from './server.js';
|
||||||
|
export * from './service.js';
|
||||||
|
export * from './status.js';
|
||||||
|
export * from './traffic.js';
|
||||||
|
export * from './user.js';
|
||||||
|
export * from './version.js';
|
42
ts_interfaces/data/secretbundle.ts
Normal file
42
ts_interfaces/data/secretbundle.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
export interface ISecretBundle {
|
||||||
|
id: string;
|
||||||
|
data: {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* determines if the secret is a service or an external secret
|
||||||
|
* if external secret additional checks are put in place to protect the secret
|
||||||
|
*/
|
||||||
|
type: 'service' | 'npmci' | 'gitzone' | 'external';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can add specific secret groups using this
|
||||||
|
*/
|
||||||
|
includedSecretGroupIds: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can add specific tags using this
|
||||||
|
*/
|
||||||
|
includedTags: {
|
||||||
|
key: string;
|
||||||
|
value?: string;
|
||||||
|
}[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add images
|
||||||
|
*/
|
||||||
|
includedImages: {
|
||||||
|
imageId: string;
|
||||||
|
permissions: ('read' | 'write')[];
|
||||||
|
}[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* authrozations select a specific environment of a config bundle
|
||||||
|
*/
|
||||||
|
authorizations: Array<{
|
||||||
|
secretAccessKey: string;
|
||||||
|
environment: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
}
|
54
ts_interfaces/data/secretgroup.ts
Normal file
54
ts_interfaces/data/secretgroup.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
export interface ISecretGroup {
|
||||||
|
/**
|
||||||
|
* the insatnce id. This should be a random id, except for default
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
data: {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the key of the secretgroup like CI_RUNNER_TOKEN
|
||||||
|
*/
|
||||||
|
key: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the priority of the secretgroup
|
||||||
|
* will be used to determine which secretgroup will be used
|
||||||
|
* when there are multiple secretgroups with the same key
|
||||||
|
*/
|
||||||
|
priority?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* any tags that can be used to filter the secretgroup
|
||||||
|
* can be used for putting secrets into projects
|
||||||
|
*/
|
||||||
|
tags: {
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}[];
|
||||||
|
/**
|
||||||
|
* the values for this secretGroup
|
||||||
|
*/
|
||||||
|
environments: {
|
||||||
|
[key: string]: {
|
||||||
|
value: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* can be used to update the value
|
||||||
|
*/
|
||||||
|
updateToken?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the linux timestamp of the last update
|
||||||
|
*/
|
||||||
|
lastUpdated: number;
|
||||||
|
history: {
|
||||||
|
timestamp: string;
|
||||||
|
value: string;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
36
ts_interfaces/data/server.ts
Normal file
36
ts_interfaces/data/server.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
import { type IDockerRegistryInfo } from './docker.js';
|
||||||
|
|
||||||
|
export interface IServerMetrics {
|
||||||
|
serverId: string;
|
||||||
|
cpuUsageInPercent: number;
|
||||||
|
memoryUsageinMB: number;
|
||||||
|
memoryAvailableInMB: number;
|
||||||
|
containerCount: number;
|
||||||
|
containerMetrics: Array<{
|
||||||
|
containerId: string;
|
||||||
|
containerName: string;
|
||||||
|
cpuUsageInPercent: number;
|
||||||
|
memoryUsageInMB: number;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IServer {
|
||||||
|
id: string;
|
||||||
|
data: {
|
||||||
|
type: 'baremetal' | 'hetzner';
|
||||||
|
|
||||||
|
assignedClusterId: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a list of debian packages to be installed
|
||||||
|
*/
|
||||||
|
requiredDebianPackages: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a list of SSH keys to deploy
|
||||||
|
*/
|
||||||
|
sshKeys: plugins.tsclass.network.ISshKey[];
|
||||||
|
};
|
||||||
|
}
|
26
ts_interfaces/data/service.ts
Normal file
26
ts_interfaces/data/service.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import type { IServiceRessources } from './docker.js';
|
||||||
|
|
||||||
|
export interface IService {
|
||||||
|
id: string;
|
||||||
|
data: {
|
||||||
|
name: string;
|
||||||
|
imageId: string;
|
||||||
|
imageVersion: string;
|
||||||
|
environment: { [key: string]: string };
|
||||||
|
secretBundleId: string;
|
||||||
|
scaleFactor: number;
|
||||||
|
balancingStrategy: 'round-robin' | 'least-connections';
|
||||||
|
ports: {
|
||||||
|
web: number;
|
||||||
|
custom?: { [domain: string]: string };
|
||||||
|
};
|
||||||
|
resources?: IServiceRessources;
|
||||||
|
domains: {
|
||||||
|
name: string;
|
||||||
|
port?: number;
|
||||||
|
protocol?: 'http' | 'https' | 'ssh';
|
||||||
|
}[];
|
||||||
|
deploymentIds: string[];
|
||||||
|
deploymentDirectiveIds: string[];
|
||||||
|
};
|
||||||
|
}
|
20
ts_interfaces/data/status.ts
Normal file
20
ts_interfaces/data/status.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export interface IClusterStatus {
|
||||||
|
name: string;
|
||||||
|
ip: string;
|
||||||
|
nodesCount: number;
|
||||||
|
containersUnderManagementCount: number;
|
||||||
|
nodeStatusId: string;
|
||||||
|
containerStatusArray: IContainerStatus[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface INodeStatus {
|
||||||
|
nodeId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IContainerStatus {
|
||||||
|
serviceName: string;
|
||||||
|
dockerImageUrl: string;
|
||||||
|
dockerImageVersion: string;
|
||||||
|
}
|
5
ts_interfaces/data/traffic.ts
Normal file
5
ts_interfaces/data/traffic.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
interface IReverseProxyConfig extends plugins.tsclass.network.IReverseProxyConfig {}
|
||||||
|
|
||||||
|
export { type IReverseProxyConfig };
|
30
ts_interfaces/data/user.ts
Normal file
30
ts_interfaces/data/user.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
export interface IToken {
|
||||||
|
token: string;
|
||||||
|
expiresAt: number;
|
||||||
|
assignedRoles: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* an identity is assumed by authentication as a user
|
||||||
|
* an identity is ephemeral and has to be renewed regularly
|
||||||
|
*/
|
||||||
|
export interface IIdentity {
|
||||||
|
name: string;
|
||||||
|
userId: string;
|
||||||
|
type: 'machine' | 'human';
|
||||||
|
role: 'admin' | 'user' | 'api' | 'cluster';
|
||||||
|
expiresAt: number;
|
||||||
|
/** the jwt token should contain above data for verification */
|
||||||
|
jwt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUser {
|
||||||
|
id: string;
|
||||||
|
data: {
|
||||||
|
type: 'machine' | 'human';
|
||||||
|
role: 'admin' | 'user' | 'api' | 'cluster';
|
||||||
|
username?: string;
|
||||||
|
password?: string;
|
||||||
|
tokens?: IToken[];
|
||||||
|
}
|
||||||
|
}
|
11
ts_interfaces/data/version.ts
Normal file
11
ts_interfaces/data/version.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export interface IContainerVersionData {
|
||||||
|
/**
|
||||||
|
* the docker image url
|
||||||
|
* example: registry.gitlab.com/hosttoday/ht-docker-node:latest
|
||||||
|
*/
|
||||||
|
dockerImageUrl: string;
|
||||||
|
/**
|
||||||
|
* the docker image version. Note: This is different from docker tags that are often used for versions.
|
||||||
|
*/
|
||||||
|
dockerImageVersion: string;
|
||||||
|
}
|
9
ts_interfaces/index.ts
Normal file
9
ts_interfaces/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import * as data from './data/index.js';
|
||||||
|
import * as platformservice from './platformservice/index.js';
|
||||||
|
import * as requests from './requests/index.js';
|
||||||
|
|
||||||
|
export {
|
||||||
|
data,
|
||||||
|
platformservice,
|
||||||
|
requests
|
||||||
|
}
|
1
ts_interfaces/platformservice/00readme.md
Normal file
1
ts_interfaces/platformservice/00readme.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
The platform folder contains types that can be used for talking with the underlying platform by apps running on serve.zone.
|
23
ts_interfaces/platformservice/aibridge.ts
Normal file
23
ts_interfaces/platformservice/aibridge.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export interface IChat {
|
||||||
|
systemMessage: string;
|
||||||
|
messages: {
|
||||||
|
role: 'assistant' | 'user';
|
||||||
|
content: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IReq_Chat extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IReq_Chat
|
||||||
|
> {
|
||||||
|
method: 'chat',
|
||||||
|
request: {
|
||||||
|
chat: IChat;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
chat: IChat;
|
||||||
|
latestMessage: string;
|
||||||
|
}
|
||||||
|
}
|
13
ts_interfaces/platformservice/index.ts
Normal file
13
ts_interfaces/platformservice/index.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import * as aibridge from './aibridge.js';
|
||||||
|
import * as letter from './letter.js';
|
||||||
|
import * as mta from './mta.js';
|
||||||
|
import * as pushnotification from './pushnotification.js';
|
||||||
|
import * as sms from './sms.js';
|
||||||
|
|
||||||
|
export {
|
||||||
|
aibridge,
|
||||||
|
letter,
|
||||||
|
mta,
|
||||||
|
pushnotification,
|
||||||
|
sms,
|
||||||
|
}
|
34
ts_interfaces/platformservice/letter.ts
Normal file
34
ts_interfaces/platformservice/letter.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export interface IRequest_SendLetter extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_SendLetter
|
||||||
|
> {
|
||||||
|
method: 'sendLetter';
|
||||||
|
request: {
|
||||||
|
/**
|
||||||
|
* will be used in logs
|
||||||
|
*/
|
||||||
|
description: string;
|
||||||
|
/**
|
||||||
|
* if you send any PDF / invoice that you have not made sure to be letterxpress compliant
|
||||||
|
* we strongly recommend using a cover page
|
||||||
|
*/
|
||||||
|
needsCover: boolean;
|
||||||
|
title?: string;
|
||||||
|
from?: plugins.tsclass.business.IAddress;
|
||||||
|
to?: plugins.tsclass.business.IAddress;
|
||||||
|
coverBody?: string;
|
||||||
|
service: ('Einschreiben')[];
|
||||||
|
pdfAttachments?: Array<{
|
||||||
|
name: string;
|
||||||
|
binaryAttachmentString: string;
|
||||||
|
}>
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
/**
|
||||||
|
* this process id allows status retrieval of the letter
|
||||||
|
*/
|
||||||
|
processId: string;
|
||||||
|
};
|
||||||
|
}
|
39
ts_interfaces/platformservice/mta.ts
Normal file
39
ts_interfaces/platformservice/mta.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export type TTemplates = 'default' | 'linkaction' | 'notification';
|
||||||
|
|
||||||
|
export interface IRequest_SendEmail extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_SendEmail
|
||||||
|
> {
|
||||||
|
method: 'sendEmail';
|
||||||
|
request: {
|
||||||
|
title: string;
|
||||||
|
from: string;
|
||||||
|
to: string;
|
||||||
|
body: string;
|
||||||
|
attachments?: Array<{
|
||||||
|
name: string;
|
||||||
|
binaryAttachmentString: string;
|
||||||
|
}>
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
/**
|
||||||
|
* the response id allows for handling of responses to that email
|
||||||
|
*/
|
||||||
|
responseId: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRequestRegisterRecipient extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequestRegisterRecipient
|
||||||
|
> {
|
||||||
|
method: 'registerRecepient';
|
||||||
|
request: {
|
||||||
|
emailAddress: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
status: 'ok' | 'not ok';
|
||||||
|
};
|
||||||
|
}
|
16
ts_interfaces/platformservice/pushnotification.ts
Normal file
16
ts_interfaces/platformservice/pushnotification.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export interface IRequest_SendPushNotification extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_SendPushNotification
|
||||||
|
> {
|
||||||
|
method: 'sendPushNotification';
|
||||||
|
request: {
|
||||||
|
deviceToken: string;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
response: {
|
||||||
|
ok: boolean;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
}
|
33
ts_interfaces/platformservice/sms.ts
Normal file
33
ts_interfaces/platformservice/sms.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export interface IRequest_SendSms
|
||||||
|
extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_SendSms
|
||||||
|
> {
|
||||||
|
method: 'sendSms';
|
||||||
|
request: {
|
||||||
|
toNumber: number;
|
||||||
|
fromName: string;
|
||||||
|
messageText: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
status: 'ok' | 'not ok';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRequest_SendVerificationCode
|
||||||
|
extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_SendVerificationCode
|
||||||
|
> {
|
||||||
|
method: 'sendVerificationCode';
|
||||||
|
request: {
|
||||||
|
toNumber: number;
|
||||||
|
fromName: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
status: 'ok' | 'not ok';
|
||||||
|
verificationCode: string;
|
||||||
|
}
|
||||||
|
}
|
20
ts_interfaces/plugins.ts
Normal file
20
ts_interfaces/plugins.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// @apiglobal scope
|
||||||
|
import * as typedrequestInterfaces from '@api.global/typedrequest-interfaces';
|
||||||
|
|
||||||
|
export {
|
||||||
|
typedrequestInterfaces
|
||||||
|
}
|
||||||
|
|
||||||
|
// @push.rocks scope
|
||||||
|
import * as smartlogInterfaces from '@push.rocks/smartlog-interfaces';
|
||||||
|
|
||||||
|
export {
|
||||||
|
smartlogInterfaces,
|
||||||
|
}
|
||||||
|
|
||||||
|
// tsclass scope
|
||||||
|
import * as tsclass from '@tsclass/tsclass';
|
||||||
|
|
||||||
|
export {
|
||||||
|
tsclass
|
||||||
|
}
|
18
ts_interfaces/requests/certificate.ts
Normal file
18
ts_interfaces/requests/certificate.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as userInterfaces from '../data/user.js';
|
||||||
|
|
||||||
|
export interface IRequest_Any_Cloudly_GetCertificateForDomain
|
||||||
|
extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_Any_Cloudly_GetCertificateForDomain
|
||||||
|
> {
|
||||||
|
method: 'getCertificateForDomain';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
domainName: string;
|
||||||
|
type: 'ssl';
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
certificate: plugins.tsclass.network.ICert;
|
||||||
|
};
|
||||||
|
}
|
67
ts_interfaces/requests/cluster.ts
Normal file
67
ts_interfaces/requests/cluster.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import * as userInterfaces from '../data/user.js';
|
||||||
|
import * as clusterInterfaces from '../data/cluster.js';
|
||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get all clusters
|
||||||
|
*/
|
||||||
|
export interface IRequest_GetAllClusters extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_GetAllClusters
|
||||||
|
> {
|
||||||
|
method: 'getAllClusters';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
clusters: clusterInterfaces.ICluster[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRequest_CreateCluster extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_CreateCluster
|
||||||
|
> {
|
||||||
|
method: 'createCluster';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
clusterName: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
clusterConfig: clusterInterfaces.ICluster;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* updates a cluster
|
||||||
|
*/
|
||||||
|
export interface IRequest_UpdateCluster extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_UpdateCluster
|
||||||
|
> {
|
||||||
|
method: 'updateCluster';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
clusterConfig: clusterInterfaces.ICluster;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
clusterConfig: clusterInterfaces.ICluster;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* deletes a cluster
|
||||||
|
*/
|
||||||
|
export interface IRequest_DeleteCluster extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_DeleteCluster
|
||||||
|
> {
|
||||||
|
method: 'deleteCluster';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
clusterId: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
success: boolean;
|
||||||
|
};
|
||||||
|
}
|
49
ts_interfaces/requests/config.ts
Normal file
49
ts_interfaces/requests/config.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as clusterInterfaces from '../data/cluster.js';
|
||||||
|
import * as serverInterfaces from '../data/server.js';
|
||||||
|
import * as userInterfaces from '../data/user.js';
|
||||||
|
import type { IService } from '../data/service.js';
|
||||||
|
import type { IDeploymentDirective } from '../data/deploymentdirective.js';
|
||||||
|
|
||||||
|
export interface IRequest_Any_Cloudly_GetServerConfig
|
||||||
|
extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_Any_Cloudly_GetServerConfig
|
||||||
|
> {
|
||||||
|
method: 'getServerConfig';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
serverId: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
configData: serverInterfaces.IServer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRequest_Any_Cloudly_GetClusterConfig
|
||||||
|
extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_Any_Cloudly_GetClusterConfig
|
||||||
|
> {
|
||||||
|
method: 'getClusterConfig';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
configData: clusterInterfaces.ICluster;
|
||||||
|
deploymentDirectives: IDeploymentDirective[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRequest_Cloudly_Coreflow_PushClusterConfig
|
||||||
|
extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_Cloudly_Coreflow_PushClusterConfig
|
||||||
|
> {
|
||||||
|
method: 'pushClusterConfig';
|
||||||
|
request: {
|
||||||
|
configData: clusterInterfaces.ICluster;
|
||||||
|
deploymentDirectives: IDeploymentDirective[];
|
||||||
|
};
|
||||||
|
response: {};
|
||||||
|
}
|
23
ts_interfaces/requests/identity.ts
Normal file
23
ts_interfaces/requests/identity.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as userInterfaces from '../data/user.js'
|
||||||
|
|
||||||
|
// ========
|
||||||
|
// IDENTITY
|
||||||
|
// ========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the identity that then will be used to get the config
|
||||||
|
*/
|
||||||
|
export interface IRequest_Any_Cloudly_CoreflowManager_GetIdentityByToken
|
||||||
|
extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_Any_Cloudly_CoreflowManager_GetIdentityByToken
|
||||||
|
> {
|
||||||
|
method: 'getIdentityByToken';
|
||||||
|
request: {
|
||||||
|
token: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
};
|
||||||
|
}
|
94
ts_interfaces/requests/image.ts
Normal file
94
ts_interfaces/requests/image.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as userInterfaces from '../data/user.js';
|
||||||
|
|
||||||
|
import type { IImage } from '../data/index.js';
|
||||||
|
|
||||||
|
export interface IRequest_GetAllImages extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_GetAllImages
|
||||||
|
> {
|
||||||
|
method: 'getAllImages';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
images: IImage[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets a single image
|
||||||
|
*/
|
||||||
|
export interface IRequest_GetImage extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_GetImage
|
||||||
|
> {
|
||||||
|
method: 'getImage';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
imageId: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
image: IImage;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRequest_CreateImage extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_CreateImage
|
||||||
|
> {
|
||||||
|
method: 'createImage';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
image: IImage;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRequest_PushImageVersion extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_PushImageVersion
|
||||||
|
> {
|
||||||
|
method: 'pushImageVersion';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
imageId: string;
|
||||||
|
versionString: string;
|
||||||
|
imageStream: plugins.typedrequestInterfaces.IVirtualStream;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
allowed: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRequest_PullImageVersion extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_PullImageVersion
|
||||||
|
> {
|
||||||
|
method: 'pullImageVersion';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
imageId: string;
|
||||||
|
versionString: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
imageStream: plugins.typedrequestInterfaces.IVirtualStream;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRequest_DeleteImage extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_DeleteImage
|
||||||
|
> {
|
||||||
|
method: 'deleteImage';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
imageId: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
};
|
||||||
|
}
|
33
ts_interfaces/requests/index.ts
Normal file
33
ts_interfaces/requests/index.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
import * as certificateRequests from './certificate.js';
|
||||||
|
import * as clusterRequests from './cluster.js';
|
||||||
|
import * as configRequests from './config.js';
|
||||||
|
import * as identityRequests from './identity.js';
|
||||||
|
import * as imageRequests from './image.js';
|
||||||
|
import * as informRequests from './inform.js';
|
||||||
|
import * as logRequests from './log.js';
|
||||||
|
import * as networkRequests from './network.js';
|
||||||
|
import * as routingRequests from './routing.js';
|
||||||
|
import * as secretRequests from './secret.js';
|
||||||
|
import * as serverRequests from './server.js';
|
||||||
|
import * as statusRequests from './status.js';
|
||||||
|
import * as versionRequests from './version.js';
|
||||||
|
|
||||||
|
export {
|
||||||
|
certificateRequests as certificate,
|
||||||
|
clusterRequests as cluster,
|
||||||
|
configRequests as config,
|
||||||
|
identityRequests as identity,
|
||||||
|
imageRequests as image,
|
||||||
|
informRequests as inform,
|
||||||
|
logRequests as log,
|
||||||
|
networkRequests as network,
|
||||||
|
routingRequests as routing,
|
||||||
|
secretRequests as secret,
|
||||||
|
serverRequests as server,
|
||||||
|
statusRequests as status,
|
||||||
|
versionRequests as version,
|
||||||
|
};
|
||||||
|
|
||||||
|
export * from './inform.js';
|
12
ts_interfaces/requests/inform.ts
Normal file
12
ts_interfaces/requests/inform.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export interface IRequest_InformAboutNewContainerImage extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_InformAboutNewContainerImage
|
||||||
|
> {
|
||||||
|
method: 'servezonestandard_InformAboutNewContainerVersion';
|
||||||
|
request: {
|
||||||
|
containerImageInfo: plugins.tsclass.container.IContainer
|
||||||
|
};
|
||||||
|
response: {};
|
||||||
|
}
|
13
ts_interfaces/requests/log.ts
Normal file
13
ts_interfaces/requests/log.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export interface IRequest_Log extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_Log
|
||||||
|
> {
|
||||||
|
method: 'log';
|
||||||
|
request: {
|
||||||
|
authToken: string;
|
||||||
|
logPackages: plugins.smartlogInterfaces.ILogPackage[];
|
||||||
|
},
|
||||||
|
response: {};
|
||||||
|
}
|
9
ts_interfaces/requests/network.ts
Normal file
9
ts_interfaces/requests/network.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
export interface IRequest_Any_Cloudly_GetNetworkNodes {
|
||||||
|
method: 'getNetworkNodes';
|
||||||
|
request: {};
|
||||||
|
response: {
|
||||||
|
networkNodes: plugins.tsclass.network.INetworkNode[];
|
||||||
|
};
|
||||||
|
}
|
12
ts_interfaces/requests/routing.ts
Normal file
12
ts_interfaces/requests/routing.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { type IReverseProxyConfig } from '../data/traffic.js';
|
||||||
|
|
||||||
|
export interface IRequest_Coreflow_Coretraffic_RoutingUpdate {
|
||||||
|
method: 'updateRouting';
|
||||||
|
request: {
|
||||||
|
reverseConfigs: IReverseProxyConfig[];
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
status: 'ok' | 'error';
|
||||||
|
errorText: string;
|
||||||
|
};
|
||||||
|
}
|
94
ts_interfaces/requests/secret.ts
Normal file
94
ts_interfaces/requests/secret.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as data from '../data/index.js';
|
||||||
|
import * as userInterfaces from '../data/user.js';
|
||||||
|
|
||||||
|
export interface IReq_GetEnvBundle extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IReq_GetEnvBundle
|
||||||
|
> {
|
||||||
|
method: 'getEnvBundle';
|
||||||
|
request: {
|
||||||
|
authorization: string;
|
||||||
|
/**
|
||||||
|
* specify this if you want to get a warning, if the envBundle is for an unexpected environment
|
||||||
|
*/
|
||||||
|
environment?: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
envBundle: data.IEnvBundle;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IReq_Admin_LoginWithUsernameAndPassword extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IReq_Admin_LoginWithUsernameAndPassword
|
||||||
|
> {
|
||||||
|
method: 'adminLoginWithUsernameAndPassword';
|
||||||
|
request: {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IReq_Admin_GetConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IReq_Admin_GetConfigBundlesAndSecretGroups
|
||||||
|
> {
|
||||||
|
method: 'adminGetConfigBundlesAndSecretGroups';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
secretBundles: data.ISecretBundle[];
|
||||||
|
secretGroups: data.ISecretGroup[];
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IReq_Admin_CreateConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IReq_Admin_CreateConfigBundlesAndSecretGroups
|
||||||
|
> {
|
||||||
|
method: 'adminCreateConfigBundlesAndSecretGroups';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
secretBundles: data.ISecretBundle[];
|
||||||
|
secretGroups: data.ISecretGroup[];
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
ok: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IReq_Admin_UpdateConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IReq_Admin_UpdateConfigBundlesAndSecretGroups
|
||||||
|
> {
|
||||||
|
method: 'adminUpdateConfigBundlesAndSecretGroups';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
configBundles: data.ISecretBundle[];
|
||||||
|
secretGroups: data.ISecretGroup[];
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
ok: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IReq_Admin_DeleteConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IReq_Admin_DeleteConfigBundlesAndSecretGroups
|
||||||
|
> {
|
||||||
|
method: 'adminDeleteConfigBundlesAndSecretGroups';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
secretBundleIds: string[];
|
||||||
|
secretGroupIds: string[];
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
ok: boolean;
|
||||||
|
};
|
||||||
|
}
|
47
ts_interfaces/requests/server.ts
Normal file
47
ts_interfaces/requests/server.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import type { IServerMetrics } from '../data/server.js';
|
||||||
|
import * as plugins from '../plugins.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This request can be used between any two players
|
||||||
|
* Examples:
|
||||||
|
* WebApp -> Cloudly (get metrics)
|
||||||
|
* Cloudly -> Webapp (send metrics)
|
||||||
|
* Cloudly -> Coreflow (get metrics)
|
||||||
|
* Coreflow -> Cloudly (send metrics)
|
||||||
|
*/
|
||||||
|
export interface IRequest_Any_Cloudly_ServerStatus
|
||||||
|
extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_Any_Cloudly_ServerStatus
|
||||||
|
> {
|
||||||
|
method: 'getOrSendServerMetrics',
|
||||||
|
request: {
|
||||||
|
getOrSend: 'get' | 'send';
|
||||||
|
serverMetrics?: IServerMetrics;
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
serverMetrics?: IServerMetrics;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this request can be used between any two players
|
||||||
|
* Examples:
|
||||||
|
* WebApp -> Cloudly
|
||||||
|
* Cloudly -> Coreflow
|
||||||
|
* Cloudly -> HostingProvider
|
||||||
|
*/
|
||||||
|
export interface IRequest_TriggerServerAction
|
||||||
|
extends plugins.typedrequestInterfaces.implementsTR<
|
||||||
|
plugins.typedrequestInterfaces.ITypedRequest,
|
||||||
|
IRequest_TriggerServerAction
|
||||||
|
> {
|
||||||
|
method: 'triggerServerAction';
|
||||||
|
request: {
|
||||||
|
actionName: 'reboot' | 'rebuild';
|
||||||
|
payload: any;
|
||||||
|
};
|
||||||
|
response: {
|
||||||
|
actionConfirmed: boolean;
|
||||||
|
};
|
||||||
|
}
|
12
ts_interfaces/requests/status.ts
Normal file
12
ts_interfaces/requests/status.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import * as userInterfaces from '../data/user.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a status update dashboard
|
||||||
|
*/
|
||||||
|
export interface IRequest_Coreflow_Cloudly_CoreflowManagerStatusupdate {
|
||||||
|
method: 'cloudlyStatus';
|
||||||
|
request: {
|
||||||
|
identity: userInterfaces.IIdentity;
|
||||||
|
};
|
||||||
|
response: {};
|
||||||
|
}
|
8
ts_interfaces/requests/version.ts
Normal file
8
ts_interfaces/requests/version.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import * as versionInterfaces from '../data/version.js';
|
||||||
|
|
||||||
|
// Containers
|
||||||
|
export interface IRequest_Any_Cloudly_VersionManager_InformCloudlyAboutNewContainerVersion {
|
||||||
|
method: 'informCloudlyAboutNewContainerVersion';
|
||||||
|
request: versionInterfaces.IContainerVersionData;
|
||||||
|
response: {};
|
||||||
|
}
|
12
ts_interfaces/tspublish.json
Normal file
12
ts_interfaces/tspublish.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "@serve.zone/interfaces",
|
||||||
|
"dependencies": [
|
||||||
|
"@api.global/typedrequest-interfaces",
|
||||||
|
"@push.rocks/smartlog-interfaces",
|
||||||
|
"@tsclass/tsclass"
|
||||||
|
],
|
||||||
|
"registries": [
|
||||||
|
"registry.npmjs.org:public",
|
||||||
|
"verdaccio.lossless.digital:public"
|
||||||
|
]
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* autocreated commitinfo by @pushrocks/commitinfo
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/cloudly',
|
name: '@serve.zone/cloudly',
|
||||||
version: '1.1.5',
|
version: '1.2.5',
|
||||||
description: 'A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and integrate robust configuration and API management capabilities.'
|
description: 'A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.'
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,11 @@ import * as domtools from '@design.estate/dees-domtools';
|
|||||||
|
|
||||||
const appstate = new plugins.deesDomtools.plugins.smartstate.Smartstate();
|
const appstate = new plugins.deesDomtools.plugins.smartstate.Smartstate();
|
||||||
export interface ILoginState {
|
export interface ILoginState {
|
||||||
jwt: string;
|
identity: plugins.interfaces.data.IIdentity;
|
||||||
}
|
}
|
||||||
export const loginStatePart: plugins.smartstate.StatePart<unknown, ILoginState> = await appstate.getStatePart<ILoginState>(
|
export const loginStatePart: plugins.smartstate.StatePart<unknown, ILoginState> = await appstate.getStatePart<ILoginState>(
|
||||||
'login',
|
'login',
|
||||||
{ jwt: null },
|
{ identity: null },
|
||||||
'persistent'
|
'persistent'
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -22,10 +22,15 @@ export const loginAction = loginStatePart.createAction<{ username: string; passw
|
|||||||
const response = await trLogin.fire({
|
const response = await trLogin.fire({
|
||||||
username: payloadArg.username,
|
username: payloadArg.username,
|
||||||
password: payloadArg.password,
|
password: payloadArg.password,
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
return {
|
||||||
|
...statePartArg.getState(),
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
...currentState,
|
...currentState,
|
||||||
...(response.jwt ? { jwt: response.jwt } : {}),
|
...(response.identity ? { identity: response.identity } : {}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -34,7 +39,7 @@ export const logoutAction = loginStatePart.createAction(async (statePartArg) =>
|
|||||||
const currentState = statePartArg.getState();
|
const currentState = statePartArg.getState();
|
||||||
return {
|
return {
|
||||||
...currentState,
|
...currentState,
|
||||||
jwt: null,
|
identity: null,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -81,7 +86,7 @@ export const getAllDataAction = dataState.createAction(async (statePartArg, part
|
|||||||
'adminGetConfigBundlesAndSecretGroups'
|
'adminGetConfigBundlesAndSecretGroups'
|
||||||
);
|
);
|
||||||
const response = await trGetSecrets.fire({
|
const response = await trGetSecrets.fire({
|
||||||
jwt: loginStatePart.getState().jwt,
|
identity: loginStatePart.getState().identity,
|
||||||
});
|
});
|
||||||
currentState = {
|
currentState = {
|
||||||
...currentState,
|
...currentState,
|
||||||
@ -95,7 +100,7 @@ export const getAllDataAction = dataState.createAction(async (statePartArg, part
|
|||||||
'getAllImages'
|
'getAllImages'
|
||||||
);
|
);
|
||||||
const responseImages = await trGetImages.fire({
|
const responseImages = await trGetImages.fire({
|
||||||
jwt: loginStatePart.getState().jwt,
|
identity: loginStatePart.getState().identity,
|
||||||
});
|
});
|
||||||
currentState = {
|
currentState = {
|
||||||
...currentState,
|
...currentState,
|
||||||
@ -109,7 +114,7 @@ export const getAllDataAction = dataState.createAction(async (statePartArg, part
|
|||||||
'getAllClusters'
|
'getAllClusters'
|
||||||
);
|
);
|
||||||
const responseClusters = await trGetClusters.fire({
|
const responseClusters = await trGetClusters.fire({
|
||||||
jwt: loginStatePart.getState().jwt,
|
identity: loginStatePart.getState().identity,
|
||||||
});
|
});
|
||||||
|
|
||||||
currentState = {
|
currentState = {
|
||||||
@ -130,7 +135,7 @@ export const createSecretGroupAction = dataState.createAction(
|
|||||||
'adminCreateConfigBundlesAndSecretGroups'
|
'adminCreateConfigBundlesAndSecretGroups'
|
||||||
);
|
);
|
||||||
const response = await trCreateSecretGroup.fire({
|
const response = await trCreateSecretGroup.fire({
|
||||||
jwt: loginStatePart.getState().jwt,
|
identity: loginStatePart.getState().identity,
|
||||||
secretBundles: [],
|
secretBundles: [],
|
||||||
secretGroups: [payloadArg],
|
secretGroups: [payloadArg],
|
||||||
});
|
});
|
||||||
@ -149,7 +154,7 @@ export const deleteSecretGroupAction = dataState.createAction(
|
|||||||
'adminDeleteConfigBundlesAndSecretGroups'
|
'adminDeleteConfigBundlesAndSecretGroups'
|
||||||
);
|
);
|
||||||
const response = await trDeleteSecretGroup.fire({
|
const response = await trDeleteSecretGroup.fire({
|
||||||
jwt: loginStatePart.getState().jwt,
|
identity: loginStatePart.getState().identity,
|
||||||
secretBundleIds: [],
|
secretBundleIds: [],
|
||||||
secretGroupIds: [payloadArg.secretGroupId],
|
secretGroupIds: [payloadArg.secretGroupId],
|
||||||
});
|
});
|
||||||
@ -168,7 +173,7 @@ export const deleteSecretBundleAction = dataState.createAction(
|
|||||||
'adminDeleteConfigBundlesAndSecretGroups'
|
'adminDeleteConfigBundlesAndSecretGroups'
|
||||||
);
|
);
|
||||||
const response = await trDeleteConfigBundle.fire({
|
const response = await trDeleteConfigBundle.fire({
|
||||||
jwt: loginStatePart.getState().jwt,
|
identity: loginStatePart.getState().identity,
|
||||||
secretBundleIds: [payloadArg.configBundleId],
|
secretBundleIds: [payloadArg.configBundleId],
|
||||||
secretGroupIds: [],
|
secretGroupIds: [],
|
||||||
});
|
});
|
||||||
@ -187,7 +192,7 @@ export const createImageAction = dataState.createAction(
|
|||||||
'createImage'
|
'createImage'
|
||||||
);
|
);
|
||||||
const response = await trCreateImage.fire({
|
const response = await trCreateImage.fire({
|
||||||
jwt: loginStatePart.getState().jwt,
|
identity: loginStatePart.getState().identity,
|
||||||
name: payloadArg.imageName,
|
name: payloadArg.imageName,
|
||||||
description: payloadArg.description,
|
description: payloadArg.description,
|
||||||
});
|
});
|
||||||
@ -210,7 +215,7 @@ export const deleteImageAction = dataState.createAction(
|
|||||||
'deleteImage'
|
'deleteImage'
|
||||||
);
|
);
|
||||||
const response = await trDeleteImage.fire({
|
const response = await trDeleteImage.fire({
|
||||||
jwt: loginStatePart.getState().jwt,
|
identity: loginStatePart.getState().identity,
|
||||||
imageId: payloadArg.imageId,
|
imageId: payloadArg.imageId,
|
||||||
});
|
});
|
||||||
currentState = {
|
currentState = {
|
||||||
@ -238,7 +243,7 @@ export const addClusterAction = dataState.createAction(
|
|||||||
'createCluster'
|
'createCluster'
|
||||||
);
|
);
|
||||||
const response = await trAddCluster.fire({
|
const response = await trAddCluster.fire({
|
||||||
jwt: loginStatePart.getState().jwt,
|
identity: loginStatePart.getState().identity,
|
||||||
...payloadArg,
|
...payloadArg,
|
||||||
});
|
});
|
||||||
currentState = {
|
currentState = {
|
||||||
|
@ -33,7 +33,7 @@ declare global {
|
|||||||
|
|
||||||
@customElement('cloudly-dashboard')
|
@customElement('cloudly-dashboard')
|
||||||
export class CloudlyDashboard extends DeesElement {
|
export class CloudlyDashboard extends DeesElement {
|
||||||
@state() private jwt: string;
|
@state() private identity: plugins.interfaces.data.IIdentity;
|
||||||
@state() private data: appstate.IDataState = {
|
@state() private data: appstate.IDataState = {
|
||||||
secretGroups: [],
|
secretGroups: [],
|
||||||
secretBundles: [],
|
secretBundles: [],
|
||||||
@ -97,6 +97,10 @@ export class CloudlyDashboard extends DeesElement {
|
|||||||
name: 'Services',
|
name: 'Services',
|
||||||
element: CloudlyViewServices,
|
element: CloudlyViewServices,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Testing & Building',
|
||||||
|
element: CloudlyViewServices,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Deployments',
|
name: 'Deployments',
|
||||||
element: CloudlyViewDeployments,
|
element: CloudlyViewDeployments,
|
||||||
@ -169,8 +173,8 @@ export class CloudlyDashboard extends DeesElement {
|
|||||||
const domtools = await this.domtoolsPromise;
|
const domtools = await this.domtoolsPromise;
|
||||||
const loginState = appstate.loginStatePart.getState();
|
const loginState = appstate.loginStatePart.getState();
|
||||||
console.log(loginState);
|
console.log(loginState);
|
||||||
if (loginState.jwt) {
|
if (loginState.identity) {
|
||||||
this.jwt = loginState.jwt;
|
this.identity = loginState.identity;
|
||||||
await simpleLogin.switchToSlottedContent();
|
await simpleLogin.switchToSlottedContent();
|
||||||
await appstate.dataState.dispatchAction(appstate.getAllDataAction, null);
|
await appstate.dataState.dispatchAction(appstate.getAllDataAction, null);
|
||||||
}
|
}
|
||||||
@ -186,9 +190,9 @@ export class CloudlyDashboard extends DeesElement {
|
|||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
});
|
});
|
||||||
if (state.jwt) {
|
if (state.identity) {
|
||||||
console.log('got jwt');
|
console.log('got jwt');
|
||||||
this.jwt = state.jwt;
|
this.identity = state.identity;
|
||||||
form.setStatus('success', 'Logged in!');
|
form.setStatus('success', 'Logged in!');
|
||||||
await simpleLogin.switchToSlottedContent();
|
await simpleLogin.switchToSlottedContent();
|
||||||
await appstate.dataState.dispatchAction(appstate.getAllDataAction, null);
|
await appstate.dataState.dispatchAction(appstate.getAllDataAction, null);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewBackups extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewClusters extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewDbs extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewDeployments extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,8 @@ export class CloudlyViewDns extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import { DeesElement, customElement, html, state, css, cssManager } from '@design.estate/dees-element';
|
import { DeesElement, customElement, html, state, css, cssManager } from '@design.estate/dees-element';
|
||||||
|
|
||||||
@ -23,13 +24,9 @@ export class CloudlyViewImages extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewLogs extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,14 +32,8 @@ export class CloudlyViewMails extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
css`
|
shared.viewHostCss,
|
||||||
:host {
|
css``
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user