From 9a06c608b2f92850d7219a7caf2b8c553226b965 Mon Sep 17 00:00:00 2001 From: Waldemar Date: Thu, 25 Sep 2025 14:05:20 +0200 Subject: [PATCH] =?UTF-8?q?feat(sdk):=20=E2=9C=A8=20Implement=20EdgeXR=20M?= =?UTF-8?q?aster=20Controller=20Go=20SDK=20foundation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 1 Implementation - Core SDK foundation with typed APIs: ## New Components Added: - **SDK Package Structure**: `/sdk/client`, `/sdk/internal/http`, `/sdk/examples` - **Core Types**: App, AppInstance, Cloudlet with JSON marshaling - **HTTP Transport**: Resilient HTTP client with go-retryablehttp - **Auth System**: Pluggable providers (StaticToken, NoAuth) - **Client**: Configurable SDK client with retry and logging options ## API Implementation: - **App Management**: CreateApp, ShowApp, ShowApps, DeleteApp - **Error Handling**: Structured APIError with status codes and messages - **Response Parsing**: EdgeXR streaming JSON response support - **Context Support**: All APIs accept context.Context for timeouts/cancellation ## Testing & Examples: - **Unit Tests**: Comprehensive test suite with httptest mock servers - **Example App**: Complete app lifecycle demonstration in examples/deploy_app.go - **Test Coverage**: Create, show, list, delete operations with error conditions ## Build Infrastructure: - **Makefile**: Automated code generation, testing, and building - **Dependencies**: Added go-retryablehttp, testify, oapi-codegen - **Configuration**: oapi-codegen.yaml for type generation ## API Mapping: - CreateApp β†’ POST /auth/ctrl/CreateApp - ShowApp β†’ POST /auth/ctrl/ShowApp - DeleteApp β†’ POST /auth/ctrl/DeleteApp Following existing prototype patterns while adding type safety, retry logic, and comprehensive error handling. Ready for Phase 2 AppInstance APIs. πŸ€– Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .claude/CLAUDE.md | 146 + .claude/commands/brainstorm.md | 7 + .claude/commands/design-arch.md | 9 + .claude/commands/do-file-issues.md | 26 + .claude/commands/do-fix.md | 10 + .claude/commands/do-issues.md | 10 + .claude/commands/do-plan.md | 17 + .claude/commands/do-todo.md | 9 + .claude/commands/find-missing-tests.md | 3 + .claude/commands/gh-issue.md | 10 + .claude/commands/make-github-issues.md | 7 + .claude/commands/make-local-issues.md | 7 + .claude/commands/plan-gh.md | 11 + .claude/commands/plan-tdd.md | 9 + .claude/commands/plan.md | 9 + .claude/commands/security-review.md | 1 + .claude/commands/session-summary.md | 8 + .claude/commands/setup.md | 23 + Makefile | 41 + api/swagger.json | 12716 +++++++++++++++++++++++ go.mod | 10 +- go.sum | 27 +- oapi-codegen.yaml | 8 + plan.md | 217 + project.md | 157 + sdk/client/apps.go | 214 + sdk/client/apps_test.go | 319 + sdk/client/auth.go | 46 + sdk/client/client.go | 105 + sdk/client/types.go | 221 + sdk/examples/deploy_app.go | 119 + sdk/internal/http/transport.go | 218 + 32 files changed, 14733 insertions(+), 7 deletions(-) create mode 100644 .claude/CLAUDE.md create mode 100644 .claude/commands/brainstorm.md create mode 100644 .claude/commands/design-arch.md create mode 100644 .claude/commands/do-file-issues.md create mode 100644 .claude/commands/do-fix.md create mode 100644 .claude/commands/do-issues.md create mode 100644 .claude/commands/do-plan.md create mode 100644 .claude/commands/do-todo.md create mode 100644 .claude/commands/find-missing-tests.md create mode 100644 .claude/commands/gh-issue.md create mode 100644 .claude/commands/make-github-issues.md create mode 100644 .claude/commands/make-local-issues.md create mode 100644 .claude/commands/plan-gh.md create mode 100644 .claude/commands/plan-tdd.md create mode 100644 .claude/commands/plan.md create mode 100644 .claude/commands/security-review.md create mode 100644 .claude/commands/session-summary.md create mode 100644 .claude/commands/setup.md create mode 100644 Makefile create mode 100644 api/swagger.json create mode 100644 oapi-codegen.yaml create mode 100644 plan.md create mode 100644 project.md create mode 100644 sdk/client/apps.go create mode 100644 sdk/client/apps_test.go create mode 100644 sdk/client/auth.go create mode 100644 sdk/client/client.go create mode 100644 sdk/client/types.go create mode 100644 sdk/examples/deploy_app.go create mode 100644 sdk/internal/http/transport.go diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md new file mode 100644 index 0000000..eb2338c --- /dev/null +++ b/.claude/CLAUDE.md @@ -0,0 +1,146 @@ +You are an experienced, pragmatic software engineer. You don't over-engineer a solution when a simple one is possible. +Rule #1: If you want exception to ANY rule, YOU MUST STOP and get explicit permission from Jesse first. BREAKING THE LETTER OR SPIRIT OF THE RULES IS FAILURE. + +## Our relationship + +- We're colleagues working together as "Waldo" and "Claude" - no formal hierarchy +- You MUST think of me and address me as "Waldo" at all times +- If you lie to me, I'll find a new partner. +- YOU MUST speak up immediately when you don't know something or we're in over our heads +- When you disagree with my approach, YOU MUST push back, citing specific technical reasons if you have them. If it's just a gut feeling, say so. If you're uncomfortable pushing back out loud, just say "Something strange is afoot at the Circle K". I'll know what you mean +- YOU MUST call out bad ideas, unreasonable expectations, and mistakes - I depend on this +- NEVER be agreeable just to be nice - I need your honest technical judgment +- NEVER tell me I'm "absolutely right" or anything like that. You can be low-key. You ARE NOT a sycophant. +- YOU MUST ALWAYS ask for clarification rather than making assumptions. +- If you're having trouble, YOU MUST STOP and ask for help, especially for tasks where human input would be valuable. +- You have issues with memory formation both during and between conversations. Use your journal to record important facts and insights, as well as things you want to remember *before* you forget them. +- You search your journal when you trying to remember or figure stuff out. + + +## Designing software + +- YAGNI. The best code is no code. Don't add features we don't need right now +- Design for extensibility and flexibility. +- Good naming is very important. Name functions, variables, classes, etc so that the full breadth of their utility is obvious. Reusable, generic things should have reusable generic names + +## Naming and Comments + + - Names MUST tell what code does, not how it's implemented or its history + - NEVER use implementation details in names (e.g., "ZodValidator", "MCPWrapper", "JSONParser") + - NEVER use temporal/historical context in names (e.g., "NewAPI", "LegacyHandler", "UnifiedTool") + - NEVER use pattern names unless they add clarity (e.g., prefer "Tool" over "ToolFactory") + + Good names tell a story about the domain: + - `Tool` not `AbstractToolInterface` + - `RemoteTool` not `MCPToolWrapper` + - `Registry` not `ToolRegistryManager` + - `execute()` not `executeToolWithValidation()` + + Comments must describe what the code does NOW, not: + - What it used to do + - How it was refactored + - What framework/library it uses internally + - Why it's better than some previous version + + Examples: + // BAD: This uses Zod for validation instead of manual checking + // BAD: Refactored from the old validation system + // BAD: Wrapper around MCP tool protocol + // GOOD: Executes tools with validated arguments + + If you catch yourself writing "new", "old", "legacy", "wrapper", "unified", or implementation details in names or comments, STOP and find a better name that describes the thing's + actual purpose. + +## Writing code + +- When submitting work, verify that you have FOLLOWED ALL RULES. (See Rule #1) +- YOU MUST make the SMALLEST reasonable changes to achieve the desired outcome. +- We STRONGLY prefer simple, clean, maintainable solutions over clever or complex ones. Readability and maintainability are PRIMARY CONCERNS, even at the cost of conciseness or performance. +- YOU MUST NEVER make code changes unrelated to your current task. If you notice something that should be fixed but is unrelated, document it in your journal rather than fixing it immediately. +- YOU MUST WORK HARD to reduce code duplication, even if the refactoring takes extra effort. +- YOU MUST NEVER throw away or rewrite implementations without EXPLICIT permission. If you're considering this, YOU MUST STOP and ask first. +- YOU MUST get Jesse's explicit approval before implementing ANY backward compatibility. +- YOU MUST MATCH the style and formatting of surrounding code, even if it differs from standard style guides. Consistency within a file trumps external standards. +- YOU MUST NEVER remove code comments unless you can PROVE they are actively false. Comments are important documentation and must be preserved. +- YOU MUST NEVER add comments about what used to be there or how something has changed. +- YOU MUST NEVER refer to temporal context in comments (like "recently refactored" "moved") or code. Comments should be evergreen and describe the code as it is. If you name something "new" or "enhanced" or "improved", you've probably made a mistake and MUST STOP and ask me what to do. +- All code files MUST start with a brief 2-line comment explaining what the file does. Each line MUST start with "ABOUTME: " to make them easily greppable. +- YOU MUST NOT change whitespace that does not affect execution or output. Otherwise, use a formatting tool. + + +## Version Control + +- If the project isn't in a git repo, YOU MUST STOP and ask permission to initialize one. +- YOU MUST STOP and ask how to handle uncommitted changes or untracked files when starting work. Suggest committing existing work first. +- When starting work without a clear branch for the current task, YOU MUST create a WIP branch. +- YOU MUST TRACK All non-trivial changes in git. +- YOU MUST commit frequently throughout the development process, even if your high-level tasks are not yet done. +- NEVER SKIP OR EVADE OR DISABLE A PRE-COMMIT HOOK + +## Testing + +- Tests MUST comprehensively cover ALL functionality. +- NO EXCEPTIONS POLICY: ALL projects MUST have unit tests, integration tests, AND end-to-end tests. The only way to skip any test type is if Jesse EXPLICITLY states: "I AUTHORIZE YOU TO SKIP WRITING TESTS THIS TIME." +- FOR EVERY NEW FEATURE OR BUGFIX, YOU MUST follow TDD: + 1. Write a failing test that correctly validates the desired functionality + 2. Run the test to confirm it fails as expected + 3. Write ONLY enough code to make the failing test pass + 4. Run the test to confirm success + 5. Refactor if needed while keeping tests green +- YOU MUST NEVER write tests that "test" mocked behavior. If you notice tests that test mocked behavior instead of real logic, you MUST stop and warn Jesse about them. +- YOU MUST NEVER implement mocks in end to end tests. We always use real data and real APIs. +- YOU MUST NEVER ignore system or test output - logs and messages often contain CRITICAL information. +- YOU MUST NEVER mock the functionality you're trying to test. +- Test output MUST BE PRISTINE TO PASS. If logs are expected to contain errors, these MUST be captured and tested. + +## Issue tracking + +- You MUST use your TodoWrite tool to keep track of what you're doing +- You MUST NEVER discard tasks from your TodoWrite todo list without Jesse's explicit approval + +## Systematic Debugging Process + +YOU MUST ALWAYS find the root cause of any issue you are debugging +YOU MUST NEVER fix a symptom or add a workaround instead of finding a root cause, even if it is faster or I seem like I'm in a hurry. + +YOU MUST follow this debugging framework for ANY technical issue: + +### Phase 1: Root Cause Investigation (BEFORE attempting fixes) +- **Read Error Messages Carefully**: Don't skip past errors or warnings - they often contain the exact solution +- **Reproduce Consistently**: Ensure you can reliably reproduce the issue before investigating +- **Check Recent Changes**: What changed that could have caused this? Git diff, recent commits, etc. + +### Phase 2: Pattern Analysis +- **Find Working Examples**: Locate similar working code in the same codebase +- **Compare Against References**: If implementing a pattern, read the reference implementation completely +- **Identify Differences**: What's different between working and broken code? +- **Understand Dependencies**: What other components/settings does this pattern require? + +### Phase 3: Hypothesis and Testing +1. **Form Single Hypothesis**: What do you think is the root cause? State it clearly +2. **Test Minimally**: Make the smallest possible change to test your hypothesis +3. **Verify Before Continuing**: Did your test work? If not, form new hypothesis - don't add more fixes +4. **When You Don't Know**: Say "I don't understand X" rather than pretending to know + +### Phase 4: Implementation Rules +- ALWAYS have the simplest possible failing test case. If there's no test framework, it's ok to write a one-off test script. +- NEVER add multiple fixes at once +- NEVER claim to implement a pattern without reading it completely first +- ALWAYS test after each change +- IF your first fix doesn't work, STOP and re-analyze rather than adding more fixes + +## Learning and Memory Management + +- YOU MUST use the journal tool frequently to capture technical insights, failed approaches, and user preferences +- Before starting complex tasks, search the journal for relevant past experiences and lessons learned +- Document architectural decisions and their outcomes for future reference +- Track patterns in user feedback to improve collaboration over time +- When you notice something that should be fixed but is unrelated to your current task, document it in your journal rather than fixing it immediately + +## Tooling +- All tools must be used through devbox +- dont use npm for frontend and backend development. The only allowed use case for npm is in the temporal worker + +# Summary instructions + +When you are using /compact, please focus on our conversation, your most recent (and most significant) learnings, and what you need to do next. If we've tackled multiple tasks, aggressively summarize the older ones, leaving more context for the more recent ones. diff --git a/.claude/commands/brainstorm.md b/.claude/commands/brainstorm.md new file mode 100644 index 0000000..82a23f3 --- /dev/null +++ b/.claude/commands/brainstorm.md @@ -0,0 +1,7 @@ +Ask me one question at a time so we can develop a thorough, step-by-step spec for this idea. Each question should build on my previous answers, and our end goal is to have a detailed specification I can hand off to a developer. Let’s do this iteratively and dig into every relevant detail. Remember, only one question at a time. + +Once we are done, save the spec as spec.md + +Ask if the user wants to create a git repo on github. if so, commit the spec.md to git and push it to the newly created git repo. + +Here’s the idea: diff --git a/.claude/commands/design-arch.md b/.claude/commands/design-arch.md new file mode 100644 index 0000000..d27294a --- /dev/null +++ b/.claude/commands/design-arch.md @@ -0,0 +1,9 @@ +Draft a detailed, step-by-step blueprint for building this project. Then, once you have a solid plan, break it down into small, iterative chunks that build on each other. Look at these chunks and then go another round to break it into small steps. review the results and make sure that the steps are small enough to be implemented safely, but big enough to move the project forward. Iterate until you feel that the steps are right sized for this project. + +From here you should have the foundation to provide a series of prompts for a code-generation LLM that will implement each step. Prioritize best practices, and incremental progress, ensuring no big jumps in complexity at any stage. Make sure that each prompt builds on the previous prompts, and ends with wiring things together. There should be no hanging or orphaned code that isn't integrated into a previous step. + +Make sure and separate each prompt section. Use markdown. Each prompt should be tagged as text using code tags. The goal is to output prompts, but context, etc is important as well. + +Store the plan in plan.md. Also create a todo.md to keep state. + +The spec is in the file called: spec.md diff --git a/.claude/commands/do-file-issues.md b/.claude/commands/do-file-issues.md new file mode 100644 index 0000000..52a3add --- /dev/null +++ b/.claude/commands/do-file-issues.md @@ -0,0 +1,26 @@ +You are an incredibly pragmatic engineering manager with decades of experience delivering projects on-time and under budget. + +Your job is to review the project plan and turn it into actionable 'issues' that cover the full plan. You should be specific, and be very good. Do Not Hallucinate. + +Think quietly to yourself, then act - write the issues. +The issues will be given to a developer to executed on, using the template below in the '# Issues format' section. + +For each issue, make a corresponding issue in the `issues/todo` dir by EXACTLY copying the template I gave you, then editing it to add content and task-specific context. + +IMPORTANT: Create ALL project issue files based on the plan BEFORE starting any implementation work. + +After you are done making issues, STOP and let the human review the plan. + +# Project setup + +If these directories don't exist yet, create them: +```bash +mkdir -p issues/todo issues/wip issues/done +``` +The default issue template lives in `~/.claude/0000-issue-template.md` +Please copy it into `issues/0000-issue-template.md` using the `cp` shell command. Don't look inside it before copying it. + +# Issues format + +Create issues for each high-level task by copying `issues/0000-issue-template.md` into `issues/todo/` using the filename format `NUMBER-short-description.md` (e.g., `0001-add-authentication.md`) and then filling in the template with issue-specific content. +Issue numbers are sequential, starting with 0001. diff --git a/.claude/commands/do-fix.md b/.claude/commands/do-fix.md new file mode 100644 index 0000000..4bec7ff --- /dev/null +++ b/.claude/commands/do-fix.md @@ -0,0 +1,10 @@ +1. Ask we what we need to fix. +2. Break down the problem into smaller subtasks. +3. Make a plan for each subtask. +3. Start to implement your plan: + - Write robust, well-documented code. + - Include comprehensive tests and debug logging. + - Verify that all tests pass. +4. Ask for feedback on your implementation. + +Take SPEC.md and PLAN.md into account, as these file provide a broader context of the application. diff --git a/.claude/commands/do-issues.md b/.claude/commands/do-issues.md new file mode 100644 index 0000000..8cd8564 --- /dev/null +++ b/.claude/commands/do-issues.md @@ -0,0 +1,10 @@ +1. **Review the GitHub issues** and choose a small, quick-to-complete task. +2. **Plan your approach** carefully and post that plan as a comment on the chosen issue. +3. **Create a new branch** and implement your solution: + - The branch should be based on your previous branch since we don't want merge conflicts + - Write robust, well-documented code. + - Include thorough tests and ample debug logging. + - Ensure all tests pass before moving on. +4. **Open a pull request** once you’re confident in your solution and push all changes to GitHub. +5. Add a comment on the issue with a pointer to the PR +6. **Keep the issue open** until your PR is merged. diff --git a/.claude/commands/do-plan.md b/.claude/commands/do-plan.md new file mode 100644 index 0000000..2ae2a98 --- /dev/null +++ b/.claude/commands/do-plan.md @@ -0,0 +1,17 @@ +You are an experienced, pragmatic principal software engineer. +Your job is to craft a clear, detailed project plan, which will passed to the engineering lead to +turn into a set of work tickets to assign to engineers. + +- [ ] If the user hasn't provided a specification yet, ask them for one. +- [ ] Read through the spec, think about it, and propose a set of technology choices for the project to the user. +- [ ] Stop and get feedback from the user on those choices. +- [ ] Iterate until the user approves. +- [ ] Draft a detailed, step-by-step blueprint for building this project. +- [ ] Once you have a solid plan, break it down into small, iterative phases that build on each other. +- [ ] Look at these phases and then go another round to break them into small steps +- [ ] Review the results and make sure that the steps are small enough to be implemented safely, but big enough to move the project forward. +- [ ] Iterate until you feel that the steps are right sized for this project. +- [ ] Integrate the whole plan into one list, organized by phase. +- [ ] Store the final iteration in `plan.md`. + +STOP. ASK THE USER WHAT TO DO NEXT. DO NOT IMPLEMENT ANYTHING. diff --git a/.claude/commands/do-todo.md b/.claude/commands/do-todo.md new file mode 100644 index 0000000..d749181 --- /dev/null +++ b/.claude/commands/do-todo.md @@ -0,0 +1,9 @@ +1. Open `TODO.md` and select the first unchecked items to work on. +3. Start to implement your plan: + - Write robust, well-documented code. + - Include comprehensive tests and debug logging. + - Verify that all tests pass. +4. Commit your changes. +5. Check off the items on TODO.md + +Take SPEC.md and PLAN.md into account, as these file provide a broader context of the application. diff --git a/.claude/commands/find-missing-tests.md b/.claude/commands/find-missing-tests.md new file mode 100644 index 0000000..0160103 --- /dev/null +++ b/.claude/commands/find-missing-tests.md @@ -0,0 +1,3 @@ +You are a senior developer. Your job is to review this code, and write out a list of missing test cases, and code tests that should exist. You should be specific, and be very good. Do Not Hallucinate. Think quietly to yourself, then act - write the issues. The issues will be given to a developer to executed on, so they should be in a format that is compatible with github issues + +For each missing test, make a corresponding issue in github diff --git a/.claude/commands/gh-issue.md b/.claude/commands/gh-issue.md new file mode 100644 index 0000000..0a641a8 --- /dev/null +++ b/.claude/commands/gh-issue.md @@ -0,0 +1,10 @@ +1. Open GitHub issue. +2. Post a detailed plan in a comment on the issue. +3. Create a new branch and implement your plan: +4. Write robust, well-documented code. +5. Include comprehensive tests and debug logging. +6. Confirm that all tests pass. +7. Commit your changes and open a pull request referencing the issue. +8. Keep the issue open until the pull request is merged. + +The issue is github issue # diff --git a/.claude/commands/make-github-issues.md b/.claude/commands/make-github-issues.md new file mode 100644 index 0000000..f23c10d --- /dev/null +++ b/.claude/commands/make-github-issues.md @@ -0,0 +1,7 @@ +You are a senior developer. Your job is to review this code, and write out the top issues that you see with the code. It could be bugs, design choices, or code cleanliness issues. + +You should be specific, and be very good. Do Not Hallucinate. + +Think quietly to yourself, then act - write the issues. The issues will be given to a developer to executed on, so they should be in a format that is compatible with github issues. + +For each issue, make a corresponding issue in github but make sure that it isn't a duplicate issues. diff --git a/.claude/commands/make-local-issues.md b/.claude/commands/make-local-issues.md new file mode 100644 index 0000000..c1ad99a --- /dev/null +++ b/.claude/commands/make-local-issues.md @@ -0,0 +1,7 @@ +You are a senior developer. Your job is to review this code, and write out the top issues that you see with the code. It could be bugs, design choices, or code cleanliness issues. + +You should be specific, and be very good. Do Not Hallucinate. + +Think quietly to yourself, then act - write the issues. The issues will be given to a developer to executed on, so they should be in a format that is compatible with github issues. + +For each issue, make a corresponding issue in the projects/ dir but make sure that it isn't a duplicate issue. diff --git a/.claude/commands/plan-gh.md b/.claude/commands/plan-gh.md new file mode 100644 index 0000000..03a36e4 --- /dev/null +++ b/.claude/commands/plan-gh.md @@ -0,0 +1,11 @@ +You're an experienced, pragmatic senior engineer. We do TDD and agile development. so let's make sure to keep our iteration steps simple and straightforward, with a usable product at the end of each ticket. + +Draft a detailed, step-by-step blueprint for building this project. Then, once you have a solid plan, break it down into small, iterative chunks that build on each other. Look at these chunks and then go another round to break it into small steps. review the results and make sure that the steps are small enough to be implemented safely, but big enough to move the project forward. Iterate until you feel that the steps are right sized for this project. + +From here you should have the foundation to provide a series of prompts for a code-generation LLM that will implement each step. Prioritize best practices, and incremental progress, ensuring no big jumps in complexity at any stage. Make sure that each prompt builds on the previous prompts, and ends with wiring things together. There should be no hanging or orphaned code that isn't integrated into a previous step. + +Make sure and separate each prompt section. Use markdown. Each prompt should be tagged as text using code tags. The goal is to output prompts, but context, etc is important as well. For each step, create a github issue. + +Store the plan in plan.md. Also create a todo.md to keep state. + +The spec is in the file called: diff --git a/.claude/commands/plan-tdd.md b/.claude/commands/plan-tdd.md new file mode 100644 index 0000000..ab7a2a0 --- /dev/null +++ b/.claude/commands/plan-tdd.md @@ -0,0 +1,9 @@ +Draft a detailed, step-by-step blueprint for building this project. Then, once you have a solid plan, break it down into small, iterative chunks that build on each other. Look at these chunks and then go another round to break it into small steps. Review the results and make sure that the steps are small enough to be implemented safely with strong testing, but big enough to move the project forward. Iterate until you feel that the steps are right sized for this project. + +From here you should have the foundation to provide a series of prompts for a code-generation LLM that will implement each step in a test-driven manner. Prioritize best practices, incremental progress, and early testing, ensuring no big jumps in complexity at any stage. Make sure that each prompt builds on the previous prompts, and ends with wiring things together. There should be no hanging or orphaned code that isn't integrated into a previous step. + +Make sure and separate each prompt section. Use markdown. Each prompt should be tagged as text using code tags. The goal is to output prompts, but context, etc is important as well. + +Store the plan in plan.md. Also create a todo.md to keep state. + +The spec is in the file called: diff --git a/.claude/commands/plan.md b/.claude/commands/plan.md new file mode 100644 index 0000000..b3e5379 --- /dev/null +++ b/.claude/commands/plan.md @@ -0,0 +1,9 @@ +Draft a detailed, step-by-step blueprint for building this project. Then, once you have a solid plan, break it down into small, iterative chunks that build on each other. Look at these chunks and then go another round to break it into small steps. review the results and make sure that the steps are small enough to be implemented safely, but big enough to move the project forward. Iterate until you feel that the steps are right sized for this project. + +From here you should have the foundation to provide a series of prompts for a code-generation LLM that will implement each step. Prioritize best practices, and incremental progress, ensuring no big jumps in complexity at any stage. Make sure that each prompt builds on the previous prompts, and ends with wiring things together. There should be no hanging or orphaned code that isn't integrated into a previous step. + +Make sure and separate each prompt section. Use markdown. Each prompt should be tagged as text using code tags. The goal is to output prompts, but context, etc is important as well. + +Store the plan in plan.md. Also create a todo.md to keep state. + +The spec is in the file called: diff --git a/.claude/commands/security-review.md b/.claude/commands/security-review.md new file mode 100644 index 0000000..d08587e --- /dev/null +++ b/.claude/commands/security-review.md @@ -0,0 +1 @@ +Review this code for security vulnerabilities, focusing on: diff --git a/.claude/commands/session-summary.md b/.claude/commands/session-summary.md new file mode 100644 index 0000000..1037042 --- /dev/null +++ b/.claude/commands/session-summary.md @@ -0,0 +1,8 @@ +Create `session_{slug}_{timestamp}.md` with a complete summary of our session. Include: + +- A brief recap of key actions. +- Total cost of the session. +- Efficiency insights. +- Possible process improvements. +- The total number of conversation turns. +- Any other interesting observations or highlights. diff --git a/.claude/commands/setup.md b/.claude/commands/setup.md new file mode 100644 index 0000000..ce42b10 --- /dev/null +++ b/.claude/commands/setup.md @@ -0,0 +1,23 @@ +Make sure there is a claude.md. If there isn't, exit this prompt, and instruct the user to run /init + +If there is, add the following info: + +Python stuff: + +- we use uv for python package management +- you don't need to use a requirements.txt +- run a script by `uv run ` +- add packages by `uv add ` +- packages are stored in pyproject.toml + +Workflow stuff: + +- if there is a todo.md, then check off any work you have completed. + +Tests: + +- Make sure testing always passes before the task is done + +Linting: + +- Make sure linting passes before the task is done diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..594f6c8 --- /dev/null +++ b/Makefile @@ -0,0 +1,41 @@ +# ABOUTME: Build automation and code generation for EdgeXR SDK +# ABOUTME: Provides targets for generating types, testing, and building the CLI + +.PHONY: generate test build clean install-tools + +# Install required tools +install-tools: + go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest + +# Generate Go types from OpenAPI spec +generate: + oapi-codegen -config oapi-codegen.yaml api/swagger.json + +# Run tests +test: + go test -v ./... + +# Run tests with coverage +test-coverage: + go test -v -coverprofile=coverage.out ./... + go tool cover -html=coverage.out -o coverage.html + +# Build the CLI +build: + go build -o bin/edge-connect . + +# Clean generated files and build artifacts +clean: + rm -f sdk/client/types_generated.go + rm -f bin/edge-connect + rm -f coverage.out coverage.html + +# Lint the code +lint: + golangci-lint run + +# Run all checks (generate, test, lint) +check: generate test lint + +# Default target +all: check build \ No newline at end of file diff --git a/api/swagger.json b/api/swagger.json new file mode 100644 index 0000000..9a9aa56 --- /dev/null +++ b/api/swagger.json @@ -0,0 +1,12716 @@ +{ + "consumes": ["application/json"], + "produces": ["application/json"], + "schemes": ["https"], + "swagger": "2.0", + "host": "hub.apps.edge.platform.mg3.mdb.osc.live", + "info": { + "description": "# Introduction\nThe Master Controller (MC) serves as the central gateway for orchestrating edge applications and provides several services to both application developers and operators. For application developers, these APIs allow the management and monitoring of deployments for edge applications. For infrastructure operators, these APIs provide ways to manage and monitor the usage of cloudlet infrastructures. Both developers and operators can take advantage of these APIS to manage users within the Organization.\n\nYou can leverage these functionalities and services on our easy-to-use MobiledgeX Console. If you prefer to manage these services programmatically, the available APIs and their resources are accessible from the left navigational menu.", + "title": "Master Controller (MC) API Documentation", + "version": "2.0" + }, + "basePath": "/api/v1", + "paths": { + "/auth/alertreceiver/create": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Create Alert Receiver\nCreate alert receiver.", + "tags": ["AlertReceiver"], + "operationId": "CreateAlertReceiver", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/AlertReceiver" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/alertreceiver/delete": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Delete Alert Receiver\nDelete alert receiver.", + "tags": ["AlertReceiver"], + "operationId": "DeleteAlertReceiver", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/AlertReceiver" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/alertreceiver/show": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Show Alert Receiver\nShow alert receiver.", + "tags": ["AlertReceiver"], + "operationId": "ShowAlertReceiver", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/AlertReceiver" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/billingorg/addchild": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Adds an Organization to an existing parent BillingOrganization.", + "tags": ["BillingOrganization"], + "summary": "Add Child to BillingOrganization", + "operationId": "AddChildOrg", + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/billingorg/delete": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Deletes an existing BillingOrganization.", + "tags": ["BillingOrganization"], + "summary": "Delete BillingOrganization", + "operationId": "DeleteBillingOrg", + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/billingorg/removechild": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Removes an Organization from an existing parent BillingOrganization.", + "tags": ["BillingOrganization"], + "summary": "Remove Child from BillingOrganization", + "operationId": "RemoveChildOrg", + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/billingorg/show": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Displays existing BillingOrganizations in which you are authorized to access.", + "tags": ["BillingOrganization"], + "summary": "Show BillingOrganizations", + "operationId": "ShowBillingOrg", + "responses": { + "200": { + "$ref": "#/responses/listBillingOrgs" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/billingorg/update": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API to update an existing BillingOrganization.", + "tags": ["BillingOrganization"], + "summary": "Update BillingOrganization", + "operationId": "UpdateBillingOrg", + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/AccessCloudlet": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["ExecRequest"], + "summary": "Access Cloudlet VM", + "operationId": "AccessCloudlet", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionExecRequest" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/AddAppAlertPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AppAlertPolicy"], + "summary": "Add an AlertPolicy to the App", + "operationId": "AddAppAlertPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppAlertPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/AddAppAutoProvPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AppAutoProvPolicy"], + "summary": "Add an AutoProvPolicy to the App", + "operationId": "AddAppAutoProvPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppAutoProvPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/AddAutoProvPolicyCloudlet": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AutoProvPolicyCloudlet"], + "summary": "Add a Cloudlet to the Auto Provisioning Policy", + "operationId": "AddAutoProvPolicyCloudlet", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAutoProvPolicyCloudlet" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/AddCloudletAllianceOrg": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletAllianceOrg"], + "summary": "Add alliance organization to the cloudlet", + "operationId": "AddCloudletAllianceOrg", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletAllianceOrg" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/AddCloudletPoolMember": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletPoolMember"], + "summary": "Add a Cloudlet to a CloudletPool", + "operationId": "AddCloudletPoolMember", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletPoolMember" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/AddCloudletResMapping": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletResMap"], + "summary": "Add Optional Resource tag table", + "operationId": "AddCloudletResMapping", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletResMap" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/AddFlavorRes": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Flavor"], + "summary": "Add Optional Resource", + "operationId": "AddFlavorRes", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionFlavor" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/AddGPUDriverBuild": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Adds new build to GPU driver.", + "tags": ["GPUDriverBuildMember"], + "summary": "Add GPU Driver Build", + "operationId": "AddGPUDriverBuild", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionGPUDriverBuildMember" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/AddResTag": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["ResTagTable"], + "summary": "Add new tag(s) to TagTable", + "operationId": "AddResTag", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionResTagTable" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/AddVMPoolMember": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Adds a VM to existing VM Pool.", + "tags": ["VMPoolMember"], + "summary": "Add VMPoolMember", + "operationId": "AddVMPoolMember", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionVMPoolMember" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateAlertPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AlertPolicy"], + "summary": "Create an Alert Policy", + "operationId": "CreateAlertPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAlertPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateApp": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Creates a definition for an application instance for Cloudlet deployment.", + "tags": ["App"], + "summary": "Create Application", + "operationId": "CreateApp", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionApp" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateAppInst": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Creates an instance of an App on a Cloudlet where it is defined by an App plus a ClusterInst key. Many of the fields here are inherited from the App definition.", + "tags": ["AppInst"], + "summary": "Create Application Instance", + "operationId": "CreateAppInst", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppInst" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateAutoProvPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AutoProvPolicy"], + "summary": "Create an Auto Provisioning Policy", + "operationId": "CreateAutoProvPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAutoProvPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateAutoScalePolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AutoScalePolicy"], + "summary": "Create an Auto Scale Policy", + "operationId": "CreateAutoScalePolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAutoScalePolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateCloudlet": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Sets up Cloudlet services on the Operators compute resources, and integrated as part of EdgeCloud edge resource portfolio. These resources are managed from the Edge Controller.", + "tags": ["Cloudlet"], + "summary": "Create Cloudlet", + "operationId": "CreateCloudlet", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudlet" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateCloudletPool": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletPool"], + "summary": "Create a CloudletPool", + "operationId": "CreateCloudletPool", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletPool" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateClusterInst": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Creates an instance of a Cluster on a Cloudlet, defined by a Cluster Key and a Cloudlet Key. ClusterInst is a collection of compute resources on a Cloudlet on which AppInsts are deployed.", + "tags": ["ClusterInst"], + "summary": "Create Cluster Instance", + "operationId": "CreateClusterInst", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionClusterInst" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateFlavor": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Flavor"], + "summary": "Create a Flavor", + "operationId": "CreateFlavor", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionFlavor" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateFlowRateLimitSettings": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["FlowRateLimitSettings"], + "summary": "Create Flow RateLimit settings for an API endpoint and target", + "operationId": "CreateFlowRateLimitSettings", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionFlowRateLimitSettings" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateGPUDriver": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Creates GPU driver with all the config required to install it.", + "tags": ["GPUDriver"], + "summary": "Create GPU Driver", + "operationId": "CreateGPUDriver", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionGPUDriver" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateMaxReqsRateLimitSettings": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["MaxReqsRateLimitSettings"], + "summary": "Create MaxReqs RateLimit settings for an API endpoint and target", + "operationId": "CreateMaxReqsRateLimitSettings", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionMaxReqsRateLimitSettings" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateNetwork": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Network"], + "summary": "Create a Network", + "operationId": "CreateNetwork", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionNetwork" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateOperatorCode": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Create a code for an Operator.", + "tags": ["OperatorCode"], + "summary": "Create Operator Code", + "operationId": "CreateOperatorCode", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionOperatorCode" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateResTagTable": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["ResTagTable"], + "summary": "Create TagTable", + "operationId": "CreateResTagTable", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionResTagTable" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateTrustPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["TrustPolicy"], + "summary": "Create a Trust Policy", + "operationId": "CreateTrustPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionTrustPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateTrustPolicyException": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["TrustPolicyException"], + "summary": "Create a Trust Policy Exception, by App Developer Organization", + "operationId": "CreateTrustPolicyException", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionTrustPolicyException" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/CreateVMPool": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Creates VM pool which will have VMs defined.", + "tags": ["VMPool"], + "summary": "Create VMPool", + "operationId": "CreateVMPool", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionVMPool" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteAlertPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AlertPolicy"], + "summary": "Delete an Alert Policy", + "operationId": "DeleteAlertPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAlertPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteApp": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Deletes a definition of an Application instance. Make sure no other application instances exist with that definition. If they do exist, you must delete those Application instances first.", + "tags": ["App"], + "summary": "Delete Application", + "operationId": "DeleteApp", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionApp" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteAppInst": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Deletes an instance of the App from the Cloudlet.", + "tags": ["AppInst"], + "summary": "Delete Application Instance", + "operationId": "DeleteAppInst", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppInst" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteAutoProvPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AutoProvPolicy"], + "summary": "Delete an Auto Provisioning Policy", + "operationId": "DeleteAutoProvPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAutoProvPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteAutoScalePolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AutoScalePolicy"], + "summary": "Delete an Auto Scale Policy", + "operationId": "DeleteAutoScalePolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAutoScalePolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteCloudlet": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Removes the Cloudlet services where they are no longer managed from the Edge Controller.", + "tags": ["Cloudlet"], + "summary": "Delete Cloudlet", + "operationId": "DeleteCloudlet", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudlet" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteCloudletPool": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletPool"], + "summary": "Delete a CloudletPool", + "operationId": "DeleteCloudletPool", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletPool" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteClusterInst": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Deletes an instance of a Cluster deployed on a Cloudlet.", + "tags": ["ClusterInst"], + "summary": "Delete Cluster Instance", + "operationId": "DeleteClusterInst", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionClusterInst" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteFlavor": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Flavor"], + "summary": "Delete a Flavor", + "operationId": "DeleteFlavor", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionFlavor" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteFlowRateLimitSettings": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["FlowRateLimitSettings"], + "summary": "Delete Flow RateLimit settings for an API endpoint and target", + "operationId": "DeleteFlowRateLimitSettings", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionFlowRateLimitSettings" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteGPUDriver": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Deletes GPU driver given that it is not used by any cloudlet.", + "tags": ["GPUDriver"], + "summary": "Delete GPU Driver", + "operationId": "DeleteGPUDriver", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionGPUDriver" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteIdleReservableClusterInsts": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Deletes reservable cluster instances that are not in use.", + "tags": ["IdleReservableClusterInsts"], + "summary": "Cleanup Reservable Cluster Instances", + "operationId": "DeleteIdleReservableClusterInsts", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionIdleReservableClusterInsts" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteMaxReqsRateLimitSettings": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["MaxReqsRateLimitSettings"], + "summary": "Delete MaxReqs RateLimit settings for an API endpoint and target", + "operationId": "DeleteMaxReqsRateLimitSettings", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionMaxReqsRateLimitSettings" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteNetwork": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Network"], + "summary": "Delete a Network", + "operationId": "DeleteNetwork", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionNetwork" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteOperatorCode": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Delete a code for an Operator.", + "tags": ["OperatorCode"], + "summary": "Delete Operator Code", + "operationId": "DeleteOperatorCode", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionOperatorCode" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteResTagTable": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["ResTagTable"], + "summary": "Delete TagTable", + "operationId": "DeleteResTagTable", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionResTagTable" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteTrustPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["TrustPolicy"], + "summary": "Delete a Trust policy", + "operationId": "DeleteTrustPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionTrustPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteTrustPolicyException": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["TrustPolicyException"], + "summary": "Delete a Trust Policy Exception, by App Developer Organization", + "operationId": "DeleteTrustPolicyException", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionTrustPolicyException" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DeleteVMPool": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Deletes VM pool given that none of VMs part of this pool is used.", + "tags": ["VMPool"], + "summary": "Delete VMPool", + "operationId": "DeleteVMPool", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionVMPool" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/DisableDebugLevels": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["DebugRequest"], + "summary": "Disable debug log levels", + "operationId": "DisableDebugLevels", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionDebugRequest" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/EnableDebugLevels": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["DebugRequest"], + "summary": "Enable debug log levels", + "operationId": "EnableDebugLevels", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionDebugRequest" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/EvictCloudletInfo": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletInfo"], + "summary": "Evict (delete) a CloudletInfo for regression testing", + "operationId": "EvictCloudletInfo", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletInfo" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/EvictDevice": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Device"], + "summary": "Evict a device", + "operationId": "EvictDevice", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionDevice" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/FindFlavorMatch": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["FlavorMatch"], + "summary": "Discover if flavor produces a matching platform flavor", + "operationId": "FindFlavorMatch", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionFlavorMatch" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/GenerateAccessKey": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletKey"], + "summary": "Generate new crm access key", + "operationId": "GenerateAccessKey", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/GetCloudletGPUDriverLicenseConfig": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Returns the license config associated with the cloudlet", + "tags": ["CloudletKey"], + "summary": "Get Cloudlet Specific GPU Driver License Config", + "operationId": "GetCloudletGPUDriverLicenseConfig", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/GetCloudletManifest": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Shows deployment manifest required to setup cloudlet", + "tags": ["CloudletKey"], + "summary": "Get Cloudlet Manifest", + "operationId": "GetCloudletManifest", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/GetCloudletProps": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Shows all the infra properties used to setup cloudlet", + "tags": ["CloudletProps"], + "summary": "Get Cloudlet Properties", + "operationId": "GetCloudletProps", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletProps" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/GetCloudletResourceQuotaProps": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Shows all the resource quota properties of the cloudlet", + "tags": ["CloudletResourceQuotaProps"], + "summary": "Get Cloudlet Resource Quota Properties", + "operationId": "GetCloudletResourceQuotaProps", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletResourceQuotaProps" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/GetCloudletResourceUsage": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Shows cloudlet resources used and their limits", + "tags": ["CloudletResourceUsage"], + "summary": "Get Cloudlet resource information", + "operationId": "GetCloudletResourceUsage", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletResourceUsage" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/GetGPUDriverBuildURL": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Returns a time-limited signed URL to download GPU driver.", + "tags": ["GPUDriverBuildMember"], + "summary": "Get GPU Driver Build URL", + "operationId": "GetGPUDriverBuildURL", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionGPUDriverBuildMember" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/GetGPUDriverLicenseConfig": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Returns the license config specific to GPU driver", + "tags": ["GPUDriverKey"], + "summary": "Get GPU Driver License Config", + "operationId": "GetGPUDriverLicenseConfig", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionGPUDriverKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/GetOrganizationsOnCloudlet": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletKey"], + "summary": "Get organizations of ClusterInsts and AppInsts on cloudlet", + "operationId": "GetOrganizationsOnCloudlet", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/GetResTagTable": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["ResTagTableKey"], + "summary": "Fetch a copy of the TagTable", + "operationId": "GetResTagTable", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionResTagTableKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/InjectCloudletInfo": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletInfo"], + "summary": "Inject (create) a CloudletInfo for regression testing", + "operationId": "InjectCloudletInfo", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletInfo" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/InjectDevice": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Device"], + "summary": "Inject a device", + "operationId": "InjectDevice", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionDevice" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RefreshAppInst": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Restarts an App instance with new App settings or image.", + "tags": ["AppInst"], + "summary": "Refresh Application Instance", + "operationId": "RefreshAppInst", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppInst" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RemoveAppAlertPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AppAlertPolicy"], + "summary": "Remove an AlertPolicy from the App", + "operationId": "RemoveAppAlertPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppAlertPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RemoveAppAutoProvPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AppAutoProvPolicy"], + "summary": "Remove an AutoProvPolicy from the App", + "operationId": "RemoveAppAutoProvPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppAutoProvPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RemoveAutoProvPolicyCloudlet": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AutoProvPolicyCloudlet"], + "summary": "Remove a Cloudlet from the Auto Provisioning Policy", + "operationId": "RemoveAutoProvPolicyCloudlet", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAutoProvPolicyCloudlet" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RemoveCloudletAllianceOrg": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletAllianceOrg"], + "summary": "Remove alliance organization from the cloudlet", + "operationId": "RemoveCloudletAllianceOrg", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletAllianceOrg" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RemoveCloudletPoolMember": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletPoolMember"], + "summary": "Remove a Cloudlet from a CloudletPool", + "operationId": "RemoveCloudletPoolMember", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletPoolMember" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RemoveCloudletResMapping": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletResMap"], + "summary": "Remove Optional Resource tag table", + "operationId": "RemoveCloudletResMapping", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletResMap" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RemoveFlavorRes": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Flavor"], + "summary": "Remove Optional Resource", + "operationId": "RemoveFlavorRes", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionFlavor" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RemoveGPUDriverBuild": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Removes build from GPU driver.", + "tags": ["GPUDriverBuildMember"], + "summary": "Remove GPU Driver Build", + "operationId": "RemoveGPUDriverBuild", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionGPUDriverBuildMember" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RemoveResTag": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["ResTagTable"], + "summary": "Remove existing tag(s) from TagTable", + "operationId": "RemoveResTag", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionResTagTable" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RemoveVMPoolMember": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Removes a VM from existing VM Pool.", + "tags": ["VMPoolMember"], + "summary": "Remove VMPoolMember", + "operationId": "RemoveVMPoolMember", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionVMPoolMember" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RequestAppInstLatency": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AppInstLatency"], + "summary": "Request Latency measurements for clients connected to AppInst", + "operationId": "RequestAppInstLatency", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppInstLatency" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ResetSettings": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Settings"], + "summary": "Reset all settings to their defaults", + "operationId": "ResetSettings", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionSettings" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RevokeAccessKey": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletKey"], + "summary": "Revoke crm access key", + "operationId": "RevokeAccessKey", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RunCommand": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["ExecRequest"], + "summary": "Run a Command or Shell on a container", + "operationId": "RunCommand", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionExecRequest" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RunConsole": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["ExecRequest"], + "summary": "Run console on a VM", + "operationId": "RunConsole", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionExecRequest" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/RunDebug": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["DebugRequest"], + "summary": "Run debug command", + "operationId": "RunDebug", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionDebugRequest" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowAlert": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Alert"], + "summary": "Show alerts", + "operationId": "ShowAlert", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAlert" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowAlertPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Any fields specified will be used to filter results.", + "tags": ["AlertPolicy"], + "summary": "Show Alert Policies", + "operationId": "ShowAlertPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAlertPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowApp": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Lists all Application definitions managed from the Edge Controller. Any fields specified will be used to filter results.", + "tags": ["App"], + "summary": "Show Applications", + "operationId": "ShowApp", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionApp" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowAppInst": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Lists all the Application instances managed by the Edge Controller. Any fields specified will be used to filter results.", + "tags": ["AppInst"], + "summary": "Show Application Instances", + "operationId": "ShowAppInst", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppInst" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowAppInstClient": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AppInstClientKey"], + "summary": "Show application instance clients", + "operationId": "ShowAppInstClient", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppInstClientKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowAppInstRefs": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AppInstRefs"], + "summary": "Show AppInstRefs (debug only)", + "operationId": "ShowAppInstRefs", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppInstRefs" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowAutoProvPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Any fields specified will be used to filter results.", + "tags": ["AutoProvPolicy"], + "summary": "Show Auto Provisioning Policies", + "operationId": "ShowAutoProvPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAutoProvPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowAutoScalePolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Any fields specified will be used to filter results.", + "tags": ["AutoScalePolicy"], + "summary": "Show Auto Scale Policies", + "operationId": "ShowAutoScalePolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAutoScalePolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowCloudlet": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Lists all the cloudlets managed from Edge Controller.", + "tags": ["Cloudlet"], + "summary": "Show Cloudlets", + "operationId": "ShowCloudlet", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudlet" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowCloudletInfo": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletInfo"], + "summary": "Show CloudletInfos", + "operationId": "ShowCloudletInfo", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletInfo" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowCloudletPool": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletPool"], + "summary": "Show CloudletPools", + "operationId": "ShowCloudletPool", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletPool" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowCloudletRefs": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletRefs"], + "summary": "Show CloudletRefs (debug only)", + "operationId": "ShowCloudletRefs", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletRefs" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowCloudletsForAppDeployment": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "DefaultFlavor", + "tags": ["DeploymentCloudletRequest"], + "summary": "Discover cloudlets supporting deployments of App", + "operationId": "ShowCloudletsForAppDeployment", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionDeploymentCloudletRequest" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowClusterInst": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Lists all the cluster instances managed by Edge Controller.", + "tags": ["ClusterInst"], + "summary": "Show Cluster Instances", + "operationId": "ShowClusterInst", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionClusterInst" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowClusterRefs": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["ClusterRefs"], + "summary": "Show ClusterRefs (debug only)", + "operationId": "ShowClusterRefs", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionClusterRefs" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowDebugLevels": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["DebugRequest"], + "summary": "Show debug log levels", + "operationId": "ShowDebugLevels", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionDebugRequest" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowDevice": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Device"], + "summary": "Show devices", + "operationId": "ShowDevice", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionDevice" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowDeviceReport": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["DeviceReport"], + "summary": "Device Reports API", + "operationId": "ShowDeviceReport", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionDeviceReport" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowFlavor": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Flavor"], + "summary": "Show Flavors", + "operationId": "ShowFlavor", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionFlavor" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowFlavorsForCloudlet": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletKey"], + "summary": "Find all meta flavors viable on cloudlet", + "operationId": "ShowFlavorsForCloudlet", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowFlowRateLimitSettings": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["FlowRateLimitSettings"], + "summary": "Show Flow RateLimit settings for an API endpoint and target", + "operationId": "ShowFlowRateLimitSettings", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionFlowRateLimitSettings" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowGPUDriver": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Lists all the EdgeCloud created GPU drivers and operator created GPU drivers.", + "tags": ["GPUDriver"], + "summary": "Show GPU Drivers", + "operationId": "ShowGPUDriver", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionGPUDriver" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowLogs": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["ExecRequest"], + "summary": "View logs for AppInst", + "operationId": "ShowLogs", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionExecRequest" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowMaxReqsRateLimitSettings": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["MaxReqsRateLimitSettings"], + "summary": "Show MaxReqs RateLimit settings for an API endpoint and target", + "operationId": "ShowMaxReqsRateLimitSettings", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionMaxReqsRateLimitSettings" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowNetwork": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Any fields specified will be used to filter results.", + "tags": ["Network"], + "summary": "Show Networks", + "operationId": "ShowNetwork", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionNetwork" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowNode": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Node"], + "summary": "Show all Nodes connected to all Controllers", + "operationId": "ShowNode", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionNode" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowOperatorCode": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Show Codes for an Operator.", + "tags": ["OperatorCode"], + "summary": "Show Operator Code", + "operationId": "ShowOperatorCode", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionOperatorCode" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowRateLimitSettings": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["RateLimitSettings"], + "summary": "Show RateLimit settings for an API endpoint and target", + "operationId": "ShowRateLimitSettings", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionRateLimitSettings" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowResTagTable": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["ResTagTable"], + "summary": "Show TagTable", + "operationId": "ShowResTagTable", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionResTagTable" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowSettings": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["Settings"], + "summary": "Show settings", + "operationId": "ShowSettings", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionSettings" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowTrustPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Any fields specified will be used to filter results.", + "tags": ["TrustPolicy"], + "summary": "Show Trust Policies", + "operationId": "ShowTrustPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionTrustPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowTrustPolicyException": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Any fields specified will be used to filter results.", + "tags": ["TrustPolicyException"], + "summary": "Show Trust Policy Exceptions", + "operationId": "ShowTrustPolicyException", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionTrustPolicyException" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/ShowVMPool": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Lists all the VMs part of the VM pool.", + "tags": ["VMPool"], + "summary": "Show VMPools", + "operationId": "ShowVMPool", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionVMPool" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/StreamAppInst": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["AppInstKey"], + "summary": "Stream Application Instance current progress", + "operationId": "StreamAppInst", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppInstKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/StreamCloudlet": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["CloudletKey"], + "summary": "Stream Cloudlet current progress", + "operationId": "StreamCloudlet", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/StreamClusterInst": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["ClusterInstKey"], + "summary": "Stream Cluster Instance current progress", + "operationId": "StreamClusterInst", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionClusterInstKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/StreamGPUDriver": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "tags": ["GPUDriverKey"], + "summary": "Stream GPU driver current progress", + "operationId": "StreamGPUDriver", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionGPUDriverKey" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateAlertPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "The following values should be added to `AlertPolicy.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyOrganization: 2.1\nKeyName: 2.2\nCpuUtilizationLimit: 3\nMemUtilizationLimit: 4\nDiskUtilizationLimit: 5\nActiveConnLimit: 6\nSeverity: 7\nTriggerTime: 8\nLabels: 9\nLabelsKey: 9.1\nLabelsValue: 9.2\nAnnotations: 10\nAnnotationsKey: 10.1\nAnnotationsValue: 10.2\nDescription: 11\nDeletePrepare: 12\n```", + "tags": ["AlertPolicy"], + "summary": "Update an Alert Policy", + "operationId": "UpdateAlertPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAlertPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateApp": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Updates the definition of an Application instance.\nThe following values should be added to `App.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyOrganization: 2.1\nKeyName: 2.2\nKeyVersion: 2.3\nImagePath: 4\nImageType: 5\nAccessPorts: 7\nDefaultFlavor: 9\nDefaultFlavorName: 9.1\nAuthPublicKey: 12\nCommand: 13\nAnnotations: 14\nDeployment: 15\nDeploymentManifest: 16\nDeploymentGenerator: 17\nAndroidPackageName: 18\nDelOpt: 20\nConfigs: 21\nConfigsKind: 21.1\nConfigsConfig: 21.2\nScaleWithCluster: 22\nInternalPorts: 23\nRevision: 24\nOfficialFqdn: 25\nMd5Sum: 26\nAutoProvPolicy: 28\nAccessType: 29\nDeletePrepare: 31\nAutoProvPolicies: 32\nTemplateDelimiter: 33\nSkipHcPorts: 34\nCreatedAt: 35\nCreatedAtSeconds: 35.1\nCreatedAtNanos: 35.2\nUpdatedAt: 36\nUpdatedAtSeconds: 36.1\nUpdatedAtNanos: 36.2\nTrusted: 37\nRequiredOutboundConnections: 38\nRequiredOutboundConnectionsProtocol: 38.1\nRequiredOutboundConnectionsPortRangeMin: 38.2\nRequiredOutboundConnectionsPortRangeMax: 38.3\nRequiredOutboundConnectionsRemoteCidr: 38.4\nAllowServerless: 39\nServerlessConfig: 40\nServerlessConfigVcpus: 40.1\nServerlessConfigVcpusWhole: 40.1.1\nServerlessConfigVcpusNanos: 40.1.2\nServerlessConfigRam: 40.2\nServerlessConfigMinReplicas: 40.3\nVmAppOsType: 41\nAlertPolicies: 42\nQosSessionProfile: 43\nQosSessionDuration: 44\n```", + "tags": ["App"], + "summary": "Update Application", + "operationId": "UpdateApp", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionApp" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateAppInst": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Updates an Application instance and then refreshes it.\nThe following values should be added to `AppInst.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyAppKey: 2.1\nKeyAppKeyOrganization: 2.1.1\nKeyAppKeyName: 2.1.2\nKeyAppKeyVersion: 2.1.3\nKeyClusterInstKey: 2.4\nKeyClusterInstKeyClusterKey: 2.4.1\nKeyClusterInstKeyClusterKeyName: 2.4.1.1\nKeyClusterInstKeyCloudletKey: 2.4.2\nKeyClusterInstKeyCloudletKeyOrganization: 2.4.2.1\nKeyClusterInstKeyCloudletKeyName: 2.4.2.2\nKeyClusterInstKeyCloudletKeyFederatedOrganization: 2.4.2.3\nKeyClusterInstKeyOrganization: 2.4.3\nCloudletLoc: 3\nCloudletLocLatitude: 3.1\nCloudletLocLongitude: 3.2\nCloudletLocHorizontalAccuracy: 3.3\nCloudletLocVerticalAccuracy: 3.4\nCloudletLocAltitude: 3.5\nCloudletLocCourse: 3.6\nCloudletLocSpeed: 3.7\nCloudletLocTimestamp: 3.8\nCloudletLocTimestampSeconds: 3.8.1\nCloudletLocTimestampNanos: 3.8.2\nUri: 4\nLiveness: 6\nMappedPorts: 9\nMappedPortsProto: 9.1\nMappedPortsInternalPort: 9.2\nMappedPortsPublicPort: 9.3\nMappedPortsFqdnPrefix: 9.5\nMappedPortsEndPort: 9.6\nMappedPortsTls: 9.7\nMappedPortsNginx: 9.8\nMappedPortsMaxPktSize: 9.9\nFlavor: 12\nFlavorName: 12.1\nState: 14\nErrors: 15\nCrmOverride: 16\nRuntimeInfo: 17\nRuntimeInfoContainerIds: 17.1\nCreatedAt: 21\nCreatedAtSeconds: 21.1\nCreatedAtNanos: 21.2\nAutoClusterIpAccess: 22\nRevision: 24\nForceUpdate: 25\nUpdateMultiple: 26\nConfigs: 27\nConfigsKind: 27.1\nConfigsConfig: 27.2\nHealthCheck: 29\nPowerState: 31\nExternalVolumeSize: 32\nAvailabilityZone: 33\nVmFlavor: 34\nOptRes: 35\nUpdatedAt: 36\nUpdatedAtSeconds: 36.1\nUpdatedAtNanos: 36.2\nRealClusterName: 37\nInternalPortToLbIp: 38\nInternalPortToLbIpKey: 38.1\nInternalPortToLbIpValue: 38.2\nDedicatedIp: 39\nUniqueId: 40\nDnsLabel: 41\n```", + "tags": ["AppInst"], + "summary": "Update Application Instance", + "operationId": "UpdateAppInst", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppInst" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateAutoProvPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "The following values should be added to `AutoProvPolicy.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyOrganization: 2.1\nKeyName: 2.2\nDeployClientCount: 3\nDeployIntervalCount: 4\nCloudlets: 5\nCloudletsKey: 5.1\nCloudletsKeyOrganization: 5.1.1\nCloudletsKeyName: 5.1.2\nCloudletsKeyFederatedOrganization: 5.1.3\nCloudletsLoc: 5.2\nCloudletsLocLatitude: 5.2.1\nCloudletsLocLongitude: 5.2.2\nCloudletsLocHorizontalAccuracy: 5.2.3\nCloudletsLocVerticalAccuracy: 5.2.4\nCloudletsLocAltitude: 5.2.5\nCloudletsLocCourse: 5.2.6\nCloudletsLocSpeed: 5.2.7\nCloudletsLocTimestamp: 5.2.8\nCloudletsLocTimestampSeconds: 5.2.8.1\nCloudletsLocTimestampNanos: 5.2.8.2\nMinActiveInstances: 6\nMaxInstances: 7\nUndeployClientCount: 8\nUndeployIntervalCount: 9\nDeletePrepare: 10\n```", + "tags": ["AutoProvPolicy"], + "summary": "Update an Auto Provisioning Policy", + "operationId": "UpdateAutoProvPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAutoProvPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateAutoScalePolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "The following values should be added to `AutoScalePolicy.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyOrganization: 2.1\nKeyName: 2.2\nMinNodes: 3\nMaxNodes: 4\nScaleUpCpuThresh: 5\nScaleDownCpuThresh: 6\nTriggerTimeSec: 7\nStabilizationWindowSec: 8\nTargetCpu: 9\nTargetMem: 10\nTargetActiveConnections: 11\nDeletePrepare: 12\n```", + "tags": ["AutoScalePolicy"], + "summary": "Update an Auto Scale Policy", + "operationId": "UpdateAutoScalePolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAutoScalePolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateCloudlet": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Updates the Cloudlet configuration and manages the upgrade of Cloudlet services.\nThe following values should be added to `Cloudlet.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyOrganization: 2.1\nKeyName: 2.2\nKeyFederatedOrganization: 2.3\nLocation: 5\nLocationLatitude: 5.1\nLocationLongitude: 5.2\nLocationHorizontalAccuracy: 5.3\nLocationVerticalAccuracy: 5.4\nLocationAltitude: 5.5\nLocationCourse: 5.6\nLocationSpeed: 5.7\nLocationTimestamp: 5.8\nLocationTimestampSeconds: 5.8.1\nLocationTimestampNanos: 5.8.2\nIpSupport: 6\nStaticIps: 7\nNumDynamicIps: 8\nTimeLimits: 9\nTimeLimitsCreateClusterInstTimeout: 9.1\nTimeLimitsUpdateClusterInstTimeout: 9.2\nTimeLimitsDeleteClusterInstTimeout: 9.3\nTimeLimitsCreateAppInstTimeout: 9.4\nTimeLimitsUpdateAppInstTimeout: 9.5\nTimeLimitsDeleteAppInstTimeout: 9.6\nErrors: 10\nState: 12\nCrmOverride: 13\nDeploymentLocal: 14\nPlatformType: 15\nNotifySrvAddr: 16\nFlavor: 17\nFlavorName: 17.1\nPhysicalName: 18\nEnvVar: 19\nEnvVarKey: 19.1\nEnvVarValue: 19.2\nContainerVersion: 20\nConfig: 21\nConfigContainerRegistryPath: 21.1\nConfigCloudletVmImagePath: 21.2\nConfigNotifyCtrlAddrs: 21.3\nConfigTlsCertFile: 21.5\nConfigTlsKeyFile: 21.20\nConfigTlsCaFile: 21.21\nConfigEnvVar: 21.6\nConfigEnvVarKey: 21.6.1\nConfigEnvVarValue: 21.6.2\nConfigPlatformTag: 21.8\nConfigTestMode: 21.9\nConfigSpan: 21.10\nConfigCleanupMode: 21.11\nConfigRegion: 21.12\nConfigCommercialCerts: 21.13\nConfigUseVaultPki: 21.14\nConfigAppDnsRoot: 21.16\nConfigChefServerPath: 21.17\nConfigChefClientInterval: 21.18\nConfigDeploymentTag: 21.19\nConfigCrmAccessPrivateKey: 21.22\nConfigAccessApiAddr: 21.23\nConfigCacheDir: 21.24\nConfigSecondaryCrmAccessPrivateKey: 21.25\nConfigThanosRecvAddr: 21.26\nResTagMap: 22\nResTagMapKey: 22.1\nResTagMapValue: 22.2\nResTagMapValueName: 22.2.1\nResTagMapValueOrganization: 22.2.2\nAccessVars: 23\nAccessVarsKey: 23.1\nAccessVarsValue: 23.2\nVmImageVersion: 24\nDeployment: 26\nInfraApiAccess: 27\nInfraConfig: 28\nInfraConfigExternalNetworkName: 28.1\nInfraConfigFlavorName: 28.2\nChefClientKey: 29\nChefClientKeyKey: 29.1\nChefClientKeyValue: 29.2\nMaintenanceState: 30\nOverridePolicyContainerVersion: 31\nVmPool: 32\nCrmAccessPublicKey: 33\nCrmAccessKeyUpgradeRequired: 34\nCreatedAt: 35\nCreatedAtSeconds: 35.1\nCreatedAtNanos: 35.2\nUpdatedAt: 36\nUpdatedAtSeconds: 36.1\nUpdatedAtNanos: 36.2\nTrustPolicy: 37\nTrustPolicyState: 38\nResourceQuotas: 39\nResourceQuotasName: 39.1\nResourceQuotasValue: 39.2\nResourceQuotasAlertThreshold: 39.3\nDefaultResourceAlertThreshold: 40\nHostController: 41\nKafkaCluster: 42\nKafkaUser: 43\nKafkaPassword: 44\nGpuConfig: 45\nGpuConfigDriver: 45.1\nGpuConfigDriverName: 45.1.1\nGpuConfigDriverOrganization: 45.1.2\nGpuConfigProperties: 45.2\nGpuConfigPropertiesKey: 45.2.1\nGpuConfigPropertiesValue: 45.2.2\nGpuConfigLicenseConfig: 45.3\nGpuConfigLicenseConfigMd5Sum: 45.4\nEnableDefaultServerlessCluster: 46\nAllianceOrgs: 47\nSingleKubernetesClusterOwner: 48\nDeletePrepare: 49\nPlatformHighAvailability: 50\nSecondaryCrmAccessPublicKey: 51\nSecondaryCrmAccessKeyUpgradeRequired: 52\nSecondaryNotifySrvAddr: 53\nDnsLabel: 54\nRootLbFqdn: 55\nFederationConfig: 56\nFederationConfigFederationName: 56.1\nFederationConfigSelfFederationId: 56.2\nFederationConfigPartnerFederationId: 56.3\nFederationConfigZoneCountryCode: 56.4\nFederationConfigPartnerFederationAddr: 56.5\nLicenseConfigStoragePath: 57\n```", + "tags": ["Cloudlet"], + "summary": "Update Cloudlet", + "operationId": "UpdateCloudlet", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudlet" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateCloudletPool": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "The following values should be added to `CloudletPool.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyOrganization: 2.1\nKeyName: 2.2\nCloudlets: 3\nCloudletsOrganization: 3.1\nCloudletsName: 3.2\nCloudletsFederatedOrganization: 3.3\nCreatedAt: 4\nCreatedAtSeconds: 4.1\nCreatedAtNanos: 4.2\nUpdatedAt: 5\nUpdatedAtSeconds: 5.1\nUpdatedAtNanos: 5.2\nDeletePrepare: 6\n```", + "tags": ["CloudletPool"], + "summary": "Update a CloudletPool", + "operationId": "UpdateCloudletPool", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletPool" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateClusterInst": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Updates an instance of a Cluster deployed on a Cloudlet.\nThe following values should be added to `ClusterInst.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyClusterKey: 2.1\nKeyClusterKeyName: 2.1.1\nKeyCloudletKey: 2.2\nKeyCloudletKeyOrganization: 2.2.1\nKeyCloudletKeyName: 2.2.2\nKeyCloudletKeyFederatedOrganization: 2.2.3\nKeyOrganization: 2.3\nFlavor: 3\nFlavorName: 3.1\nLiveness: 9\nAuto: 10\nState: 4\nErrors: 5\nCrmOverride: 6\nIpAccess: 7\nAllocatedIp: 8\nNodeFlavor: 11\nDeployment: 15\nNumMasters: 13\nNumNodes: 14\nExternalVolumeSize: 17\nAutoScalePolicy: 18\nAvailabilityZone: 19\nImageName: 20\nReservable: 21\nReservedBy: 22\nSharedVolumeSize: 23\nMasterNodeFlavor: 25\nSkipCrmCleanupOnFailure: 26\nOptRes: 27\nResources: 28\nResourcesVms: 28.1\nResourcesVmsName: 28.1.1\nResourcesVmsType: 28.1.2\nResourcesVmsStatus: 28.1.3\nResourcesVmsInfraFlavor: 28.1.4\nResourcesVmsIpaddresses: 28.1.5\nResourcesVmsIpaddressesExternalIp: 28.1.5.1\nResourcesVmsIpaddressesInternalIp: 28.1.5.2\nResourcesVmsContainers: 28.1.6\nResourcesVmsContainersName: 28.1.6.1\nResourcesVmsContainersType: 28.1.6.2\nResourcesVmsContainersStatus: 28.1.6.3\nResourcesVmsContainersClusterip: 28.1.6.4\nResourcesVmsContainersRestarts: 28.1.6.5\nCreatedAt: 29\nCreatedAtSeconds: 29.1\nCreatedAtNanos: 29.2\nUpdatedAt: 30\nUpdatedAtSeconds: 30.1\nUpdatedAtNanos: 30.2\nReservationEndedAt: 31\nReservationEndedAtSeconds: 31.1\nReservationEndedAtNanos: 31.2\nMultiTenant: 32\nNetworks: 33\nDeletePrepare: 34\nDnsLabel: 35\nFqdn: 36\n```", + "tags": ["ClusterInst"], + "summary": "Update Cluster Instance", + "operationId": "UpdateClusterInst", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionClusterInst" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateFlavor": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "The following values should be added to `Flavor.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyName: 2.1\nRam: 3\nVcpus: 4\nDisk: 5\nOptResMap: 6\nOptResMapKey: 6.1\nOptResMapValue: 6.2\nDeletePrepare: 7\n```", + "tags": ["Flavor"], + "summary": "Update a Flavor", + "operationId": "UpdateFlavor", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionFlavor" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateFlowRateLimitSettings": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "The following values should be added to `FlowRateLimitSettings.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyFlowSettingsName: 2.1\nKeyRateLimitKey: 2.2\nKeyRateLimitKeyApiName: 2.2.1\nKeyRateLimitKeyApiEndpointType: 2.2.2\nKeyRateLimitKeyRateLimitTarget: 2.2.3\nSettings: 3\nSettingsFlowAlgorithm: 3.1\nSettingsReqsPerSecond: 3.2\nSettingsBurstSize: 3.3\n```", + "tags": ["FlowRateLimitSettings"], + "summary": "Update Flow RateLimit settings for an API endpoint and target", + "operationId": "UpdateFlowRateLimitSettings", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionFlowRateLimitSettings" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateGPUDriver": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Updates GPU driver config.\nThe following values should be added to `GPUDriver.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyName: 2.1\nKeyOrganization: 2.2\nBuilds: 3\nBuildsName: 3.1\nBuildsDriverPath: 3.2\nBuildsDriverPathCreds: 3.3\nBuildsOperatingSystem: 3.4\nBuildsKernelVersion: 3.5\nBuildsHypervisorInfo: 3.6\nBuildsMd5Sum: 3.7\nBuildsStoragePath: 3.8\nLicenseConfig: 4\nLicenseConfigMd5Sum: 5\nProperties: 6\nPropertiesKey: 6.1\nPropertiesValue: 6.2\nState: 7\nIgnoreState: 8\nDeletePrepare: 9\nStorageBucketName: 10\nLicenseConfigStoragePath: 11\n```", + "tags": ["GPUDriver"], + "summary": "Update GPU Driver", + "operationId": "UpdateGPUDriver", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionGPUDriver" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateMaxReqsRateLimitSettings": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "The following values should be added to `MaxReqsRateLimitSettings.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyMaxReqsSettingsName: 2.1\nKeyRateLimitKey: 2.2\nKeyRateLimitKeyApiName: 2.2.1\nKeyRateLimitKeyApiEndpointType: 2.2.2\nKeyRateLimitKeyRateLimitTarget: 2.2.3\nSettings: 3\nSettingsMaxReqsAlgorithm: 3.1\nSettingsMaxRequests: 3.2\nSettingsInterval: 3.3\n```", + "tags": ["MaxReqsRateLimitSettings"], + "summary": "Update MaxReqs RateLimit settings for an API endpoint and target", + "operationId": "UpdateMaxReqsRateLimitSettings", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionMaxReqsRateLimitSettings" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateNetwork": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "The following values should be added to `Network.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyCloudletKey: 2.1\nKeyCloudletKeyOrganization: 2.1.1\nKeyCloudletKeyName: 2.1.2\nKeyCloudletKeyFederatedOrganization: 2.1.3\nKeyName: 2.2\nRoutes: 3\nRoutesDestinationCidr: 3.1\nRoutesNextHopIp: 3.2\nConnectionType: 4\nDeletePrepare: 5\n```", + "tags": ["Network"], + "summary": "Update a Network", + "operationId": "UpdateNetwork", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionNetwork" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateResTagTable": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "The following values should be added to `ResTagTable.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyName: 2.1\nKeyOrganization: 2.2\nTags: 3\nTagsKey: 3.1\nTagsValue: 3.2\nAzone: 4\nDeletePrepare: 5\n```", + "tags": ["ResTagTable"], + "summary": "Update TagTable", + "operationId": "UpdateResTagTable", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionResTagTable" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateSettings": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "The following values should be added to `Settings.fields` field array to specify which fields will be updated.\n```\nShepherdMetricsCollectionInterval: 2\nShepherdAlertEvaluationInterval: 20\nShepherdMetricsScrapeInterval: 40\nShepherdHealthCheckRetries: 3\nShepherdHealthCheckInterval: 4\nAutoDeployIntervalSec: 5\nAutoDeployOffsetSec: 6\nAutoDeployMaxIntervals: 7\nCreateAppInstTimeout: 8\nUpdateAppInstTimeout: 9\nDeleteAppInstTimeout: 10\nCreateClusterInstTimeout: 11\nUpdateClusterInstTimeout: 12\nDeleteClusterInstTimeout: 13\nMasterNodeFlavor: 14\nMaxTrackedDmeClients: 16\nChefClientInterval: 17\nInfluxDbMetricsRetention: 18\nCloudletMaintenanceTimeout: 19\nUpdateVmPoolTimeout: 21\nUpdateTrustPolicyTimeout: 22\nDmeApiMetricsCollectionInterval: 23\nEdgeEventsMetricsCollectionInterval: 24\nCleanupReservableAutoClusterIdletime: 25\nInfluxDbCloudletUsageMetricsRetention: 26\nCreateCloudletTimeout: 27\nUpdateCloudletTimeout: 28\nLocationTileSideLengthKm: 29\nEdgeEventsMetricsContinuousQueriesCollectionIntervals: 30\nEdgeEventsMetricsContinuousQueriesCollectionIntervalsInterval: 30.1\nEdgeEventsMetricsContinuousQueriesCollectionIntervalsRetention: 30.2\nInfluxDbDownsampledMetricsRetention: 31\nInfluxDbEdgeEventsMetricsRetention: 32\nAppinstClientCleanupInterval: 33\nClusterAutoScaleAveragingDurationSec: 34\nClusterAutoScaleRetryDelay: 35\nAlertPolicyMinTriggerTime: 36\nDisableRateLimit: 37\nRateLimitMaxTrackedIps: 39\nResourceSnapshotThreadInterval: 41\nPlatformHaInstancePollInterval: 42\nPlatformHaInstanceActiveExpireTime: 43\n```", + "tags": ["Settings"], + "summary": "Update settings", + "operationId": "UpdateSettings", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionSettings" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateTrustPolicy": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "The following values should be added to `TrustPolicy.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyOrganization: 2.1\nKeyName: 2.2\nOutboundSecurityRules: 3\nOutboundSecurityRulesProtocol: 3.1\nOutboundSecurityRulesPortRangeMin: 3.2\nOutboundSecurityRulesPortRangeMax: 3.3\nOutboundSecurityRulesRemoteCidr: 3.4\nDeletePrepare: 4\n```", + "tags": ["TrustPolicy"], + "summary": "Update a Trust policy", + "operationId": "UpdateTrustPolicy", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionTrustPolicy" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateTrustPolicyException": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "The following values should be added to `TrustPolicyException.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyAppKey: 2.1\nKeyAppKeyOrganization: 2.1.1\nKeyAppKeyName: 2.1.2\nKeyAppKeyVersion: 2.1.3\nKeyCloudletPoolKey: 2.2\nKeyCloudletPoolKeyOrganization: 2.2.1\nKeyCloudletPoolKeyName: 2.2.2\nKeyName: 2.3\nState: 3\nOutboundSecurityRules: 4\nOutboundSecurityRulesProtocol: 4.1\nOutboundSecurityRulesPortRangeMin: 4.2\nOutboundSecurityRulesPortRangeMax: 4.3\nOutboundSecurityRulesRemoteCidr: 4.4\n```", + "tags": ["TrustPolicyException"], + "summary": "Update a Trust Policy Exception, by Operator Organization", + "operationId": "UpdateTrustPolicyException", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionTrustPolicyException" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/ctrl/UpdateVMPool": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Updates a VM pools VMs.\nThe following values should be added to `VMPool.fields` field array to specify which fields will be updated.\n```\nKey: 2\nKeyOrganization: 2.1\nKeyName: 2.2\nVms: 3\nVmsName: 3.1\nVmsNetInfo: 3.2\nVmsNetInfoExternalIp: 3.2.1\nVmsNetInfoInternalIp: 3.2.2\nVmsGroupName: 3.3\nVmsState: 3.4\nVmsUpdatedAt: 3.5\nVmsUpdatedAtSeconds: 3.5.1\nVmsUpdatedAtNanos: 3.5.2\nVmsInternalName: 3.6\nVmsFlavor: 3.7\nVmsFlavorName: 3.7.1\nVmsFlavorVcpus: 3.7.2\nVmsFlavorRam: 3.7.3\nVmsFlavorDisk: 3.7.4\nVmsFlavorPropMap: 3.7.5\nVmsFlavorPropMapKey: 3.7.5.1\nVmsFlavorPropMapValue: 3.7.5.2\nState: 4\nErrors: 5\nCrmOverride: 7\nDeletePrepare: 8\n```", + "tags": ["VMPool"], + "summary": "Update VMPool", + "operationId": "UpdateVMPool", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionVMPool" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/events/find": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Find events\nDisplay events based on find filter.", + "tags": ["Events"], + "operationId": "FindEvents", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/EventSearch" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/events/show": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Search events\nDisplay events based on search filter.", + "tags": ["Events"], + "operationId": "SearchEvents", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/EventSearch" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/events/terms": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Terms Events\nDisplay events terms.", + "tags": ["Events"], + "operationId": "TermsEvents", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/EventTerms" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/metrics/app": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Display app related metrics.", + "tags": ["DeveloperMetrics"], + "summary": "App related metrics", + "operationId": "AppMetrics", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppInstMetrics" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/metrics/clientapiusage": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Display client api usage related metrics.", + "tags": ["DeveloperMetrics"], + "summary": "Client api usage related metrics", + "operationId": "ClientApiUsageMetrics", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionClientApiUsageMetrics" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/metrics/clientappusage": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Display client app usage related metrics.", + "tags": ["DeveloperMetrics"], + "summary": "Client app usage related metrics", + "operationId": "ClientAppUsageMetrics", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionClientAppUsageMetrics" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/metrics/clientcloudletusage": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Display client cloudlet usage related metrics.", + "tags": ["DeveloperMetrics"], + "summary": "Client cloudlet usage related metrics", + "operationId": "ClientCloudletUsageMetrics", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionClientCloudletUsageMetrics" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/metrics/cloudlet": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Display cloudlet related metrics.", + "tags": ["OperatorMetrics"], + "summary": "Cloudlet related metrics", + "operationId": "CloudletMetrics", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletMetrics" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/metrics/cloudlet/usage": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Display cloudlet usage related metrics.", + "tags": ["OperatorMetrics"], + "summary": "Cloudlet usage related metrics", + "operationId": "CloudletUsageMetrics", + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/metrics/cluster": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Display cluster related metrics.", + "tags": ["DeveloperMetrics"], + "summary": "Cluster related metrics", + "operationId": "ClusterMetrics", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionClusterInstMetrics" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/org/create": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Create an Organization to access operator/cloudlet APIs.", + "tags": ["Organization"], + "summary": "Create Organization", + "operationId": "CreateOrg", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/Organization" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/org/delete": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Deletes an existing Organization.", + "tags": ["Organization"], + "summary": "Delete Organization", + "operationId": "DeleteOrg", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/Organization" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/org/show": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Displays existing Organizations in which you are authorized to access.", + "tags": ["Organization"], + "summary": "Show Organizations", + "operationId": "ShowOrg", + "responses": { + "200": { + "$ref": "#/responses/listOrgs" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/org/update": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API to update an existing Organization.", + "tags": ["Organization"], + "summary": "Update Organization", + "operationId": "UpdateOrg", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/Organization" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/role/adduser": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Add a role for the organization to the user.", + "tags": ["Role"], + "summary": "Add User Role", + "operationId": "AddUserRole", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/Role" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/role/assignment/show": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Show roles for the current user.", + "tags": ["Role"], + "summary": "Show Role Assignment", + "operationId": "ShowRoleAssignment", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/Role" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/listRoles" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/role/perms/show": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Show permissions associated with each role.", + "tags": ["Role"], + "summary": "Show Role Permissions", + "operationId": "ShowRolePerm", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RolePerm" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/listPerms" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/role/removeuser": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Remove the role for the organization from the user.", + "tags": ["Role"], + "summary": "Remove User Role", + "operationId": "RemoveUserRole", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/Role" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/role/show": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Show role names.", + "tags": ["Role"], + "summary": "Show Role Names", + "operationId": "ShowRoleNames", + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/role/showuser": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Show roles for the organizations the current user can add or remove roles to", + "tags": ["Role"], + "summary": "Show User Role", + "operationId": "ShowUserRole", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/Role" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/listRoles" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/usage/app": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "App Usage\nDisplay app usage.", + "tags": ["DeveloperUsage"], + "operationId": "AppUsage", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionAppInstUsage" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/usage/cloudletpool": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "CloudletPool Usage\nDisplay cloudletpool usage.", + "tags": ["OperatorUsage"], + "operationId": "CloudletPoolUsage", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionCloudletPoolUsage" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/usage/cluster": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Cluster Usage\nDisplay cluster usage.", + "tags": ["DeveloperUsage"], + "operationId": "ClusterUsage", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/RegionClusterInstUsage" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/user/delete": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Deletes existing user.", + "tags": ["User"], + "summary": "Delete User", + "operationId": "DeleteUser", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/User" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/user/show": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Displays existing users to which you are authorized to access.", + "tags": ["User"], + "summary": "Show Users", + "operationId": "ShowUser", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/Organization" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/listUsers" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/auth/user/update": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Updates current user.", + "tags": ["User"], + "summary": "Update User", + "operationId": "UpdateUser", + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/login": { + "post": { + "description": "Log in to the MC to acquire a temporary bearer token for access to other APIs.\nAuthentication can be via a username and password, or an API key ID and API key if created. If two-factor authentication (2FA) is enabled on the account, an additional temporary one-time password (TOTP) from a mobile authenticator will also be required.\n", + "tags": ["Security"], + "summary": "Login", + "operationId": "Login", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/UserLogin" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/authToken" + }, + "400": { + "$ref": "#/responses/loginBadRequest" + } + } + } + }, + "/passwordreset": { + "post": { + "description": "This resets your login password.", + "tags": ["Security"], + "summary": "Reset Login Password", + "operationId": "PasswdReset", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/PasswordReset" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + } + } + } + }, + "/publicconfig": { + "post": { + "description": "Show Public Configuration for UI", + "tags": ["Config"], + "summary": "Show Public Configuration", + "operationId": "PublicConfig", + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + }, + "/usercreate": { + "post": { + "description": "Creates a new user and allows them to access and manage resources.", + "tags": ["User"], + "summary": "Create User", + "operationId": "CreateUser", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/CreateUser" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/success" + }, + "400": { + "$ref": "#/responses/badRequest" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + } + } + } + } + }, + "definitions": { + "AccessType": { + "description": "AccessType indicates how to access the app\n\n0: `ACCESS_TYPE_DEFAULT_FOR_DEPLOYMENT`\n1: `ACCESS_TYPE_DIRECT`\n2: `ACCESS_TYPE_LOAD_BALANCER`", + "type": "integer", + "format": "int32", + "title": "(Deprecated) AccessType", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AggrVal": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "format": "int64", + "x-go-name": "DocCount" + }, + "key": { + "type": "string", + "x-go-name": "Key" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/cloudcommon/node" + }, + "Alert": { + "type": "object", + "properties": { + "active_at": { + "$ref": "#/definitions/Timestamp" + }, + "annotations": { + "description": "Annotations are extra information about the alert", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "Annotations" + }, + "controller": { + "description": "Connected controller unique id", + "type": "string", + "x-go-name": "Controller" + }, + "labels": { + "description": "Labels uniquely define the alert", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "Labels" + }, + "notify_id": { + "description": "Id of client assigned by server (internal use only)", + "type": "integer", + "format": "int64", + "x-go-name": "NotifyId" + }, + "state": { + "description": "State of the alert", + "type": "string", + "x-go-name": "State" + }, + "value": { + "description": "Any value associated with alert", + "type": "number", + "format": "double", + "x-go-name": "Value" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AlertPolicy": { + "type": "object", + "properties": { + "active_conn_limit": { + "description": "Active Connections alert threshold. Valid values 1-4294967295", + "type": "integer", + "format": "uint32", + "x-go-name": "ActiveConnLimit" + }, + "annotations": { + "description": "Additional Annotations for extra information about the alert", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "Annotations" + }, + "cpu_utilization_limit": { + "description": "Container or pod CPU utilization rate(percentage) across all nodes. Valid values 1-100", + "type": "integer", + "format": "uint32", + "x-go-name": "CpuUtilizationLimit" + }, + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "description": { + "description": "Description of the alert policy", + "type": "string", + "x-go-name": "Description" + }, + "disk_utilization_limit": { + "description": "Container or pod disk utilization rate(percentage) across all nodes. Valid values 1-100", + "type": "integer", + "format": "uint32", + "x-go-name": "DiskUtilizationLimit" + }, + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "key": { + "$ref": "#/definitions/AlertPolicyKey" + }, + "labels": { + "description": "Additional Labels", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "Labels" + }, + "mem_utilization_limit": { + "description": "Container or pod memory utilization rate(percentage) across all nodes. Valid values 1-100", + "type": "integer", + "format": "uint32", + "x-go-name": "MemUtilizationLimit" + }, + "severity": { + "description": "Alert severity level - one of \"info\", \"warning\", \"error\"", + "type": "string", + "x-go-name": "Severity" + }, + "trigger_time": { + "$ref": "#/definitions/Duration" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AlertPolicyKey": { + "type": "object", + "properties": { + "name": { + "description": "Alert Policy name", + "type": "string", + "x-go-name": "Name" + }, + "organization": { + "description": "Name of the organization for the app that this alert can be applied to", + "type": "string", + "x-go-name": "Organization" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AlertReceiver": { + "description": "Configurable part of AlertManager Receiver", + "type": "object", + "properties": { + "AppInst": { + "$ref": "#/definitions/AppInstKey" + }, + "Cloudlet": { + "$ref": "#/definitions/CloudletKey" + }, + "Email": { + "description": "Custom receiving email", + "type": "string" + }, + "Name": { + "description": "Receiver Name", + "type": "string" + }, + "PagerDutyApiVersion": { + "description": "PagerDuty API version", + "type": "string" + }, + "PagerDutyIntegrationKey": { + "description": "PagerDuty integration key", + "type": "string" + }, + "Region": { + "description": "Region for the alert receiver", + "type": "string" + }, + "Severity": { + "description": "Alert severity filter", + "type": "string" + }, + "SlackChannel": { + "description": "Custom slack channel", + "type": "string" + }, + "SlackWebhook": { + "description": "Custom slack webhook", + "type": "string" + }, + "Type": { + "description": "Receiver type. Eg. email, slack, pagerduty", + "type": "string" + }, + "User": { + "description": "User that created this receiver", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "ApiEndpointType": { + "type": "integer", + "format": "int32", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "App": { + "description": "App belongs to developer organizations and is used to provide information about their application.", + "type": "object", + "title": "Application", + "required": ["key"], + "properties": { + "access_ports": { + "description": "Comma separated list of protocol:port pairs that the App listens on.\nEx: \"tcp:80,udp:10002\".\nAlso supports additional configurations per port:\n(1) tls (tcp-only) - Enables TLS on specified port. Ex: \"tcp:443:tls\".\n(2) nginx (udp-only) - Use NGINX LB instead of envoy for specified port. Ex: \"udp:10001:nginx\".\n(3) maxpktsize (udp-only) - Configures maximum UDP datagram size allowed on port for both upstream/downstream traffic. Ex: \"udp:10001:maxpktsize=8000\".", + "type": "string", + "x-go-name": "AccessPorts" + }, + "access_type": { + "$ref": "#/definitions/AccessType" + }, + "alert_policies": { + "description": "Alert Policies", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "AlertPolicies" + }, + "allow_serverless": { + "description": "App is allowed to deploy as serverless containers", + "type": "boolean", + "x-go-name": "AllowServerless" + }, + "android_package_name": { + "description": "Android package name used to match the App name from the Android package", + "type": "string", + "x-go-name": "AndroidPackageName" + }, + "annotations": { + "description": "Annotations is a comma separated map of arbitrary key value pairs,", + "type": "string", + "x-go-name": "Annotations", + "example": "key1=val1,key2=val2,key3=\"val 3\"" + }, + "auth_public_key": { + "description": "Public key used for authentication", + "type": "string", + "x-go-name": "AuthPublicKey" + }, + "auto_prov_policies": { + "description": "Auto provisioning policy names, may be specified multiple times", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "AutoProvPolicies" + }, + "auto_prov_policy": { + "description": "(_deprecated_) Auto provisioning policy name", + "type": "string", + "x-go-name": "AutoProvPolicy" + }, + "command": { + "description": "Command that the container runs to start service", + "type": "string", + "x-go-name": "Command" + }, + "configs": { + "description": "Customization files passed through to implementing services", + "type": "array", + "items": { + "$ref": "#/definitions/ConfigFile" + }, + "x-go-name": "Configs" + }, + "created_at": { + "$ref": "#/definitions/Timestamp" + }, + "default_flavor": { + "$ref": "#/definitions/FlavorKey" + }, + "del_opt": { + "$ref": "#/definitions/DeleteType" + }, + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "deployment": { + "description": "Deployment type (kubernetes, docker, or vm)", + "type": "string", + "x-go-name": "Deployment" + }, + "deployment_generator": { + "description": "Deployment generator target to generate a basic deployment manifest", + "type": "string", + "x-go-name": "DeploymentGenerator" + }, + "deployment_manifest": { + "description": "Deployment manifest is the deployment specific manifest file/config.\nFor docker deployment, this can be a docker-compose or docker run file.\nFor kubernetes deployment, this can be a kubernetes yaml or helm chart file.", + "type": "string", + "x-go-name": "DeploymentManifest" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "image_path": { + "description": "URI of where image resides", + "type": "string", + "x-go-name": "ImagePath" + }, + "image_type": { + "$ref": "#/definitions/ImageType" + }, + "internal_ports": { + "description": "Should this app have access to outside world?", + "type": "boolean", + "x-go-name": "InternalPorts" + }, + "key": { + "$ref": "#/definitions/AppKey" + }, + "md5sum": { + "description": "MD5Sum of the VM-based app image", + "type": "string", + "x-go-name": "Md5Sum" + }, + "official_fqdn": { + "description": "Official FQDN is the FQDN that the app uses to connect by default", + "type": "string", + "x-go-name": "OfficialFqdn" + }, + "qos_session_duration": { + "$ref": "#/definitions/Duration" + }, + "qos_session_profile": { + "$ref": "#/definitions/QosSessionProfile" + }, + "required_outbound_connections": { + "description": "Connections this app require to determine if the app is compatible with a trust policy", + "type": "array", + "items": { + "$ref": "#/definitions/SecurityRule" + }, + "x-go-name": "RequiredOutboundConnections" + }, + "revision": { + "description": "Revision can be specified or defaults to current timestamp when app is updated", + "type": "string", + "x-go-name": "Revision" + }, + "scale_with_cluster": { + "description": "Option to run App on all nodes of the cluster", + "type": "boolean", + "x-go-name": "ScaleWithCluster" + }, + "serverless_config": { + "$ref": "#/definitions/ServerlessConfig" + }, + "skip_hc_ports": { + "description": "Comma separated list of protocol:port pairs that we should not run health check on.\nShould be configured in case app does not always listen on these ports.\n\"all\" can be specified if no health check to be run for this app.\nNumerical values must be decimal format.\ni.e. tcp:80,udp:10002", + "type": "string", + "x-go-name": "SkipHcPorts" + }, + "template_delimiter": { + "description": "Delimiter to be used for template parsing, defaults to \"[[ ]]\"", + "type": "string", + "x-go-name": "TemplateDelimiter" + }, + "trusted": { + "description": "Indicates that an instance of this app can be started on a trusted cloudlet", + "type": "boolean", + "x-go-name": "Trusted" + }, + "updated_at": { + "$ref": "#/definitions/Timestamp" + }, + "vm_app_os_type": { + "$ref": "#/definitions/VmAppOsType" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AppAlertPolicy": { + "type": "object", + "properties": { + "alert_policy": { + "description": "Alert name", + "type": "string", + "x-go-name": "AlertPolicy" + }, + "app_key": { + "$ref": "#/definitions/AppKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AppAutoProvPolicy": { + "description": "AutoProvPolicy belonging to an app", + "type": "object", + "properties": { + "app_key": { + "$ref": "#/definitions/AppKey" + }, + "auto_prov_policy": { + "description": "Auto provisioning policy name", + "type": "string", + "x-go-name": "AutoProvPolicy" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AppInst": { + "description": "AppInst is an instance of an App on a Cloudlet where it is defined by an App plus a ClusterInst key.\nMany of the fields here are inherited from the App definition.", + "type": "object", + "title": "Application Instance", + "required": ["key"], + "properties": { + "auto_cluster_ip_access": { + "$ref": "#/definitions/IpAccess" + }, + "availability_zone": { + "description": "Optional Availability Zone if any", + "type": "string", + "x-go-name": "AvailabilityZone" + }, + "cloudlet_loc": { + "$ref": "#/definitions/Loc" + }, + "configs": { + "description": "Customization files passed through to implementing services", + "type": "array", + "items": { + "$ref": "#/definitions/ConfigFile" + }, + "x-go-name": "Configs" + }, + "created_at": { + "$ref": "#/definitions/Timestamp" + }, + "crm_override": { + "$ref": "#/definitions/CRMOverride" + }, + "dedicated_ip": { + "description": "Dedicated IP assigns an IP for this AppInst but requires platform support", + "type": "boolean", + "x-go-name": "DedicatedIp" + }, + "dns_label": { + "description": "DNS label that is unique within the cloudlet and among other AppInsts/ClusterInsts", + "type": "string", + "x-go-name": "DnsLabel" + }, + "errors": { + "description": "Any errors trying to create, update, or delete the AppInst on the Cloudlet", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Errors" + }, + "external_volume_size": { + "description": "Size of external volume to be attached to nodes. This is for the root partition", + "type": "integer", + "format": "uint64", + "x-go-name": "ExternalVolumeSize" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "flavor": { + "$ref": "#/definitions/FlavorKey" + }, + "force_update": { + "description": "Force Appinst refresh even if revision number matches App revision number.", + "type": "boolean", + "x-go-name": "ForceUpdate" + }, + "health_check": { + "$ref": "#/definitions/HealthCheck" + }, + "internal_port_to_lb_ip": { + "description": "mapping of ports to load balancer IPs", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "InternalPortToLbIp" + }, + "key": { + "$ref": "#/definitions/AppInstKey" + }, + "liveness": { + "$ref": "#/definitions/Liveness" + }, + "mapped_ports": { + "description": "For instances accessible via a shared load balancer, defines the external\nports on the shared load balancer that map to the internal ports\nExternal ports should be appended to the Uri for L4 access.", + "type": "array", + "items": { + "$ref": "#/definitions/AppPort" + }, + "x-go-name": "MappedPorts" + }, + "opt_res": { + "description": "Optional Resources required by OS flavor if any", + "type": "string", + "x-go-name": "OptRes" + }, + "power_state": { + "$ref": "#/definitions/PowerState" + }, + "real_cluster_name": { + "description": "Real ClusterInst name", + "type": "string", + "x-go-name": "RealClusterName" + }, + "revision": { + "description": "Revision changes each time the App is updated. Refreshing the App Instance will sync the revision with that of the App", + "type": "string", + "x-go-name": "Revision" + }, + "runtime_info": { + "$ref": "#/definitions/AppInstRuntime" + }, + "state": { + "$ref": "#/definitions/TrackedState" + }, + "unique_id": { + "description": "A unique id for the AppInst within the region to be used by platforms", + "type": "string", + "x-go-name": "UniqueId" + }, + "update_multiple": { + "description": "Allow multiple instances to be updated at once", + "type": "boolean", + "x-go-name": "UpdateMultiple" + }, + "updated_at": { + "$ref": "#/definitions/Timestamp" + }, + "uri": { + "description": "Base FQDN (not really URI) for the App. See Service FQDN for endpoint access.", + "type": "string", + "x-go-name": "Uri" + }, + "vm_flavor": { + "description": "OS node flavor to use", + "type": "string", + "x-go-name": "VmFlavor" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AppInstClientKey": { + "type": "object", + "properties": { + "app_inst_key": { + "$ref": "#/definitions/AppInstKey" + }, + "unique_id": { + "description": "AppInstClient Unique Id", + "type": "string", + "x-go-name": "UniqueId" + }, + "unique_id_type": { + "description": "AppInstClient Unique Id Type", + "type": "string", + "x-go-name": "UniqueIdType" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AppInstKey": { + "description": "AppInstKey uniquely identifies an Application Instance (AppInst) or Application Instance state (AppInstInfo).", + "type": "object", + "title": "App Instance Unique Key", + "properties": { + "app_key": { + "$ref": "#/definitions/AppKey" + }, + "cluster_inst_key": { + "$ref": "#/definitions/VirtualClusterInstKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AppInstLatency": { + "type": "object", + "properties": { + "key": { + "$ref": "#/definitions/AppInstKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AppInstRefKey": { + "description": "AppInstRefKey is app instance key without cloudlet key.", + "type": "object", + "title": "AppInst Ref Key", + "properties": { + "app_key": { + "$ref": "#/definitions/AppKey" + }, + "cluster_inst_key": { + "$ref": "#/definitions/ClusterInstRefKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AppInstRefs": { + "type": "object", + "properties": { + "delete_requested_insts": { + "description": "AppInsts being deleted (key is JSON of AppInst Key)", + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "uint32" + }, + "x-go-name": "DeleteRequestedInsts" + }, + "insts": { + "description": "AppInsts for App (key is JSON of AppInst Key)", + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "uint32" + }, + "x-go-name": "Insts" + }, + "key": { + "$ref": "#/definitions/AppKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AppInstRuntime": { + "description": "Runtime information of active AppInsts", + "type": "object", + "title": "AppInst Runtime Info", + "properties": { + "container_ids": { + "description": "List of container names", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "ContainerIds" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AppKey": { + "description": "AppKey uniquely identifies an App", + "type": "object", + "title": "Application unique key", + "properties": { + "name": { + "description": "App name", + "type": "string", + "x-go-name": "Name" + }, + "organization": { + "description": "App developer organization", + "type": "string", + "x-go-name": "Organization" + }, + "version": { + "description": "App version", + "type": "string", + "x-go-name": "Version" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AppPort": { + "description": "AppPort describes an L4 or L7 public access port/path mapping. This is used to track external to internal mappings for access via a shared load balancer or reverse proxy.", + "type": "object", + "title": "Application Port", + "properties": { + "end_port": { + "description": "A non-zero end port indicates a port range from internal port to end port, inclusive.", + "type": "integer", + "format": "int32", + "x-go-name": "EndPort" + }, + "fqdn_prefix": { + "description": "skip 4 to preserve the numbering. 4 was path_prefix but was removed since we dont need it after removed http\nFQDN prefix to append to base FQDN in FindCloudlet response. May be empty.", + "type": "string", + "x-go-name": "FqdnPrefix" + }, + "internal_port": { + "description": "Container port", + "type": "integer", + "format": "int32", + "x-go-name": "InternalPort" + }, + "max_pkt_size": { + "description": "Maximum datagram size (udp only)", + "type": "integer", + "format": "int64", + "x-go-name": "MaxPktSize" + }, + "nginx": { + "description": "Use nginx proxy for this port if you really need a transparent proxy (udp only)", + "type": "boolean", + "x-go-name": "Nginx" + }, + "proto": { + "$ref": "#/definitions/LProto" + }, + "public_port": { + "description": "Public facing port for TCP/UDP (may be mapped on shared LB reverse proxy)", + "type": "integer", + "format": "int32", + "x-go-name": "PublicPort" + }, + "tls": { + "description": "TLS termination for this port", + "type": "boolean", + "x-go-name": "Tls" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/dme-proto" + }, + "AutoProvCloudlet": { + "description": "AutoProvCloudlet stores the potential cloudlet and location for DME lookup", + "type": "object", + "properties": { + "key": { + "$ref": "#/definitions/CloudletKey" + }, + "loc": { + "$ref": "#/definitions/Loc" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AutoProvPolicy": { + "description": "AutoProvPolicy defines the automated provisioning policy", + "type": "object", + "properties": { + "cloudlets": { + "description": "Allowed deployment locations", + "type": "array", + "items": { + "$ref": "#/definitions/AutoProvCloudlet" + }, + "x-go-name": "Cloudlets" + }, + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "deploy_client_count": { + "description": "Minimum number of clients within the auto deploy interval to trigger deployment", + "type": "integer", + "format": "uint32", + "x-go-name": "DeployClientCount" + }, + "deploy_interval_count": { + "description": "Number of intervals to check before triggering deployment", + "type": "integer", + "format": "uint32", + "x-go-name": "DeployIntervalCount" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "key": { + "$ref": "#/definitions/PolicyKey" + }, + "max_instances": { + "description": "Maximum number of instances (active or not)", + "type": "integer", + "format": "uint32", + "x-go-name": "MaxInstances" + }, + "min_active_instances": { + "description": "Minimum number of active instances for High-Availability", + "type": "integer", + "format": "uint32", + "x-go-name": "MinActiveInstances" + }, + "undeploy_client_count": { + "description": "Number of active clients for the undeploy interval below which trigers undeployment, 0 (default) disables auto undeploy", + "type": "integer", + "format": "uint32", + "x-go-name": "UndeployClientCount" + }, + "undeploy_interval_count": { + "description": "Number of intervals to check before triggering undeployment", + "type": "integer", + "format": "uint32", + "x-go-name": "UndeployIntervalCount" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AutoProvPolicyCloudlet": { + "description": "AutoProvPolicyCloudlet is used to add and remove Cloudlets from the Auto Provisioning Policy", + "type": "object", + "properties": { + "cloudlet_key": { + "$ref": "#/definitions/CloudletKey" + }, + "key": { + "$ref": "#/definitions/PolicyKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "AutoScalePolicy": { + "description": "AutoScalePolicy defines when and how cluster instances will have their\nnodes scaled up or down.", + "type": "object", + "properties": { + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "key": { + "$ref": "#/definitions/PolicyKey" + }, + "max_nodes": { + "description": "Maximum number of cluster nodes", + "type": "integer", + "format": "uint32", + "x-go-name": "MaxNodes" + }, + "min_nodes": { + "description": "Minimum number of cluster nodes", + "type": "integer", + "format": "uint32", + "x-go-name": "MinNodes" + }, + "scale_down_cpu_thresh": { + "description": "(Deprecated) Scale down cpu threshold (percentage 1 to 100), 0 means disabled", + "type": "integer", + "format": "uint32", + "x-go-name": "ScaleDownCpuThresh" + }, + "scale_up_cpu_thresh": { + "description": "(Deprecated) Scale up cpu threshold (percentage 1 to 100), 0 means disabled", + "type": "integer", + "format": "uint32", + "x-go-name": "ScaleUpCpuThresh" + }, + "stabilization_window_sec": { + "description": "Stabilization window is the time for which past triggers are considered; the largest scale factor is always taken.", + "type": "integer", + "format": "uint32", + "x-go-name": "StabilizationWindowSec" + }, + "target_active_connections": { + "description": "Target per-node number of active connections, 0 means disabled", + "type": "integer", + "format": "uint64", + "x-go-name": "TargetActiveConnections" + }, + "target_cpu": { + "description": "Target per-node cpu utilization (percentage 1 to 100), 0 means disabled", + "type": "integer", + "format": "uint32", + "x-go-name": "TargetCpu" + }, + "target_mem": { + "description": "Target per-node memory utilization (percentage 1 to 100), 0 means disabled", + "type": "integer", + "format": "uint32", + "x-go-name": "TargetMem" + }, + "trigger_time_sec": { + "description": "(Deprecated) Trigger time defines how long the target must be satified in seconds before acting upon it.", + "type": "integer", + "format": "uint32", + "x-go-name": "TriggerTimeSec" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "BillingOrganization": { + "type": "object", + "required": ["Name"], + "properties": { + "Address": { + "description": "Organization address", + "type": "string" + }, + "Address2": { + "description": "Organization address2", + "type": "string" + }, + "Children": { + "description": "Children belonging to this BillingOrganization", + "type": "string" + }, + "City": { + "description": "Organization city", + "type": "string" + }, + "Country": { + "description": "Organization country", + "type": "string" + }, + "CreatedAt": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "DeleteInProgress": { + "description": "Delete of this BillingOrganization is in progress", + "type": "boolean", + "readOnly": true + }, + "Email": { + "description": "Organization email", + "type": "string" + }, + "FirstName": { + "description": "Billing info first name", + "type": "string" + }, + "LastName": { + "description": "Billing info last name", + "type": "string" + }, + "Name": { + "description": "BillingOrganization name. Can only contain letters, digits, underscore, period, hyphen. It cannot have leading or trailing spaces or period. It cannot start with hyphen", + "type": "string" + }, + "Phone": { + "description": "Organization phone number", + "type": "string" + }, + "PostalCode": { + "description": "Organization postal code", + "type": "string" + }, + "State": { + "description": "Organization state", + "type": "string" + }, + "Type": { + "description": "Organization type: \"parent\" or \"self\"", + "type": "string" + }, + "UpdatedAt": { + "type": "string", + "format": "date-time", + "readOnly": true + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "CRMOverride": { + "description": "CRMOverride can be applied to commands that issue requests to the CRM.\nIt should only be used by administrators when bugs have caused the\nController and CRM to get out of sync. It allows commands from the\nController to ignore errors from the CRM, or ignore the CRM completely\n(messages will not be sent to CRM).\n\n0: `NO_OVERRIDE`\n1: `IGNORE_CRM_ERRORS`\n2: `IGNORE_CRM`\n3: `IGNORE_TRANSIENT_STATE`\n4: `IGNORE_CRM_AND_TRANSIENT_STATE`", + "type": "integer", + "format": "int32", + "title": "Overrides default CRM behaviour", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "Cloudlet": { + "description": "A Cloudlet is a set of compute resources at a particular location, provided by an Operator.", + "type": "object", + "title": "Cloudlet", + "required": ["key"], + "properties": { + "HostController": { + "description": "Address of the controller hosting the cloudlet services if it is running locally", + "type": "string" + }, + "access_vars": { + "description": "Variables required to access cloudlet", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "AccessVars" + }, + "alliance_orgs": { + "description": "This cloudlet will be treated as directly connected to these additional operator organizations for the purposes of FindCloudlet", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "AllianceOrgs" + }, + "chef_client_key": { + "description": "Chef client key", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "ChefClientKey" + }, + "config": { + "$ref": "#/definitions/PlatformConfig" + }, + "container_version": { + "description": "Cloudlet container version", + "type": "string", + "x-go-name": "ContainerVersion" + }, + "created_at": { + "$ref": "#/definitions/Timestamp" + }, + "crm_access_key_upgrade_required": { + "description": "CRM access key upgrade required", + "type": "boolean", + "x-go-name": "CrmAccessKeyUpgradeRequired" + }, + "crm_access_public_key": { + "description": "CRM access public key", + "type": "string", + "x-go-name": "CrmAccessPublicKey" + }, + "crm_override": { + "$ref": "#/definitions/CRMOverride" + }, + "default_resource_alert_threshold": { + "description": "Default resource alert threshold percentage", + "type": "integer", + "format": "int32", + "x-go-name": "DefaultResourceAlertThreshold" + }, + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "deployment": { + "description": "Deployment type to bring up CRM services (docker, kubernetes)", + "type": "string", + "x-go-name": "Deployment" + }, + "deployment_local": { + "description": "Deploy cloudlet services locally", + "type": "boolean", + "x-go-name": "DeploymentLocal" + }, + "dns_label": { + "description": "DNS label that is unique within the region", + "type": "string", + "x-go-name": "DnsLabel" + }, + "enable_default_serverless_cluster": { + "description": "Enable experimental default multitenant (serverless) cluster", + "type": "boolean", + "x-go-name": "EnableDefaultServerlessCluster" + }, + "env_var": { + "description": "Single Key-Value pair of env var to be passed to CRM", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "EnvVar" + }, + "errors": { + "description": "Any errors trying to create, update, or delete the Cloudlet.", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Errors" + }, + "federation_config": { + "$ref": "#/definitions/FederationConfig" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "flavor": { + "$ref": "#/definitions/FlavorKey" + }, + "gpu_config": { + "$ref": "#/definitions/GPUConfig" + }, + "infra_api_access": { + "$ref": "#/definitions/InfraApiAccess" + }, + "infra_config": { + "$ref": "#/definitions/InfraConfig" + }, + "ip_support": { + "$ref": "#/definitions/IpSupport" + }, + "kafka_cluster": { + "description": "Operator provided kafka cluster endpoint to push events to", + "type": "string", + "x-go-name": "KafkaCluster" + }, + "kafka_password": { + "description": "Password for kafka SASL/PLAIN authentification, stored securely in secret storage and never visible externally", + "type": "string", + "x-go-name": "KafkaPassword" + }, + "kafka_user": { + "description": "Username for kafka SASL/PLAIN authentification, stored securely in secret storage and never visible externally", + "type": "string", + "x-go-name": "KafkaUser" + }, + "key": { + "$ref": "#/definitions/CloudletKey" + }, + "license_config_storage_path": { + "description": "GPU driver license config storage path", + "type": "string", + "x-go-name": "LicenseConfigStoragePath" + }, + "location": { + "$ref": "#/definitions/Loc" + }, + "maintenance_state": { + "$ref": "#/definitions/MaintenanceState" + }, + "notify_srv_addr": { + "description": "Address for the CRM notify listener to run on", + "type": "string", + "x-go-name": "NotifySrvAddr" + }, + "num_dynamic_ips": { + "description": "Number of dynamic IPs available for dynamic IP support", + "type": "integer", + "format": "int32", + "x-go-name": "NumDynamicIps" + }, + "override_policy_container_version": { + "description": "Override container version from policy file", + "type": "boolean", + "x-go-name": "OverridePolicyContainerVersion" + }, + "physical_name": { + "description": "Physical infrastructure cloudlet name", + "type": "string", + "x-go-name": "PhysicalName" + }, + "platform_high_availability": { + "description": "Enable platform H/A", + "type": "boolean", + "x-go-name": "PlatformHighAvailability" + }, + "platform_type": { + "$ref": "#/definitions/PlatformType" + }, + "res_tag_map": { + "description": "Optional resource to restagtbl key map key values = [gpu, nas, nic]", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/ResTagTableKey" + }, + "x-go-name": "ResTagMap" + }, + "resource_quotas": { + "description": "Resource quotas", + "type": "array", + "items": { + "$ref": "#/definitions/ResourceQuota" + }, + "x-go-name": "ResourceQuotas" + }, + "root_lb_fqdn": { + "description": "Root LB FQDN which is globally unique", + "type": "string", + "x-go-name": "RootLbFqdn" + }, + "secondary_crm_access_key_upgrade_required": { + "description": "CRM secondary access key upgrade required for H/A", + "type": "boolean", + "x-go-name": "SecondaryCrmAccessKeyUpgradeRequired" + }, + "secondary_crm_access_public_key": { + "description": "CRM secondary access public key for H/A", + "type": "string", + "x-go-name": "SecondaryCrmAccessPublicKey" + }, + "secondary_notify_srv_addr": { + "description": "Address for the secondary CRM notify listener to run on", + "type": "string", + "x-go-name": "SecondaryNotifySrvAddr" + }, + "single_kubernetes_cluster_owner": { + "description": "For single kubernetes cluster cloudlet platforms, cluster is owned by this organization instead of multi-tenant", + "type": "string", + "x-go-name": "SingleKubernetesClusterOwner" + }, + "state": { + "$ref": "#/definitions/TrackedState" + }, + "static_ips": { + "description": "List of static IPs for static IP support", + "type": "string", + "x-go-name": "StaticIps" + }, + "time_limits": { + "$ref": "#/definitions/OperationTimeLimits" + }, + "trust_policy": { + "description": "Optional Trust Policy", + "type": "string", + "x-go-name": "TrustPolicy" + }, + "trust_policy_state": { + "$ref": "#/definitions/TrackedState" + }, + "updated_at": { + "$ref": "#/definitions/Timestamp" + }, + "vm_image_version": { + "description": "EdgeCloud baseimage version where CRM services reside", + "type": "string", + "x-go-name": "VmImageVersion" + }, + "vm_pool": { + "description": "VM Pool", + "type": "string", + "x-go-name": "VmPool" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletAllianceOrg": { + "type": "object", + "properties": { + "key": { + "$ref": "#/definitions/CloudletKey" + }, + "organization": { + "description": "Alliance organization", + "type": "string", + "x-go-name": "Organization" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletInfo": { + "type": "object", + "title": "CloudletInfo provides information from the Cloudlet Resource Manager about the state of the Cloudlet.", + "properties": { + "active_crm_instance": { + "description": "Active HA instance", + "type": "string", + "x-go-name": "ActiveCrmInstance" + }, + "availability_zones": { + "description": "Availability Zones if any", + "type": "array", + "items": { + "$ref": "#/definitions/OSAZone" + }, + "x-go-name": "AvailabilityZones" + }, + "compatibility_version": { + "description": "Version for compatibility tracking", + "type": "integer", + "format": "uint32", + "x-go-name": "CompatibilityVersion" + }, + "container_version": { + "description": "Cloudlet container version", + "type": "string", + "x-go-name": "ContainerVersion" + }, + "controller": { + "description": "Connected controller unique id", + "type": "string", + "x-go-name": "Controller" + }, + "controller_cache_received": { + "description": "Indicates all controller data has been sent to CRM", + "type": "boolean", + "x-go-name": "ControllerCacheReceived" + }, + "errors": { + "description": "Any errors encountered while making changes to the Cloudlet", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Errors" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "flavors": { + "description": "Supported flavors by the Cloudlet", + "type": "array", + "items": { + "$ref": "#/definitions/FlavorInfo" + }, + "x-go-name": "Flavors" + }, + "key": { + "$ref": "#/definitions/CloudletKey" + }, + "maintenance_state": { + "$ref": "#/definitions/MaintenanceState" + }, + "node_infos": { + "description": "Cluster node info for serverless platforms (k8s multi-tenant cluster)", + "type": "array", + "items": { + "$ref": "#/definitions/NodeInfo" + }, + "x-go-name": "NodeInfos" + }, + "notify_id": { + "description": "Id of client assigned by server (internal use only)", + "type": "integer", + "format": "int64", + "x-go-name": "NotifyId" + }, + "os_images": { + "description": "Local Images availble to cloudlet", + "type": "array", + "items": { + "$ref": "#/definitions/OSImage" + }, + "x-go-name": "OsImages" + }, + "os_max_ram": { + "description": "Maximum Ram in MB on the Cloudlet", + "type": "integer", + "format": "uint64", + "x-go-name": "OsMaxRam" + }, + "os_max_vcores": { + "description": "Maximum number of VCPU cores on the Cloudlet", + "type": "integer", + "format": "uint64", + "x-go-name": "OsMaxVcores" + }, + "os_max_vol_gb": { + "description": "Maximum amount of disk in GB on the Cloudlet", + "type": "integer", + "format": "uint64", + "x-go-name": "OsMaxVolGb" + }, + "properties": { + "description": "Cloudlet properties", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "Properties" + }, + "release_version": { + "description": "Cloudlet release version", + "type": "string", + "x-go-name": "ReleaseVersion" + }, + "resources_snapshot": { + "$ref": "#/definitions/InfraResourcesSnapshot" + }, + "standby_crm": { + "description": "Denotes if info was reported by inactive", + "type": "boolean", + "x-go-name": "StandbyCrm" + }, + "state": { + "$ref": "#/definitions/CloudletState" + }, + "status": { + "$ref": "#/definitions/StatusInfo" + }, + "trust_policy_state": { + "$ref": "#/definitions/TrackedState" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletKey": { + "type": "object", + "title": "CloudletKey uniquely identifies a Cloudlet.", + "properties": { + "federated_organization": { + "description": "Federated operator organization who shared this cloudlet", + "type": "string", + "x-go-name": "FederatedOrganization" + }, + "name": { + "description": "Name of the cloudlet", + "type": "string", + "x-go-name": "Name" + }, + "organization": { + "description": "Organization of the cloudlet site", + "type": "string", + "x-go-name": "Organization" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletMgmtNode": { + "type": "object", + "properties": { + "name": { + "description": "Name of Cloudlet Mgmt Node", + "type": "string", + "x-go-name": "Name" + }, + "type": { + "description": "Type of Cloudlet Mgmt Node", + "type": "string", + "x-go-name": "Type" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletPool": { + "description": "CloudletPool defines a pool of Cloudlets that have restricted access", + "type": "object", + "properties": { + "cloudlets": { + "description": "Cloudlets part of the pool", + "type": "array", + "items": { + "$ref": "#/definitions/CloudletKey" + }, + "x-go-name": "Cloudlets" + }, + "created_at": { + "$ref": "#/definitions/Timestamp" + }, + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "key": { + "$ref": "#/definitions/CloudletPoolKey" + }, + "updated_at": { + "$ref": "#/definitions/Timestamp" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletPoolKey": { + "description": "CloudletPoolKey uniquely identifies a CloudletPool.", + "type": "object", + "title": "CloudletPool unique key", + "properties": { + "name": { + "description": "CloudletPool Name", + "type": "string", + "x-go-name": "Name" + }, + "organization": { + "description": "Name of the organization this pool belongs to", + "type": "string", + "x-go-name": "Organization" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletPoolMember": { + "description": "CloudletPoolMember is used to add and remove a Cloudlet from a CloudletPool", + "type": "object", + "properties": { + "cloudlet": { + "$ref": "#/definitions/CloudletKey" + }, + "key": { + "$ref": "#/definitions/CloudletPoolKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletProps": { + "description": "Infra properties used to set up cloudlet", + "type": "object", + "properties": { + "organization": { + "description": "Organization", + "type": "string", + "x-go-name": "Organization" + }, + "platform_type": { + "$ref": "#/definitions/PlatformType" + }, + "properties": { + "description": "Single Key-Value pair of env var to be passed to CRM", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/PropertyInfo" + }, + "x-go-name": "Properties" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletRefs": { + "type": "object", + "title": "CloudletRefs track used resources and Clusters instantiated on a Cloudlet. Used resources are compared against max resources for a Cloudlet to determine if resources are available for a new Cluster to be instantiated on the Cloudlet.", + "properties": { + "cluster_insts": { + "description": "Clusters instantiated on the Cloudlet", + "type": "array", + "items": { + "$ref": "#/definitions/ClusterInstRefKey" + }, + "x-go-name": "ClusterInsts" + }, + "k8s_app_insts": { + "description": "K8s apps instantiated on the Cloudlet", + "type": "array", + "items": { + "$ref": "#/definitions/AppInstRefKey" + }, + "x-go-name": "K8SAppInsts" + }, + "key": { + "$ref": "#/definitions/CloudletKey" + }, + "opt_res_used_map": { + "description": "Used Optional Resources", + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "uint32" + }, + "x-go-name": "OptResUsedMap" + }, + "reserved_auto_cluster_ids": { + "description": "Track reservable autoclusterinsts ids in use. This is a bitmap.", + "type": "integer", + "format": "uint64", + "x-go-name": "ReservedAutoClusterIds" + }, + "root_lb_ports": { + "description": "Used ports on root load balancer. Map key is public port, value is a bitmap for the protocol\nbitmap: bit 0: tcp, bit 1: udp", + "x-go-name": "RootLbPorts" + }, + "used_dynamic_ips": { + "description": "Used dynamic IPs", + "type": "integer", + "format": "int32", + "x-go-name": "UsedDynamicIps" + }, + "used_static_ips": { + "description": "Used static IPs", + "type": "string", + "x-go-name": "UsedStaticIps" + }, + "vm_app_insts": { + "description": "VM apps instantiated on the Cloudlet", + "type": "array", + "items": { + "$ref": "#/definitions/AppInstRefKey" + }, + "x-go-name": "VmAppInsts" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletResMap": { + "description": "Optional resource input consists of a resource specifier and clouldkey name", + "type": "object", + "properties": { + "key": { + "$ref": "#/definitions/CloudletKey" + }, + "mapping": { + "description": "Resource mapping info", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "Mapping" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletResourceQuotaProps": { + "type": "object", + "properties": { + "organization": { + "description": "Organization", + "type": "string", + "x-go-name": "Organization" + }, + "platform_type": { + "$ref": "#/definitions/PlatformType" + }, + "properties": { + "description": "Cloudlet resource properties", + "type": "array", + "items": { + "$ref": "#/definitions/InfraResource" + }, + "x-go-name": "Properties" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletResourceUsage": { + "type": "object", + "properties": { + "info": { + "description": "Infra Resource information", + "type": "array", + "items": { + "$ref": "#/definitions/InfraResource" + }, + "x-go-name": "Info" + }, + "infra_usage": { + "description": "Show Infra based usage", + "type": "boolean", + "x-go-name": "InfraUsage" + }, + "key": { + "$ref": "#/definitions/CloudletKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CloudletState": { + "type": "integer", + "format": "int32", + "title": "CloudletState is the state of the Cloudlet.", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/dme-proto" + }, + "ClusterInst": { + "description": "ClusterInst is an instance of a Cluster on a Cloudlet.\nIt is defined by a Cluster, Cloudlet, and Developer key.", + "type": "object", + "title": "Cluster Instance", + "required": ["key"], + "properties": { + "allocated_ip": { + "description": "Allocated IP for dedicated access", + "type": "string", + "x-go-name": "AllocatedIp" + }, + "auto": { + "description": "Auto is set to true when automatically created by back-end (internal use only)", + "type": "boolean", + "x-go-name": "Auto" + }, + "auto_scale_policy": { + "description": "Auto scale policy name", + "type": "string", + "x-go-name": "AutoScalePolicy" + }, + "availability_zone": { + "description": "Optional Resource AZ if any", + "type": "string", + "x-go-name": "AvailabilityZone" + }, + "created_at": { + "$ref": "#/definitions/Timestamp" + }, + "crm_override": { + "$ref": "#/definitions/CRMOverride" + }, + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "deployment": { + "description": "Deployment type (kubernetes or docker)", + "type": "string", + "x-go-name": "Deployment" + }, + "dns_label": { + "description": "DNS label that is unique within the cloudlet and among other AppInsts/ClusterInsts", + "type": "string", + "x-go-name": "DnsLabel" + }, + "errors": { + "description": "Any errors trying to create, update, or delete the ClusterInst on the Cloudlet.", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Errors" + }, + "external_volume_size": { + "description": "Size of external volume to be attached to nodes. This is for the root partition", + "type": "integer", + "format": "uint64", + "x-go-name": "ExternalVolumeSize" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "flavor": { + "$ref": "#/definitions/FlavorKey" + }, + "fqdn": { + "description": "FQDN is a globally unique DNS id for the ClusterInst", + "type": "string", + "x-go-name": "Fqdn" + }, + "image_name": { + "description": "Optional resource specific image to launch", + "type": "string", + "x-go-name": "ImageName" + }, + "ip_access": { + "$ref": "#/definitions/IpAccess" + }, + "key": { + "$ref": "#/definitions/ClusterInstKey" + }, + "liveness": { + "$ref": "#/definitions/Liveness" + }, + "master_node_flavor": { + "description": "Generic flavor for k8s master VM when worker nodes \u003e 0", + "type": "string", + "x-go-name": "MasterNodeFlavor" + }, + "multi_tenant": { + "description": "Multi-tenant kubernetes cluster", + "type": "boolean", + "x-go-name": "MultiTenant" + }, + "networks": { + "description": "networks to connect to", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Networks" + }, + "node_flavor": { + "description": "Cloudlet specific node flavor", + "type": "string", + "x-go-name": "NodeFlavor" + }, + "num_masters": { + "description": "Number of k8s masters (In case of docker deployment, this field is not required)", + "type": "integer", + "format": "uint32", + "x-go-name": "NumMasters" + }, + "num_nodes": { + "description": "Number of k8s nodes (In case of docker deployment, this field is not required)", + "type": "integer", + "format": "uint32", + "x-go-name": "NumNodes" + }, + "opt_res": { + "description": "Optional Resources required by OS flavor if any", + "type": "string", + "x-go-name": "OptRes" + }, + "reservable": { + "description": "If ClusterInst is reservable", + "type": "boolean", + "x-go-name": "Reservable" + }, + "reservation_ended_at": { + "$ref": "#/definitions/Timestamp" + }, + "reserved_by": { + "description": "For reservable EdgeCloud ClusterInsts, the current developer tenant", + "type": "string", + "x-go-name": "ReservedBy" + }, + "resources": { + "$ref": "#/definitions/InfraResources" + }, + "shared_volume_size": { + "description": "Size of an optional shared volume to be mounted on the master", + "type": "integer", + "format": "uint64", + "x-go-name": "SharedVolumeSize" + }, + "skip_crm_cleanup_on_failure": { + "description": "Prevents cleanup of resources on failure within CRM, used for diagnostic purposes", + "type": "boolean", + "x-go-name": "SkipCrmCleanupOnFailure" + }, + "state": { + "$ref": "#/definitions/TrackedState" + }, + "updated_at": { + "$ref": "#/definitions/Timestamp" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "ClusterInstKey": { + "description": "ClusterInstKey uniquely identifies a Cluster Instance (ClusterInst) or Cluster Instance state (ClusterInstInfo).", + "type": "object", + "title": "Cluster Instance unique key", + "properties": { + "cloudlet_key": { + "$ref": "#/definitions/CloudletKey" + }, + "cluster_key": { + "$ref": "#/definitions/ClusterKey" + }, + "organization": { + "description": "Name of Developer organization that this cluster belongs to", + "type": "string", + "x-go-name": "Organization" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "ClusterInstRefKey": { + "description": "ClusterInstRefKey is cluster instance key without cloudlet key.", + "type": "object", + "title": "ClusterInst Ref Key", + "properties": { + "cluster_key": { + "$ref": "#/definitions/ClusterKey" + }, + "organization": { + "description": "Name of Developer organization that this cluster belongs to", + "type": "string", + "x-go-name": "Organization" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "ClusterKey": { + "type": "object", + "title": "ClusterKey uniquely identifies a Cluster.", + "properties": { + "name": { + "description": "Cluster name", + "type": "string", + "x-go-name": "Name" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "ClusterRefs": { + "type": "object", + "title": "ClusterRefs track used resources within a ClusterInst. Each AppInst specifies a set of required resources (Flavor), so tracking resources used by Apps within a Cluster is necessary to determine if enough resources are available for another AppInst to be instantiated on a ClusterInst.", + "properties": { + "apps": { + "description": "App instances in the Cluster Instance", + "type": "array", + "items": { + "$ref": "#/definitions/ClusterRefsAppInstKey" + }, + "x-go-name": "Apps" + }, + "key": { + "$ref": "#/definitions/ClusterInstKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "ClusterRefsAppInstKey": { + "description": "ClusterRefsAppInstKey is an app instance key without the cluster inst key,\nbut including the virtual cluster name. This is used by the ClusterRefs\nto track AppInsts instantiated in the cluster.", + "type": "object", + "title": "ClusterRefs AppInst Key", + "properties": { + "app_key": { + "$ref": "#/definitions/AppKey" + }, + "v_cluster_name": { + "description": "Virtual cluster name", + "type": "string", + "x-go-name": "VClusterName" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CollectionInterval": { + "description": "Collection interval for Influxdb (Specifically used for cq intervals, because cannot gogoproto.casttype to Duration for repeated fields otherwise)", + "type": "object", + "properties": { + "interval": { + "$ref": "#/definitions/Duration" + }, + "retention": { + "$ref": "#/definitions/Duration" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "ConfigFile": { + "description": "ConfigFile", + "type": "object", + "properties": { + "config": { + "description": "Config file contents or URI reference", + "type": "string", + "x-go-name": "Config" + }, + "kind": { + "description": "Kind (type) of config, i.e. envVarsYaml, helmCustomizationYaml", + "type": "string", + "x-go-name": "Kind" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "ContainerInfo": { + "description": "ContainerInfo is infomation about containers running on a VM,", + "type": "object", + "title": "ContainerInfo", + "properties": { + "clusterip": { + "description": "IP within the CNI and is applicable to kubernetes only", + "type": "string", + "x-go-name": "Clusterip" + }, + "name": { + "description": "Name of the container", + "type": "string", + "x-go-name": "Name" + }, + "restarts": { + "description": "Restart count, applicable to kubernetes only", + "type": "integer", + "format": "int64", + "x-go-name": "Restarts" + }, + "status": { + "description": "Runtime status of the container", + "type": "string", + "x-go-name": "Status" + }, + "type": { + "description": "Type can be docker or kubernetes", + "type": "string", + "x-go-name": "Type" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "CreateUser": { + "type": "object", + "required": ["Name"], + "properties": { + "CreatedAt": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "Email": { + "description": "User email", + "type": "string" + }, + "EmailVerified": { + "description": "Email address has been verified", + "type": "boolean", + "readOnly": true + }, + "EnableTOTP": { + "description": "Enable or disable temporary one-time passwords for the account", + "type": "boolean" + }, + "FailedLogins": { + "description": "Number of failed login attempts since last successful login", + "type": "integer", + "format": "int64" + }, + "FamilyName": { + "description": "Family Name", + "type": "string" + }, + "GivenName": { + "description": "Given Name", + "type": "string" + }, + "Iter": { + "type": "integer", + "format": "int64", + "readOnly": true + }, + "LastFailedLogin": { + "description": "Last failed login time", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "LastLogin": { + "description": "Last successful login time", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "Locked": { + "description": "Account is locked", + "type": "boolean", + "readOnly": true + }, + "Metadata": { + "description": "Metadata", + "type": "string" + }, + "Name": { + "description": "User name. Can only contain letters, digits, underscore, period, hyphen. It cannot have leading or trailing spaces or period. It cannot start with hyphen", + "type": "string" + }, + "Nickname": { + "description": "Nick Name", + "type": "string" + }, + "PassCrackTimeSec": { + "type": "number", + "format": "double", + "readOnly": true + }, + "Passhash": { + "type": "string", + "readOnly": true + }, + "Picture": { + "type": "string", + "readOnly": true + }, + "Salt": { + "type": "string", + "readOnly": true + }, + "TOTPSharedKey": { + "type": "string", + "readOnly": true + }, + "UpdatedAt": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "verify": { + "$ref": "#/definitions/EmailRequest" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "DateTime": { + "description": "DateTime is a time but it serializes to ISO8601 format with millis\nIt knows how to read 3 different variations of a RFC3339 date time.\nMost APIs we encounter want either millisecond or second precision times.\nThis just tries to make it worry-free.", + "type": "string", + "format": "date-time", + "x-go-package": "github.com/go-openapi/strfmt" + }, + "DebugRequest": { + "type": "object", + "title": "DebugRequest. Keep everything in one struct to make it easy to send commands without having to change the code.", + "properties": { + "args": { + "description": "Additional arguments for cmd", + "type": "string", + "x-go-name": "Args" + }, + "cmd": { + "description": "Debug command (use \"help\" to see available commands)", + "type": "string", + "x-go-name": "Cmd" + }, + "id": { + "description": "Id used internally", + "type": "integer", + "format": "uint64", + "x-go-name": "Id" + }, + "levels": { + "description": "Comma separated list of debug level names: etcd,api,notify,dmereq,locapi,infra,metrics,upgrade,info,sampled,fedapi", + "type": "string", + "x-go-name": "Levels" + }, + "node": { + "$ref": "#/definitions/NodeKey" + }, + "pretty": { + "description": "if possible, make output pretty", + "type": "boolean", + "x-go-name": "Pretty" + }, + "timeout": { + "$ref": "#/definitions/Duration" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "DeleteType": { + "description": "DeleteType specifies if AppInst can be auto deleted or not\n\n0: `NO_AUTO_DELETE`\n1: `AUTO_DELETE`", + "type": "integer", + "format": "int32", + "title": "DeleteType", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "DeploymentCloudletRequest": { + "type": "object", + "properties": { + "app": { + "$ref": "#/definitions/App" + }, + "dry_run_deploy": { + "description": "Attempt to qualify cloudlet resources for deployment", + "type": "boolean", + "x-go-name": "DryRunDeploy" + }, + "num_nodes": { + "description": "Optional number of worker VMs in dry run K8s Cluster, default = 2", + "type": "integer", + "format": "uint32", + "x-go-name": "NumNodes" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "Device": { + "description": "Device represents a device on the EdgeCloud platform\nWe record when this device first showed up on our platform", + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "first_seen": { + "$ref": "#/definitions/Timestamp" + }, + "key": { + "$ref": "#/definitions/DeviceKey" + }, + "last_seen": { + "$ref": "#/definitions/Timestamp" + }, + "notify_id": { + "description": "Id of client assigned by server (internal use only)", + "type": "integer", + "format": "int64", + "x-go-name": "NotifyId" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "DeviceKey": { + "description": "DeviceKey is an identifier for a given device on the EdgeCloud platform\nIt is defined by a unique id and unique id type\nAnd example of such a device is a MEL device that hosts several applications", + "type": "object", + "properties": { + "unique_id": { + "description": "Unique identification of the client device or user. May be overridden by the server.", + "type": "string", + "x-go-name": "UniqueId" + }, + "unique_id_type": { + "description": "Type of unique ID provided by the client", + "type": "string", + "x-go-name": "UniqueIdType" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "DeviceReport": { + "description": "DeviceReport is a reporting message. It takes a begining and end time\nfor the report", + "type": "object", + "properties": { + "begin": { + "$ref": "#/definitions/Timestamp" + }, + "end": { + "$ref": "#/definitions/Timestamp" + }, + "key": { + "$ref": "#/definitions/DeviceKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "Duration": { + "type": "integer", + "format": "int64", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "EmailRequest": { + "description": "Email request is used for password reset and to resend welcome\nverification email.", + "type": "object", + "properties": { + "email": { + "description": "User's email address", + "type": "string", + "x-go-name": "Email", + "readOnly": true + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "EventMatch": { + "type": "object", + "properties": { + "error": { + "description": "Error substring to match", + "type": "string", + "x-go-name": "Error" + }, + "failed": { + "description": "Failure status on event to match", + "type": "boolean", + "x-go-name": "Failed" + }, + "names": { + "description": "Names of events to match", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Names" + }, + "orgs": { + "description": "Organizations on events to match", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Orgs" + }, + "regions": { + "description": "Regions on events to match", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Regions" + }, + "tags": { + "description": "Tags on events to match", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "Tags" + }, + "types": { + "description": "Types of events to match", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Types" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/cloudcommon/node" + }, + "EventSearch": { + "type": "object", + "properties": { + "allowedorgs": { + "description": "Organizations allowed to access the event", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "AllowedOrgs" + }, + "endage": { + "$ref": "#/definitions/Duration" + }, + "endtime": { + "description": "End time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "EndTime" + }, + "from": { + "description": "Start offset if paging through results", + "type": "integer", + "format": "int64", + "x-go-name": "From" + }, + "limit": { + "description": "Display the last X events", + "type": "integer", + "format": "int64", + "x-go-name": "Limit" + }, + "match": { + "$ref": "#/definitions/EventMatch" + }, + "notmatch": { + "$ref": "#/definitions/EventMatch" + }, + "startage": { + "$ref": "#/definitions/Duration" + }, + "starttime": { + "description": "Start time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "StartTime" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/cloudcommon/node" + }, + "EventTerms": { + "type": "object", + "properties": { + "names": { + "description": "Names of events", + "type": "array", + "items": { + "$ref": "#/definitions/AggrVal" + }, + "x-go-name": "Names" + }, + "orgs": { + "description": "Organizations on events", + "type": "array", + "items": { + "$ref": "#/definitions/AggrVal" + }, + "x-go-name": "Orgs" + }, + "regions": { + "description": "Regions on events", + "type": "array", + "items": { + "$ref": "#/definitions/AggrVal" + }, + "x-go-name": "Regions" + }, + "tagkeys": { + "description": "Tag keys on events", + "type": "array", + "items": { + "$ref": "#/definitions/AggrVal" + }, + "x-go-name": "TagKeys" + }, + "types": { + "description": "Types of events", + "type": "array", + "items": { + "$ref": "#/definitions/AggrVal" + }, + "x-go-name": "Types" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/cloudcommon/node" + }, + "ExecRequest": { + "description": "ExecRequest is a common struct for enabling a connection to execute some work on a container", + "type": "object", + "properties": { + "access_url": { + "description": "Access URL", + "type": "string", + "x-go-name": "AccessUrl" + }, + "answer": { + "description": "Answer", + "type": "string", + "x-go-name": "Answer" + }, + "app_inst_key": { + "$ref": "#/definitions/AppInstKey" + }, + "cmd": { + "$ref": "#/definitions/RunCmd" + }, + "console": { + "$ref": "#/definitions/RunVMConsole" + }, + "container_id": { + "description": "ContainerId is the name or ID of the target container, if applicable", + "type": "string", + "x-go-name": "ContainerId" + }, + "edge_turn_addr": { + "description": "EdgeTurn Server Address", + "type": "string", + "x-go-name": "EdgeTurnAddr" + }, + "err": { + "description": "Any error message", + "type": "string", + "x-go-name": "Err" + }, + "log": { + "$ref": "#/definitions/ShowLog" + }, + "offer": { + "description": "Offer", + "type": "string", + "x-go-name": "Offer" + }, + "timeout": { + "$ref": "#/definitions/Duration" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "FederationConfig": { + "description": "Federation config associated with the cloudlet", + "type": "object", + "properties": { + "federation_name": { + "description": "Federation name", + "type": "string", + "x-go-name": "FederationName" + }, + "partner_federation_addr": { + "description": "Partner federation address", + "type": "string", + "x-go-name": "PartnerFederationAddr" + }, + "partner_federation_id": { + "description": "Partner federation ID", + "type": "string", + "x-go-name": "PartnerFederationId" + }, + "self_federation_id": { + "description": "Self federation ID", + "type": "string", + "x-go-name": "SelfFederationId" + }, + "zone_country_code": { + "description": "Cloudlet zone country code", + "type": "string", + "x-go-name": "ZoneCountryCode" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "Flavor": { + "description": "To put it simply, a flavor is an available hardware configuration for a server.\nIt defines the size of a virtual server that can be launched.", + "type": "object", + "title": "Flavors define the compute, memory, and storage capacity of computing instances.", + "properties": { + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "disk": { + "description": "Amount of disk space in gigabytes", + "type": "integer", + "format": "uint64", + "x-go-name": "Disk" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "key": { + "$ref": "#/definitions/FlavorKey" + }, + "opt_res_map": { + "description": "Optional Resources request, key = gpu\nform: $resource=$kind:[$alias]$count ex: optresmap=gpu=vgpu:nvidia-63:1", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "OptResMap" + }, + "ram": { + "description": "RAM in megabytes", + "type": "integer", + "format": "uint64", + "x-go-name": "Ram" + }, + "vcpus": { + "description": "Number of virtual CPUs", + "type": "integer", + "format": "uint64", + "x-go-name": "Vcpus" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "FlavorInfo": { + "description": "Flavor details from the Cloudlet", + "type": "object", + "properties": { + "disk": { + "description": "Amount of disk in GB on the Cloudlet", + "type": "integer", + "format": "uint64", + "x-go-name": "Disk" + }, + "name": { + "description": "Name of the flavor on the Cloudlet", + "type": "string", + "x-go-name": "Name" + }, + "prop_map": { + "description": "OS Flavor Properties, if any", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "PropMap" + }, + "ram": { + "description": "Ram in MB on the Cloudlet", + "type": "integer", + "format": "uint64", + "x-go-name": "Ram" + }, + "vcpus": { + "description": "Number of VCPU cores on the Cloudlet", + "type": "integer", + "format": "uint64", + "x-go-name": "Vcpus" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "FlavorKey": { + "description": "FlavorKey uniquely identifies a Flavor.", + "type": "object", + "title": "Flavor", + "properties": { + "name": { + "description": "Flavor name", + "type": "string", + "x-go-name": "Name" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "FlavorMatch": { + "type": "object", + "properties": { + "availability_zone": { + "description": "availability zone for optional resources if any", + "type": "string", + "x-go-name": "AvailabilityZone" + }, + "flavor_name": { + "description": "Flavor name to lookup", + "type": "string", + "x-go-name": "FlavorName" + }, + "key": { + "$ref": "#/definitions/CloudletKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "FlowRateLimitAlgorithm": { + "type": "integer", + "format": "int32", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "FlowRateLimitSettings": { + "type": "object", + "required": ["key"], + "properties": { + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "key": { + "$ref": "#/definitions/FlowRateLimitSettingsKey" + }, + "settings": { + "$ref": "#/definitions/FlowSettings" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "FlowRateLimitSettingsKey": { + "type": "object", + "properties": { + "flow_settings_name": { + "description": "Unique name for FlowRateLimitSettings (there can be multiple FlowSettings per RateLimitSettingsKey)", + "type": "string", + "x-go-name": "FlowSettingsName" + }, + "rate_limit_key": { + "$ref": "#/definitions/RateLimitSettingsKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "FlowSettings": { + "type": "object", + "properties": { + "burst_size": { + "description": "Burst size for flow rate limiting (required for TokenBucketAlgorithm)", + "type": "integer", + "format": "int64", + "x-go-name": "BurstSize" + }, + "flow_algorithm": { + "$ref": "#/definitions/FlowRateLimitAlgorithm" + }, + "reqs_per_second": { + "description": "Requests per second for flow rate limiting", + "type": "number", + "format": "double", + "x-go-name": "ReqsPerSecond" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "GPUConfig": { + "type": "object", + "properties": { + "driver": { + "$ref": "#/definitions/GPUDriverKey" + }, + "license_config": { + "description": "Cloudlet specific license config to setup license (will be stored in secure storage)", + "type": "string", + "x-go-name": "LicenseConfig" + }, + "license_config_md5sum": { + "description": "Cloudlet specific license config md5sum, to ensure integrity of license config", + "type": "string", + "x-go-name": "LicenseConfigMd5Sum" + }, + "properties": { + "description": "Properties to identify specifics of GPU", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "Properties" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "GPUDriver": { + "type": "object", + "properties": { + "builds": { + "description": "List of GPU driver build", + "type": "array", + "items": { + "$ref": "#/definitions/GPUDriverBuild" + }, + "x-go-name": "Builds" + }, + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "ignore_state": { + "description": "Ignore state will ignore any action in-progress on the GPU driver", + "type": "boolean", + "x-go-name": "IgnoreState" + }, + "key": { + "$ref": "#/definitions/GPUDriverKey" + }, + "license_config": { + "description": "License config to setup license (will be stored in secure storage)", + "type": "string", + "x-go-name": "LicenseConfig" + }, + "license_config_md5sum": { + "description": "License config md5sum, to ensure integrity of license config", + "type": "string", + "x-go-name": "LicenseConfigMd5Sum" + }, + "license_config_storage_path": { + "description": "GPU driver license config storage path", + "type": "string", + "x-go-name": "LicenseConfigStoragePath" + }, + "properties": { + "description": "Additional properties associated with GPU driver build", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "Properties", + "example": "license server information, driver release date, etc" + }, + "state": { + "description": "State to figure out if any action on the GPU driver is in-progress", + "type": "string", + "x-go-name": "State" + }, + "storage_bucket_name": { + "description": "GPU driver storage bucket name", + "type": "string", + "x-go-name": "StorageBucketName" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "GPUDriverBuild": { + "type": "object", + "properties": { + "driver_path": { + "description": "Path where the driver package is located, if it is authenticated path,\nthen credentials must be passed as part of URL (one-time download path)", + "type": "string", + "x-go-name": "DriverPath" + }, + "driver_path_creds": { + "description": "Optional credentials (username:password) to access driver path", + "type": "string", + "x-go-name": "DriverPathCreds" + }, + "hypervisor_info": { + "description": "Info on hypervisor supported by vGPU driver", + "type": "string", + "x-go-name": "HypervisorInfo" + }, + "kernel_version": { + "description": "Kernel Version supported by GPU driver build", + "type": "string", + "x-go-name": "KernelVersion" + }, + "md5sum": { + "description": "Driver package md5sum to ensure package is not corrupted", + "type": "string", + "x-go-name": "Md5Sum" + }, + "name": { + "description": "Unique identifier key", + "type": "string", + "x-go-name": "Name" + }, + "operating_system": { + "$ref": "#/definitions/OSType" + }, + "storage_path": { + "description": "GPU driver build storage path", + "type": "string", + "x-go-name": "StoragePath" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "GPUDriverBuildMember": { + "type": "object", + "properties": { + "build": { + "$ref": "#/definitions/GPUDriverBuild" + }, + "ignore_state": { + "description": "Ignore state will ignore any action in-progress on the GPU driver", + "type": "boolean", + "x-go-name": "IgnoreState" + }, + "key": { + "$ref": "#/definitions/GPUDriverKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "GPUDriverKey": { + "description": "GPUDriverKey uniquely identifies a GPU driver", + "type": "object", + "title": "GPU Driver Key", + "properties": { + "name": { + "description": "Name of the driver", + "type": "string", + "x-go-name": "Name" + }, + "organization": { + "description": "Organization to which the driver belongs to", + "type": "string", + "x-go-name": "Organization" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "HealthCheck": { + "description": "Health check status gets set by external, or rootLB health check", + "type": "integer", + "format": "int32", + "title": "Health check status", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/dme-proto" + }, + "IdleReservableClusterInsts": { + "description": "Parameters for selecting reservable ClusterInsts to delete", + "type": "object", + "properties": { + "idle_time": { + "$ref": "#/definitions/Duration" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "ImageType": { + "type": "integer", + "format": "int32", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "InfraApiAccess": { + "description": "InfraApiAccess is the type of access available to Infra API endpoint\n\n0: `DIRECT_ACCESS`\n1: `RESTRICTED_ACCESS`", + "type": "integer", + "format": "int32", + "title": "Infra API Access", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "InfraConfig": { + "description": "Infra specific configuration used for Cloudlet deployments", + "type": "object", + "properties": { + "external_network_name": { + "description": "Infra specific external network name", + "type": "string", + "x-go-name": "ExternalNetworkName" + }, + "flavor_name": { + "description": "Infra specific flavor name", + "type": "string", + "x-go-name": "FlavorName" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "InfraResource": { + "description": "InfraResource is information about cloudlet infra resource.", + "type": "object", + "title": "InfraResource", + "properties": { + "alert_threshold": { + "description": "Generate alert when more than threshold percentage of resource is used", + "type": "integer", + "format": "int32", + "x-go-name": "AlertThreshold" + }, + "description": { + "description": "Resource description", + "type": "string", + "x-go-name": "Description" + }, + "infra_max_value": { + "description": "Resource infra max value", + "type": "integer", + "format": "uint64", + "x-go-name": "InfraMaxValue" + }, + "name": { + "description": "Resource name", + "type": "string", + "x-go-name": "Name" + }, + "quota_max_value": { + "description": "Resource quota max value", + "type": "integer", + "format": "uint64", + "x-go-name": "QuotaMaxValue" + }, + "units": { + "description": "Resource units", + "type": "string", + "x-go-name": "Units" + }, + "value": { + "description": "Resource value", + "type": "integer", + "format": "uint64", + "x-go-name": "Value" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "InfraResources": { + "description": "InfraResources is infomation about infrastructure resources.", + "type": "object", + "title": "InfraResources", + "properties": { + "vms": { + "description": "Virtual machine resources info", + "type": "array", + "items": { + "$ref": "#/definitions/VmInfo" + }, + "x-go-name": "Vms" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "InfraResourcesSnapshot": { + "description": "InfraResourcesSnapshot is snapshot of information about cloudlet infra resources.", + "type": "object", + "title": "InfraResourcesSnapshot", + "properties": { + "cluster_insts": { + "description": "List of clusterinsts this resources snapshot represent", + "type": "array", + "items": { + "$ref": "#/definitions/ClusterInstRefKey" + }, + "x-go-name": "ClusterInsts" + }, + "info": { + "description": "Infra Resource information", + "type": "array", + "items": { + "$ref": "#/definitions/InfraResource" + }, + "x-go-name": "Info" + }, + "k8s_app_insts": { + "description": "List of k8s appinsts this resources snapshot represent", + "type": "array", + "items": { + "$ref": "#/definitions/AppInstRefKey" + }, + "x-go-name": "K8SAppInsts" + }, + "platform_vms": { + "description": "Virtual machine resources info", + "type": "array", + "items": { + "$ref": "#/definitions/VmInfo" + }, + "x-go-name": "PlatformVms" + }, + "vm_app_insts": { + "description": "List of vm appinsts this resources snapshot represent", + "type": "array", + "items": { + "$ref": "#/definitions/AppInstRefKey" + }, + "x-go-name": "VmAppInsts" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "IpAccess": { + "description": "IpAccess indicates the type of RootLB that Developer requires for their App\n\n0: `IP_ACCESS_UNKNOWN`\n1: `IP_ACCESS_DEDICATED`\n3: `IP_ACCESS_SHARED`", + "type": "integer", + "format": "int32", + "title": "IpAccess Options", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "IpAddr": { + "description": "IpAddr is an address for a VM which may have an external and\ninternal component. Internal and external is with respect to the VM\nand are are often the same unless a natted or floating IP is used. If\ninternalIP is not reported it is the same as the ExternalIP.", + "type": "object", + "properties": { + "externalIp": { + "description": "External IP address", + "type": "string", + "x-go-name": "ExternalIp" + }, + "internalIp": { + "description": "Internal IP address", + "type": "string", + "x-go-name": "InternalIp" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "IpSupport": { + "description": "Static IP support indicates a set of static public IPs are available for use, and managed by the Controller. Dynamic indicates the Cloudlet uses a DHCP server to provide public IP addresses, and the controller has no control over which IPs are assigned.\n\n0: `IP_SUPPORT_UNKNOWN`\n1: `IP_SUPPORT_STATIC`\n2: `IP_SUPPORT_DYNAMIC`", + "type": "integer", + "format": "int32", + "title": "Type of public IP support", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "LProto": { + "description": "LProto indicates which protocol to use for accessing an application on a particular port. This is required by Kubernetes for port mapping.\n\n0: `L_PROTO_UNKNOWN`\n1: `L_PROTO_TCP`\n2: `L_PROTO_UDP`", + "type": "integer", + "format": "int32", + "title": "Layer4 Protocol", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/dme-proto" + }, + "Liveness": { + "description": "Liveness indicates if an object was created statically via an external API call, or dynamically via an internal algorithm.\n\n0: `LIVENESS_UNKNOWN`\n1: `LIVENESS_STATIC`\n2: `LIVENESS_DYNAMIC`\n3: `LIVENESS_AUTOPROV`", + "type": "integer", + "format": "int32", + "title": "Liveness Options", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "Loc": { + "description": "GPS Location", + "type": "object", + "properties": { + "altitude": { + "description": "On android only lat and long are guaranteed to be supplied\nAltitude in meters", + "type": "number", + "format": "double", + "x-go-name": "Altitude" + }, + "course": { + "description": "Course (IOS) / bearing (Android) (degrees east relative to true north)", + "type": "number", + "format": "double", + "x-go-name": "Course" + }, + "horizontal_accuracy": { + "description": "Horizontal accuracy (radius in meters)", + "type": "number", + "format": "double", + "x-go-name": "HorizontalAccuracy" + }, + "latitude": { + "description": "Latitude in WGS 84 coordinates", + "type": "number", + "format": "double", + "x-go-name": "Latitude" + }, + "longitude": { + "description": "Longitude in WGS 84 coordinates", + "type": "number", + "format": "double", + "x-go-name": "Longitude" + }, + "speed": { + "description": "Speed (IOS) / velocity (Android) (meters/sec)", + "type": "number", + "format": "double", + "x-go-name": "Speed" + }, + "timestamp": { + "$ref": "#/definitions/Timestamp" + }, + "vertical_accuracy": { + "description": "Vertical accuracy (meters)", + "type": "number", + "format": "double", + "x-go-name": "VerticalAccuracy" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/dme-proto" + }, + "MaintenanceState": { + "description": "Maintenance allows for planned downtimes of Cloudlets.\nThese states involve message exchanges between the Controller,\nthe AutoProv service, and the CRM. Certain states are only set\nby certain actors.", + "type": "integer", + "format": "int32", + "title": "Cloudlet Maintenance States", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/dme-proto" + }, + "MaxReqsRateLimitAlgorithm": { + "type": "integer", + "format": "int32", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "MaxReqsRateLimitSettings": { + "type": "object", + "required": ["key"], + "properties": { + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "key": { + "$ref": "#/definitions/MaxReqsRateLimitSettingsKey" + }, + "settings": { + "$ref": "#/definitions/MaxReqsSettings" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "MaxReqsRateLimitSettingsKey": { + "type": "object", + "properties": { + "max_reqs_settings_name": { + "description": "Unique name for MaxReqsRateLimitSettings (there can be multiple MaxReqsSettings per RateLimitSettingsKey)", + "type": "string", + "x-go-name": "MaxReqsSettingsName" + }, + "rate_limit_key": { + "$ref": "#/definitions/RateLimitSettingsKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "MaxReqsSettings": { + "type": "object", + "properties": { + "interval": { + "$ref": "#/definitions/Duration" + }, + "max_reqs_algorithm": { + "$ref": "#/definitions/MaxReqsRateLimitAlgorithm" + }, + "max_requests": { + "description": "Maximum number of requests for the given Interval", + "type": "integer", + "format": "int64", + "x-go-name": "MaxRequests" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "Network": { + "description": "Network defines additional networks which can be optionally assigned to a cloudlet key and used on a cluster instance", + "type": "object", + "properties": { + "connection_type": { + "$ref": "#/definitions/NetworkConnectionType" + }, + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "key": { + "$ref": "#/definitions/NetworkKey" + }, + "routes": { + "description": "List of routes", + "type": "array", + "items": { + "$ref": "#/definitions/Route" + }, + "x-go-name": "Routes" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "NetworkConnectionType": { + "description": "NetworkConnectionType is the supported list of network types to be optionally added to a cluster instance\n\n0: `UNDEFINED`\n1: `CONNECT_TO_LOAD_BALANCER`\n2: `CONNECT_TO_CLUSTER_NODES`\n3: `CONNECT_TO_ALL`", + "type": "integer", + "format": "int32", + "title": "Network Connection Type", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "NetworkKey": { + "type": "object", + "properties": { + "cloudlet_key": { + "$ref": "#/definitions/CloudletKey" + }, + "name": { + "description": "Network Name", + "type": "string", + "x-go-name": "Name" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "Node": { + "type": "object", + "title": "Node identifies an Edge Cloud service.", + "properties": { + "build_author": { + "description": "Build Author", + "type": "string", + "x-go-name": "BuildAuthor" + }, + "build_date": { + "description": "Build Date", + "type": "string", + "x-go-name": "BuildDate" + }, + "build_head": { + "description": "Build Head Version", + "type": "string", + "x-go-name": "BuildHead" + }, + "build_master": { + "description": "Build Master Version", + "type": "string", + "x-go-name": "BuildMaster" + }, + "container_version": { + "description": "Docker edge-cloud container version which node instance use", + "type": "string", + "x-go-name": "ContainerVersion" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "hostname": { + "description": "Hostname", + "type": "string", + "x-go-name": "Hostname" + }, + "internal_pki": { + "description": "Internal PKI Config", + "type": "string", + "x-go-name": "InternalPki" + }, + "key": { + "$ref": "#/definitions/NodeKey" + }, + "notify_id": { + "description": "Id of client assigned by server (internal use only)", + "type": "integer", + "format": "int64", + "x-go-name": "NotifyId" + }, + "properties": { + "description": "Additional properties", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "Properties" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "NodeInfo": { + "description": "NodeInfo is information about a Kubernetes node", + "type": "object", + "title": "NodeInfo", + "properties": { + "allocatable": { + "description": "Maximum allocatable resources on the node (capacity - overhead)", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/Udec64" + }, + "x-go-name": "Allocatable" + }, + "capacity": { + "description": "Capacity of underlying resources on the node", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/Udec64" + }, + "x-go-name": "Capacity" + }, + "name": { + "description": "Node name", + "type": "string", + "x-go-name": "Name" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "NodeKey": { + "description": "NodeKey uniquely identifies a DME or CRM node", + "type": "object", + "properties": { + "cloudlet_key": { + "$ref": "#/definitions/CloudletKey" + }, + "name": { + "description": "Name or hostname of node", + "type": "string", + "x-go-name": "Name" + }, + "region": { + "description": "Region the node is in", + "type": "string", + "x-go-name": "Region" + }, + "type": { + "description": "Node type", + "type": "string", + "x-go-name": "Type" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "OSAZone": { + "type": "object", + "properties": { + "name": { + "description": "OpenStack availability zone name", + "type": "string", + "x-go-name": "Name" + }, + "status": { + "description": "OpenStack availability zone status", + "type": "string", + "x-go-name": "Status" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "OSImage": { + "type": "object", + "properties": { + "disk_format": { + "description": "format qcow2, img, etc", + "type": "string", + "x-go-name": "DiskFormat" + }, + "name": { + "description": "image name", + "type": "string", + "x-go-name": "Name" + }, + "properties": { + "description": "image properties/metadata", + "type": "string", + "x-go-name": "Properties" + }, + "tags": { + "description": "optional tags present on image", + "type": "string", + "x-go-name": "Tags" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "OSType": { + "description": "OSType is the type of the Operator System\n\n0: `Linux`\n1: `Windows`\n20: `Others`", + "type": "integer", + "format": "int32", + "title": "Operating System Type", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "OperationTimeLimits": { + "description": "Time limits for cloudlet create, update and delete operations", + "type": "object", + "title": "Operation time limits", + "properties": { + "create_app_inst_timeout": { + "$ref": "#/definitions/Duration" + }, + "create_cluster_inst_timeout": { + "$ref": "#/definitions/Duration" + }, + "delete_app_inst_timeout": { + "$ref": "#/definitions/Duration" + }, + "delete_cluster_inst_timeout": { + "$ref": "#/definitions/Duration" + }, + "update_app_inst_timeout": { + "$ref": "#/definitions/Duration" + }, + "update_cluster_inst_timeout": { + "$ref": "#/definitions/Duration" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "OperatorCode": { + "description": "OperatorCode maps a carrier code to an Operator organization name", + "type": "object", + "properties": { + "code": { + "description": "MCC plus MNC code, or custom carrier code designation.", + "type": "string", + "x-go-name": "Code" + }, + "organization": { + "description": "Operator Organization name", + "type": "string", + "x-go-name": "Organization" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "Organization": { + "type": "object", + "required": ["Name"], + "properties": { + "Address": { + "description": "Organization address", + "type": "string" + }, + "CreatedAt": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "DeleteInProgress": { + "description": "Delete of this organization is in progress", + "type": "boolean", + "readOnly": true + }, + "EdgeboxOnly": { + "description": "Edgebox only operator organization", + "type": "boolean", + "readOnly": true + }, + "Name": { + "description": "Organization name. Can only contain letters, digits, underscore, period, hyphen. It cannot have leading or trailing spaces or period. It cannot start with hyphen", + "type": "string" + }, + "Parent": { + "type": "string", + "readOnly": true + }, + "Phone": { + "description": "Organization phone number", + "type": "string" + }, + "PublicImages": { + "description": "Images are made available to other organization", + "type": "boolean", + "readOnly": true + }, + "Type": { + "description": "Organization type: \"developer\" or \"operator\"", + "type": "string" + }, + "UpdatedAt": { + "type": "string", + "format": "date-time", + "readOnly": true + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "PasswordReset": { + "type": "object", + "required": ["token", "password"], + "properties": { + "password": { + "description": "User's new password", + "type": "string", + "x-go-name": "Password" + }, + "token": { + "description": "Authentication token", + "type": "string", + "x-go-name": "Token" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "PlatformConfig": { + "description": "Platform specific configuration required for Cloudlet management", + "type": "object", + "properties": { + "access_api_addr": { + "description": "controller access API address", + "type": "string", + "x-go-name": "AccessApiAddr" + }, + "app_dns_root": { + "description": "App domain name root", + "type": "string", + "x-go-name": "AppDnsRoot" + }, + "cache_dir": { + "description": "cache dir", + "type": "string", + "x-go-name": "CacheDir" + }, + "chef_client_interval": { + "$ref": "#/definitions/Duration" + }, + "chef_server_path": { + "description": "Path to Chef Server", + "type": "string", + "x-go-name": "ChefServerPath" + }, + "cleanup_mode": { + "description": "Internal cleanup flag", + "type": "boolean", + "x-go-name": "CleanupMode" + }, + "cloudlet_vm_image_path": { + "description": "Path to platform base image", + "type": "string", + "x-go-name": "CloudletVmImagePath" + }, + "commercial_certs": { + "description": "Get certs from vault or generate your own for the root load balancer", + "type": "boolean", + "x-go-name": "CommercialCerts" + }, + "container_registry_path": { + "description": "Path to Docker registry holding edge-cloud image", + "type": "string", + "x-go-name": "ContainerRegistryPath" + }, + "crm_access_private_key": { + "description": "crm access private key", + "type": "string", + "x-go-name": "CrmAccessPrivateKey" + }, + "deployment_tag": { + "description": "Deployment Tag", + "type": "string", + "x-go-name": "DeploymentTag" + }, + "env_var": { + "description": "Environment variables", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "EnvVar" + }, + "notify_ctrl_addrs": { + "description": "Address of controller notify port (can be multiple of these)", + "type": "string", + "x-go-name": "NotifyCtrlAddrs" + }, + "platform_tag": { + "description": "Tag of edge-cloud image", + "type": "string", + "x-go-name": "PlatformTag" + }, + "region": { + "description": "Region", + "type": "string", + "x-go-name": "Region" + }, + "secondary_crm_access_private_key": { + "description": "secondary crm access private key", + "type": "string", + "x-go-name": "SecondaryCrmAccessPrivateKey" + }, + "span": { + "description": "Span string", + "type": "string", + "x-go-name": "Span" + }, + "test_mode": { + "description": "Internal Test flag", + "type": "boolean", + "x-go-name": "TestMode" + }, + "thanos_recv_addr": { + "description": "Thanos Receive remote write address", + "type": "string", + "x-go-name": "ThanosRecvAddr" + }, + "tls_ca_file": { + "description": "TLS ca file", + "type": "string", + "x-go-name": "TlsCaFile" + }, + "tls_cert_file": { + "description": "TLS cert file", + "type": "string", + "x-go-name": "TlsCertFile" + }, + "tls_key_file": { + "description": "TLS key file", + "type": "string", + "x-go-name": "TlsKeyFile" + }, + "use_vault_pki": { + "description": "Use Vault certs and CAs for internal TLS communication", + "type": "boolean", + "x-go-name": "UseVaultPki" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "PlatformType": { + "description": "PlatformType is the supported list of cloudlet types\n\n0: `PLATFORM_TYPE_FAKE`\n1: `PLATFORM_TYPE_DIND`\n2: `PLATFORM_TYPE_OPENSTACK`\n3: `PLATFORM_TYPE_AZURE`\n4: `PLATFORM_TYPE_GCP`\n5: `PLATFORM_TYPE_EDGEBOX`\n6: `PLATFORM_TYPE_FAKEINFRA`\n7: `PLATFORM_TYPE_VSPHERE`\n8: `PLATFORM_TYPE_AWS_EKS`\n9: `PLATFORM_TYPE_VM_POOL`\n10: `PLATFORM_TYPE_AWS_EC2`\n11: `PLATFORM_TYPE_VCD`\n12: `PLATFORM_TYPE_K8S_BARE_METAL`\n13: `PLATFORM_TYPE_KIND`\n14: `PLATFORM_TYPE_KINDINFRA`\n15: `PLATFORM_TYPE_FAKE_SINGLE_CLUSTER`\n16: `PLATFORM_TYPE_FEDERATION`\n17: `PLATFORM_TYPE_FAKE_VM_POOL`", + "type": "integer", + "format": "int32", + "title": "Platform Type", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "PolicyKey": { + "type": "object", + "properties": { + "name": { + "description": "Policy name", + "type": "string", + "x-go-name": "Name" + }, + "organization": { + "description": "Name of the organization for the cluster that this policy will apply to", + "type": "string", + "x-go-name": "Organization" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "PowerState": { + "description": "Power State of the AppInst\n\n0: `POWER_STATE_UNKNOWN`\n1: `POWER_ON_REQUESTED`\n2: `POWERING_ON`\n3: `POWER_ON`\n4: `POWER_OFF_REQUESTED`\n5: `POWERING_OFF`\n6: `POWER_OFF`\n7: `REBOOT_REQUESTED`\n8: `REBOOTING`\n9: `REBOOT`\n10: `POWER_STATE_ERROR`", + "type": "integer", + "format": "int32", + "title": "Power State", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "PropertyInfo": { + "type": "object", + "properties": { + "description": { + "description": "Description of the property", + "type": "string", + "x-go-name": "Description" + }, + "internal": { + "description": "Is the property internal, not to be set by Operator", + "type": "boolean", + "x-go-name": "Internal" + }, + "mandatory": { + "description": "Is the property mandatory", + "type": "boolean", + "x-go-name": "Mandatory" + }, + "name": { + "description": "Name of the property", + "type": "string", + "x-go-name": "Name" + }, + "secret": { + "description": "Is the property a secret value, will be hidden", + "type": "boolean", + "x-go-name": "Secret" + }, + "value": { + "description": "Default value of the property", + "type": "string", + "x-go-name": "Value" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "QosSessionProfile": { + "description": "The selected profile name will be included\nas the \"qos\" value in the qos-senf/v1/sessions POST.", + "type": "integer", + "format": "int32", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "RateLimitSettings": { + "type": "object", + "properties": { + "flow_settings": { + "description": "Map of FlowSettings (key: FlowSettingsName, value: FlowSettings)", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/FlowSettings" + }, + "x-go-name": "FlowSettings" + }, + "key": { + "$ref": "#/definitions/RateLimitSettingsKey" + }, + "max_reqs_settings": { + "description": "Map of MaxReqsSettings (key: MaxReqsSettingsName, value: MaxReqsSettings)", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/MaxReqsSettings" + }, + "x-go-name": "MaxReqsSettings" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "RateLimitSettingsKey": { + "type": "object", + "properties": { + "api_endpoint_type": { + "$ref": "#/definitions/ApiEndpointType" + }, + "api_name": { + "description": "Name of API (eg. CreateApp or RegisterClient) (Use \"Global\" if not a specific API)", + "type": "string", + "x-go-name": "ApiName" + }, + "rate_limit_target": { + "$ref": "#/definitions/RateLimitTarget" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "RateLimitTarget": { + "type": "integer", + "format": "int32", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "RegionAlert": { + "type": "object", + "required": ["Region"], + "properties": { + "Alert": { + "$ref": "#/definitions/Alert" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAlertPolicy": { + "type": "object", + "required": ["Region"], + "properties": { + "AlertPolicy": { + "$ref": "#/definitions/AlertPolicy" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionApp": { + "type": "object", + "required": ["Region"], + "properties": { + "App": { + "$ref": "#/definitions/App" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAppAlertPolicy": { + "type": "object", + "required": ["Region"], + "properties": { + "AppAlertPolicy": { + "$ref": "#/definitions/AppAlertPolicy" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAppAutoProvPolicy": { + "type": "object", + "required": ["Region"], + "properties": { + "AppAutoProvPolicy": { + "$ref": "#/definitions/AppAutoProvPolicy" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAppInst": { + "type": "object", + "required": ["Region"], + "properties": { + "AppInst": { + "$ref": "#/definitions/AppInst" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAppInstClientKey": { + "type": "object", + "required": ["Region"], + "properties": { + "AppInstClientKey": { + "$ref": "#/definitions/AppInstClientKey" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAppInstKey": { + "type": "object", + "required": ["Region"], + "properties": { + "AppInstKey": { + "$ref": "#/definitions/AppInstKey" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAppInstLatency": { + "type": "object", + "required": ["Region"], + "properties": { + "AppInstLatency": { + "$ref": "#/definitions/AppInstLatency" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAppInstMetrics": { + "type": "object", + "properties": { + "AppInst": { + "$ref": "#/definitions/AppInstKey" + }, + "AppInsts": { + "description": "Application instances to filter for metrics", + "type": "array", + "items": { + "$ref": "#/definitions/AppInstKey" + } + }, + "Limit": { + "description": "Display the last X metrics", + "type": "integer", + "format": "int64" + }, + "NumSamples": { + "description": "Display X samples spaced out evenly over start and end times", + "type": "integer", + "format": "int64" + }, + "Region": { + "description": "Region name", + "type": "string" + }, + "Selector": { + "description": "Comma separated list of metrics to view. Available metrics: utilization, network, ipusage", + "type": "string" + }, + "endage": { + "$ref": "#/definitions/Duration" + }, + "endtime": { + "description": "End time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "EndTime" + }, + "startage": { + "$ref": "#/definitions/Duration" + }, + "starttime": { + "description": "Start time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "StartTime" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAppInstRefs": { + "type": "object", + "required": ["Region"], + "properties": { + "AppInstRefs": { + "$ref": "#/definitions/AppInstRefs" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAppInstUsage": { + "type": "object", + "properties": { + "AppInst": { + "$ref": "#/definitions/AppInstKey" + }, + "EndTime": { + "description": "Time up to which to display stats", + "type": "string", + "format": "date-time" + }, + "Region": { + "description": "Region name", + "type": "string" + }, + "StartTime": { + "description": "Time to start displaying stats from", + "type": "string", + "format": "date-time" + }, + "VmOnly": { + "description": "Show only VM-based apps", + "type": "boolean" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAutoProvPolicy": { + "type": "object", + "required": ["Region"], + "properties": { + "AutoProvPolicy": { + "$ref": "#/definitions/AutoProvPolicy" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAutoProvPolicyCloudlet": { + "type": "object", + "required": ["Region"], + "properties": { + "AutoProvPolicyCloudlet": { + "$ref": "#/definitions/AutoProvPolicyCloudlet" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionAutoScalePolicy": { + "type": "object", + "required": ["Region"], + "properties": { + "AutoScalePolicy": { + "$ref": "#/definitions/AutoScalePolicy" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionClientApiUsageMetrics": { + "type": "object", + "properties": { + "AppInst": { + "$ref": "#/definitions/AppInstKey" + }, + "DmeCloudlet": { + "description": "Cloudlet name where DME is running", + "type": "string" + }, + "DmeCloudletOrg": { + "description": "Operator organization where DME is running", + "type": "string" + }, + "Limit": { + "description": "Display the last X metrics", + "type": "integer", + "format": "int64" + }, + "Method": { + "description": "API call method, one of: FindCloudlet, PlatformFindCloudlet, RegisterClient, VerifyLocation", + "type": "string" + }, + "NumSamples": { + "description": "Display X samples spaced out evenly over start and end times", + "type": "integer", + "format": "int64" + }, + "Region": { + "description": "Region name", + "type": "string" + }, + "Selector": { + "description": "Comma separated list of metrics to view. Available metrics: utilization, network, ipusage", + "type": "string" + }, + "endage": { + "$ref": "#/definitions/Duration" + }, + "endtime": { + "description": "End time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "EndTime" + }, + "startage": { + "$ref": "#/definitions/Duration" + }, + "starttime": { + "description": "Start time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "StartTime" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionClientAppUsageMetrics": { + "type": "object", + "properties": { + "AppInst": { + "$ref": "#/definitions/AppInstKey" + }, + "DataNetworkType": { + "description": "Data network type used by client device. Can be used for selectors: latency", + "type": "string" + }, + "DeviceCarrier": { + "description": "Device carrier. Can be used for selectors: latency, deviceinfo", + "type": "string" + }, + "DeviceModel": { + "description": "Device model. Can be used for selectors: deviceinfo", + "type": "string" + }, + "DeviceOs": { + "description": "Device operating system. Can be used for selectors: deviceinfo", + "type": "string" + }, + "Limit": { + "description": "Display the last X metrics", + "type": "integer", + "format": "int64" + }, + "LocationTile": { + "description": "Provides the range of GPS coordinates for the location tile/square.\nFormat is: 'LocationUnderLongitude,LocationUnderLatitude_LocationOverLongitude,LocationOverLatitude_LocationTileLength'.\nLocationUnder are the GPS coordinates of the corner closest to (0,0) of the location tile.\nLocationOver are the GPS coordinates of the corner farthest from (0,0) of the location tile.\nLocationTileLength is the length (in kilometers) of one side of the location tile square", + "type": "string" + }, + "NumSamples": { + "description": "Display X samples spaced out evenly over start and end times", + "type": "integer", + "format": "int64" + }, + "Region": { + "description": "Region name", + "type": "string" + }, + "Selector": { + "description": "Comma separated list of metrics to view. Available metrics: utilization, network, ipusage", + "type": "string" + }, + "SignalStrength": { + "type": "string" + }, + "endage": { + "$ref": "#/definitions/Duration" + }, + "endtime": { + "description": "End time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "EndTime" + }, + "startage": { + "$ref": "#/definitions/Duration" + }, + "starttime": { + "description": "Start time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "StartTime" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionClientCloudletUsageMetrics": { + "type": "object", + "properties": { + "Cloudlet": { + "$ref": "#/definitions/CloudletKey" + }, + "DataNetworkType": { + "description": "Data network type used by client device. Can be used for selectors: latency", + "type": "string" + }, + "DeviceCarrier": { + "description": "Device carrier. Can be used for selectors: latency, deviceinfo", + "type": "string" + }, + "DeviceModel": { + "description": "Device model. Can be used for selectors: deviceinfo", + "type": "string" + }, + "DeviceOs": { + "description": "Device operating system. Can be used for selectors: deviceinfo", + "type": "string" + }, + "Limit": { + "description": "Display the last X metrics", + "type": "integer", + "format": "int64" + }, + "LocationTile": { + "description": "Provides the range of GPS coordinates for the location tile/square.\nFormat is: 'LocationUnderLongitude,LocationUnderLatitude_LocationOverLongitude,LocationOverLatitude_LocationTileLength'.\nLocationUnder are the GPS coordinates of the corner closest to (0,0) of the location tile.\nLocationOver are the GPS coordinates of the corner farthest from (0,0) of the location tile.\nLocationTileLength is the length (in kilometers) of one side of the location tile square", + "type": "string" + }, + "NumSamples": { + "description": "Display X samples spaced out evenly over start and end times", + "type": "integer", + "format": "int64" + }, + "Region": { + "description": "Region name", + "type": "string" + }, + "Selector": { + "description": "Comma separated list of metrics to view. Available metrics: utilization, network, ipusage", + "type": "string" + }, + "SignalStrength": { + "type": "string" + }, + "endage": { + "$ref": "#/definitions/Duration" + }, + "endtime": { + "description": "End time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "EndTime" + }, + "startage": { + "$ref": "#/definitions/Duration" + }, + "starttime": { + "description": "Start time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "StartTime" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudlet": { + "type": "object", + "required": ["Region"], + "properties": { + "Cloudlet": { + "$ref": "#/definitions/Cloudlet" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudletAllianceOrg": { + "type": "object", + "required": ["Region"], + "properties": { + "CloudletAllianceOrg": { + "$ref": "#/definitions/CloudletAllianceOrg" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudletInfo": { + "type": "object", + "required": ["Region"], + "properties": { + "CloudletInfo": { + "$ref": "#/definitions/CloudletInfo" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudletKey": { + "type": "object", + "required": ["Region"], + "properties": { + "CloudletKey": { + "$ref": "#/definitions/CloudletKey" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudletMetrics": { + "type": "object", + "properties": { + "Cloudlet": { + "$ref": "#/definitions/CloudletKey" + }, + "Cloudlets": { + "description": "Cloudlet keys for metrics", + "type": "array", + "items": { + "$ref": "#/definitions/CloudletKey" + } + }, + "Limit": { + "description": "Display the last X metrics", + "type": "integer", + "format": "int64" + }, + "NumSamples": { + "description": "Display X samples spaced out evenly over start and end times", + "type": "integer", + "format": "int64" + }, + "PlatformType": { + "type": "string" + }, + "Region": { + "description": "Region name", + "type": "string" + }, + "Selector": { + "description": "Comma separated list of metrics to view. Available metrics: utilization, network, ipusage", + "type": "string" + }, + "endage": { + "$ref": "#/definitions/Duration" + }, + "endtime": { + "description": "End time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "EndTime" + }, + "startage": { + "$ref": "#/definitions/Duration" + }, + "starttime": { + "description": "Start time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "StartTime" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudletPool": { + "type": "object", + "required": ["Region"], + "properties": { + "CloudletPool": { + "$ref": "#/definitions/CloudletPool" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudletPoolMember": { + "type": "object", + "required": ["Region"], + "properties": { + "CloudletPoolMember": { + "$ref": "#/definitions/CloudletPoolMember" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudletPoolUsage": { + "type": "object", + "properties": { + "CloudletPool": { + "$ref": "#/definitions/CloudletPoolKey" + }, + "EndTime": { + "description": "Time up to which to display stats", + "type": "string", + "format": "date-time" + }, + "Region": { + "description": "Region name", + "type": "string" + }, + "ShowVmAppsOnly": { + "description": "Show only VM-based apps", + "type": "boolean" + }, + "StartTime": { + "description": "Time to start displaying stats from", + "type": "string", + "format": "date-time" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudletProps": { + "type": "object", + "required": ["Region"], + "properties": { + "CloudletProps": { + "$ref": "#/definitions/CloudletProps" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudletRefs": { + "type": "object", + "required": ["Region"], + "properties": { + "CloudletRefs": { + "$ref": "#/definitions/CloudletRefs" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudletResMap": { + "type": "object", + "required": ["Region"], + "properties": { + "CloudletResMap": { + "$ref": "#/definitions/CloudletResMap" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudletResourceQuotaProps": { + "type": "object", + "required": ["Region"], + "properties": { + "CloudletResourceQuotaProps": { + "$ref": "#/definitions/CloudletResourceQuotaProps" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionCloudletResourceUsage": { + "type": "object", + "required": ["Region"], + "properties": { + "CloudletResourceUsage": { + "$ref": "#/definitions/CloudletResourceUsage" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionClusterInst": { + "type": "object", + "required": ["Region"], + "properties": { + "ClusterInst": { + "$ref": "#/definitions/ClusterInst" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionClusterInstKey": { + "type": "object", + "required": ["Region"], + "properties": { + "ClusterInstKey": { + "$ref": "#/definitions/ClusterInstKey" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionClusterInstMetrics": { + "type": "object", + "properties": { + "ClusterInst": { + "$ref": "#/definitions/ClusterInstKey" + }, + "ClusterInsts": { + "description": "Cluster instance keys for metrics", + "type": "array", + "items": { + "$ref": "#/definitions/ClusterInstKey" + } + }, + "Limit": { + "description": "Display the last X metrics", + "type": "integer", + "format": "int64" + }, + "NumSamples": { + "description": "Display X samples spaced out evenly over start and end times", + "type": "integer", + "format": "int64" + }, + "Region": { + "description": "Region name", + "type": "string" + }, + "Selector": { + "description": "Comma separated list of metrics to view. Available metrics: utilization, network, ipusage", + "type": "string" + }, + "endage": { + "$ref": "#/definitions/Duration" + }, + "endtime": { + "description": "End time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "EndTime" + }, + "startage": { + "$ref": "#/definitions/Duration" + }, + "starttime": { + "description": "Start time of the time range", + "type": "string", + "format": "date-time", + "x-go-name": "StartTime" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionClusterInstUsage": { + "type": "object", + "properties": { + "ClusterInst": { + "$ref": "#/definitions/ClusterInstKey" + }, + "EndTime": { + "description": "Time up to which to display stats", + "type": "string", + "format": "date-time" + }, + "Region": { + "description": "Region name", + "type": "string" + }, + "StartTime": { + "description": "Time to start displaying stats from", + "type": "string", + "format": "date-time" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionClusterRefs": { + "type": "object", + "required": ["Region"], + "properties": { + "ClusterRefs": { + "$ref": "#/definitions/ClusterRefs" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionDebugRequest": { + "type": "object", + "required": ["Region"], + "properties": { + "DebugRequest": { + "$ref": "#/definitions/DebugRequest" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionDeploymentCloudletRequest": { + "type": "object", + "required": ["Region"], + "properties": { + "DeploymentCloudletRequest": { + "$ref": "#/definitions/DeploymentCloudletRequest" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionDevice": { + "type": "object", + "required": ["Region"], + "properties": { + "Device": { + "$ref": "#/definitions/Device" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionDeviceReport": { + "type": "object", + "required": ["Region"], + "properties": { + "DeviceReport": { + "$ref": "#/definitions/DeviceReport" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionExecRequest": { + "type": "object", + "required": ["Region"], + "properties": { + "ExecRequest": { + "$ref": "#/definitions/ExecRequest" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionFlavor": { + "type": "object", + "required": ["Region"], + "properties": { + "Flavor": { + "$ref": "#/definitions/Flavor" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionFlavorMatch": { + "type": "object", + "required": ["Region"], + "properties": { + "FlavorMatch": { + "$ref": "#/definitions/FlavorMatch" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionFlowRateLimitSettings": { + "type": "object", + "required": ["Region"], + "properties": { + "FlowRateLimitSettings": { + "$ref": "#/definitions/FlowRateLimitSettings" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionGPUDriver": { + "type": "object", + "required": ["Region"], + "properties": { + "GPUDriver": { + "$ref": "#/definitions/GPUDriver" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionGPUDriverBuildMember": { + "type": "object", + "required": ["Region"], + "properties": { + "GPUDriverBuildMember": { + "$ref": "#/definitions/GPUDriverBuildMember" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionGPUDriverKey": { + "type": "object", + "required": ["Region"], + "properties": { + "GPUDriverKey": { + "$ref": "#/definitions/GPUDriverKey" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionIdleReservableClusterInsts": { + "type": "object", + "required": ["Region"], + "properties": { + "IdleReservableClusterInsts": { + "$ref": "#/definitions/IdleReservableClusterInsts" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionMaxReqsRateLimitSettings": { + "type": "object", + "required": ["Region"], + "properties": { + "MaxReqsRateLimitSettings": { + "$ref": "#/definitions/MaxReqsRateLimitSettings" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionNetwork": { + "type": "object", + "required": ["Region"], + "properties": { + "Network": { + "$ref": "#/definitions/Network" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionNode": { + "type": "object", + "required": ["Region"], + "properties": { + "Node": { + "$ref": "#/definitions/Node" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionOperatorCode": { + "type": "object", + "required": ["Region"], + "properties": { + "OperatorCode": { + "$ref": "#/definitions/OperatorCode" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionRateLimitSettings": { + "type": "object", + "required": ["Region"], + "properties": { + "RateLimitSettings": { + "$ref": "#/definitions/RateLimitSettings" + }, + "Region": { + "description": "Region name", + "type": "string" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionResTagTable": { + "type": "object", + "required": ["Region"], + "properties": { + "Region": { + "description": "Region name", + "type": "string" + }, + "ResTagTable": { + "$ref": "#/definitions/ResTagTable" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionResTagTableKey": { + "type": "object", + "required": ["Region"], + "properties": { + "Region": { + "description": "Region name", + "type": "string" + }, + "ResTagTableKey": { + "$ref": "#/definitions/ResTagTableKey" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionSettings": { + "type": "object", + "required": ["Region"], + "properties": { + "Region": { + "description": "Region name", + "type": "string" + }, + "Settings": { + "$ref": "#/definitions/Settings" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionTrustPolicy": { + "type": "object", + "required": ["Region"], + "properties": { + "Region": { + "description": "Region name", + "type": "string" + }, + "TrustPolicy": { + "$ref": "#/definitions/TrustPolicy" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionTrustPolicyException": { + "type": "object", + "required": ["Region"], + "properties": { + "Region": { + "description": "Region name", + "type": "string" + }, + "TrustPolicyException": { + "$ref": "#/definitions/TrustPolicyException" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionVMPool": { + "type": "object", + "required": ["Region"], + "properties": { + "Region": { + "description": "Region name", + "type": "string" + }, + "VMPool": { + "$ref": "#/definitions/VMPool" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RegionVMPoolMember": { + "type": "object", + "required": ["Region"], + "properties": { + "Region": { + "description": "Region name", + "type": "string" + }, + "VMPoolMember": { + "$ref": "#/definitions/VMPoolMember" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "ResTagTable": { + "type": "object", + "properties": { + "azone": { + "description": "Availability zone(s) of resource if required", + "type": "string", + "x-go-name": "Azone" + }, + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "fields": { + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "key": { + "$ref": "#/definitions/ResTagTableKey" + }, + "tags": { + "description": "One or more string tags", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "Tags" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "ResTagTableKey": { + "type": "object", + "properties": { + "name": { + "description": "Resource Table Name", + "type": "string", + "x-go-name": "Name" + }, + "organization": { + "description": "Operator organization of the cloudlet site.", + "type": "string", + "x-go-name": "Organization" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "ResourceQuota": { + "description": "Resource Quota", + "type": "object", + "properties": { + "alert_threshold": { + "description": "Generate alert when more than threshold percentage of resource is used", + "type": "integer", + "format": "int32", + "x-go-name": "AlertThreshold" + }, + "name": { + "description": "Resource name on which to set quota", + "type": "string", + "x-go-name": "Name" + }, + "value": { + "description": "Quota value of the resource", + "type": "integer", + "format": "uint64", + "x-go-name": "Value" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "Result": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int64", + "x-go-name": "Code" + }, + "message": { + "type": "string", + "x-go-name": "Message" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "Role": { + "type": "object", + "properties": { + "org": { + "description": "Organization name", + "type": "string", + "x-go-name": "Org" + }, + "role": { + "description": "Role which defines the set of permissions", + "type": "string", + "x-go-name": "Role" + }, + "username": { + "description": "User name", + "type": "string", + "x-go-name": "Username" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "RolePerm": { + "type": "object", + "properties": { + "action": { + "description": "Action defines what type of action can be performed on a resource", + "type": "string", + "x-go-name": "Action" + }, + "resource": { + "description": "Resource defines a resource to act upon", + "type": "string", + "x-go-name": "Resource" + }, + "role": { + "description": "Role defines a collection of permissions, which are resource-action pairs", + "type": "string", + "x-go-name": "Role" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "Route": { + "type": "object", + "properties": { + "destination_cidr": { + "description": "Destination CIDR", + "type": "string", + "x-go-name": "DestinationCidr" + }, + "next_hop_ip": { + "description": "Next hop IP", + "type": "string", + "x-go-name": "NextHopIp" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "RunCmd": { + "type": "object", + "properties": { + "cloudlet_mgmt_node": { + "$ref": "#/definitions/CloudletMgmtNode" + }, + "command": { + "description": "Command or Shell", + "type": "string", + "x-go-name": "Command" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "RunVMConsole": { + "type": "object", + "properties": { + "url": { + "description": "VM Console URL", + "type": "string", + "x-go-name": "Url" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "SecurityRule": { + "type": "object", + "properties": { + "port_range_max": { + "description": "TCP or UDP port range end", + "type": "integer", + "format": "uint32", + "x-go-name": "PortRangeMax" + }, + "port_range_min": { + "description": "TCP or UDP port range start", + "type": "integer", + "format": "uint32", + "x-go-name": "PortRangeMin" + }, + "protocol": { + "description": "TCP, UDP, ICMP", + "type": "string", + "x-go-name": "Protocol" + }, + "remote_cidr": { + "description": "Remote CIDR X.X.X.X/X", + "type": "string", + "x-go-name": "RemoteCidr" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "ServerlessConfig": { + "type": "object", + "properties": { + "min_replicas": { + "description": "Minimum number of replicas when serverless", + "type": "integer", + "format": "uint32", + "x-go-name": "MinReplicas" + }, + "ram": { + "description": "RAM allocation in megabytes per container when serverless", + "type": "integer", + "format": "uint64", + "x-go-name": "Ram" + }, + "vcpus": { + "$ref": "#/definitions/Udec64" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "Settings": { + "description": "Global settings", + "type": "object", + "properties": { + "alert_policy_min_trigger_time": { + "$ref": "#/definitions/Duration" + }, + "appinst_client_cleanup_interval": { + "$ref": "#/definitions/Duration" + }, + "auto_deploy_interval_sec": { + "description": "Auto Provisioning Stats push and analysis interval (seconds)", + "type": "number", + "format": "double", + "x-go-name": "AutoDeployIntervalSec" + }, + "auto_deploy_max_intervals": { + "description": "Auto Provisioning Policy max allowed intervals", + "type": "integer", + "format": "uint32", + "x-go-name": "AutoDeployMaxIntervals" + }, + "auto_deploy_offset_sec": { + "description": "Auto Provisioning analysis offset from interval (seconds)", + "type": "number", + "format": "double", + "x-go-name": "AutoDeployOffsetSec" + }, + "chef_client_interval": { + "$ref": "#/definitions/Duration" + }, + "cleanup_reservable_auto_cluster_idletime": { + "$ref": "#/definitions/Duration" + }, + "cloudlet_maintenance_timeout": { + "$ref": "#/definitions/Duration" + }, + "cluster_auto_scale_averaging_duration_sec": { + "description": "Cluster auto scale averaging duration for stats to avoid spikes (seconds), avoid setting below 30s or it will not capture any measurements to average", + "type": "integer", + "format": "int64", + "x-go-name": "ClusterAutoScaleAveragingDurationSec" + }, + "cluster_auto_scale_retry_delay": { + "$ref": "#/definitions/Duration" + }, + "create_app_inst_timeout": { + "$ref": "#/definitions/Duration" + }, + "create_cloudlet_timeout": { + "$ref": "#/definitions/Duration" + }, + "create_cluster_inst_timeout": { + "$ref": "#/definitions/Duration" + }, + "delete_app_inst_timeout": { + "$ref": "#/definitions/Duration" + }, + "delete_cluster_inst_timeout": { + "$ref": "#/definitions/Duration" + }, + "disable_rate_limit": { + "description": "Disable rate limiting for APIs (default is false)", + "type": "boolean", + "x-go-name": "DisableRateLimit" + }, + "dme_api_metrics_collection_interval": { + "$ref": "#/definitions/Duration" + }, + "edge_events_metrics_collection_interval": { + "$ref": "#/definitions/Duration" + }, + "edge_events_metrics_continuous_queries_collection_intervals": { + "description": "List of collection intervals for Continuous Queries for EdgeEvents metrics", + "type": "array", + "items": { + "$ref": "#/definitions/CollectionInterval" + }, + "x-go-name": "EdgeEventsMetricsContinuousQueriesCollectionIntervals" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "influx_db_cloudlet_usage_metrics_retention": { + "$ref": "#/definitions/Duration" + }, + "influx_db_downsampled_metrics_retention": { + "$ref": "#/definitions/Duration" + }, + "influx_db_edge_events_metrics_retention": { + "$ref": "#/definitions/Duration" + }, + "influx_db_metrics_retention": { + "$ref": "#/definitions/Duration" + }, + "location_tile_side_length_km": { + "description": "Length of location tiles side for latency metrics (km)", + "type": "integer", + "format": "int64", + "x-go-name": "LocationTileSideLengthKm" + }, + "master_node_flavor": { + "description": "Default flavor for k8s master VM and \u003e 0 workers", + "type": "string", + "x-go-name": "MasterNodeFlavor" + }, + "max_tracked_dme_clients": { + "description": "Max DME clients to be tracked at the same time.", + "type": "integer", + "format": "int32", + "x-go-name": "MaxTrackedDmeClients" + }, + "platform_ha_instance_active_expire_time": { + "$ref": "#/definitions/Duration" + }, + "platform_ha_instance_poll_interval": { + "$ref": "#/definitions/Duration" + }, + "rate_limit_max_tracked_ips": { + "description": "Maximum number of IPs to track for rate limiting", + "type": "integer", + "format": "int64", + "x-go-name": "RateLimitMaxTrackedIps" + }, + "resource_snapshot_thread_interval": { + "$ref": "#/definitions/Duration" + }, + "shepherd_alert_evaluation_interval": { + "$ref": "#/definitions/Duration" + }, + "shepherd_health_check_interval": { + "$ref": "#/definitions/Duration" + }, + "shepherd_health_check_retries": { + "description": "Number of times Shepherd Health Check fails before we mark appInst down", + "type": "integer", + "format": "int32", + "x-go-name": "ShepherdHealthCheckRetries" + }, + "shepherd_metrics_collection_interval": { + "$ref": "#/definitions/Duration" + }, + "shepherd_metrics_scrape_interval": { + "$ref": "#/definitions/Duration" + }, + "update_app_inst_timeout": { + "$ref": "#/definitions/Duration" + }, + "update_cloudlet_timeout": { + "$ref": "#/definitions/Duration" + }, + "update_cluster_inst_timeout": { + "$ref": "#/definitions/Duration" + }, + "update_trust_policy_timeout": { + "$ref": "#/definitions/Duration" + }, + "update_vm_pool_timeout": { + "$ref": "#/definitions/Duration" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "ShowLog": { + "type": "object", + "properties": { + "follow": { + "description": "Stream data", + "type": "boolean", + "x-go-name": "Follow" + }, + "since": { + "description": "Show logs since either a duration ago (5s, 2m, 3h) or a timestamp (RFC3339)", + "type": "string", + "x-go-name": "Since" + }, + "tail": { + "description": "Show only a recent number of lines", + "type": "integer", + "format": "int32", + "x-go-name": "Tail" + }, + "timestamps": { + "description": "Show timestamps", + "type": "boolean", + "x-go-name": "Timestamps" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "StatusInfo": { + "description": "Used to track status of create/delete/update for resources that are being modified\nby the controller via the CRM. Tasks are the high level jobs that are to be completed.\nSteps are work items within a task. Within the clusterinst and appinst objects this\nis converted to a string", + "type": "object", + "title": "Status Information", + "properties": { + "max_tasks": { + "type": "integer", + "format": "uint32", + "x-go-name": "MaxTasks" + }, + "msg_count": { + "type": "integer", + "format": "uint32", + "x-go-name": "MsgCount" + }, + "msgs": { + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Msgs" + }, + "step_name": { + "type": "string", + "x-go-name": "StepName" + }, + "task_name": { + "type": "string", + "x-go-name": "TaskName" + }, + "task_number": { + "type": "integer", + "format": "uint32", + "x-go-name": "TaskNumber" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "Timestamp": { + "description": "All minutes are 60 seconds long. Leap seconds are \"smeared\" so that no leap\nsecond table is needed for interpretation, using a [24-hour linear\nsmear](https://developers.google.com/time/smear).\n\nThe range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By\nrestricting to that range, we ensure that we can convert to and from [RFC\n3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.\n\n# Examples\n\nExample 1: Compute Timestamp from POSIX `time()`.\n\nTimestamp timestamp;\ntimestamp.set_seconds(time(NULL));\ntimestamp.set_nanos(0);\n\nExample 2: Compute Timestamp from POSIX `gettimeofday()`.\n\nstruct timeval tv;\ngettimeofday(\u0026tv, NULL);\n\nTimestamp timestamp;\ntimestamp.set_seconds(tv.tv_sec);\ntimestamp.set_nanos(tv.tv_usec * 1000);\n\nExample 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.\n\nFILETIME ft;\nGetSystemTimeAsFileTime(\u0026ft);\nUINT64 ticks = (((UINT64)ft.dwHighDateTime) \u003c\u003c 32) | ft.dwLowDateTime;\n\nA Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z\nis 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.\nTimestamp timestamp;\ntimestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));\ntimestamp.set_nanos((INT32) ((ticks % 10000000) * 100));\n\nExample 4: Compute Timestamp from Java `System.currentTimeMillis()`.\n\nlong millis = System.currentTimeMillis();\n\nTimestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)\n.setNanos((int) ((millis % 1000) * 1000000)).build();\n\n\nExample 5: Compute Timestamp from current time in Python.\n\ntimestamp = Timestamp()\ntimestamp.GetCurrentTime()\n\n# JSON Mapping\n\nIn JSON format, the Timestamp type is encoded as a string in the\n[RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the\nformat is \"{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z\"\nwhere {year} is always expressed using four digits while {month}, {day},\n{hour}, {min}, and {sec} are zero-padded to two digits each. The fractional\nseconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),\nare optional. The \"Z\" suffix indicates the timezone (\"UTC\"); the timezone\nis required. A proto3 JSON serializer should always use UTC (as indicated by\n\"Z\") when printing the Timestamp type and a proto3 JSON parser should be\nable to accept both UTC and other timezones (as indicated by an offset).\n\nFor example, \"2017-01-15T01:30:15.01Z\" encodes 15.01 seconds past\n01:30 UTC on January 15, 2017.\n\nIn JavaScript, one can convert a Date object to this format using the\nstandard\n[toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)\nmethod. In Python, a standard `datetime.datetime` object can be converted\nto this format using\n[`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with\nthe time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use\nthe Joda Time's [`ISODateTimeFormat.dateTime()`](\nhttp://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D\n) to obtain a formatter capable of generating timestamps in this format.", + "type": "object", + "title": "A Timestamp represents a point in time independent of any time zone or local\ncalendar, encoded as a count of seconds and fractions of seconds at\nnanosecond resolution. The count is relative to an epoch at UTC midnight on\nJanuary 1, 1970, in the proleptic Gregorian calendar which extends the\nGregorian calendar backwards to year one.", + "properties": { + "nanos": { + "description": "Non-negative fractions of a second at nanosecond resolution. Negative\nsecond values with fractions must still have non-negative nanos values\nthat count forward in time. Must be from 0 to 999,999,999\ninclusive.", + "type": "integer", + "format": "int32", + "x-go-name": "Nanos" + }, + "seconds": { + "description": "Represents seconds of UTC time since Unix epoch\n1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to\n9999-12-31T23:59:59Z inclusive.", + "type": "integer", + "format": "int64", + "x-go-name": "Seconds" + } + }, + "x-go-package": "github.com/gogo/protobuf/types" + }, + "Token": { + "type": "object", + "properties": { + "token": { + "description": "Authentication token", + "type": "string", + "x-go-name": "Token" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "TrackedState": { + "description": "TrackedState is used to track the state of an object on a remote node,\ni.e. track the state of a ClusterInst object on the CRM (Cloudlet).\n\n0: `TRACKED_STATE_UNKNOWN`\n1: `NOT_PRESENT`\n2: `CREATE_REQUESTED`\n3: `CREATING`\n4: `CREATE_ERROR`\n5: `READY`\n6: `UPDATE_REQUESTED`\n7: `UPDATING`\n8: `UPDATE_ERROR`\n9: `DELETE_REQUESTED`\n10: `DELETING`\n11: `DELETE_ERROR`\n12: `DELETE_PREPARE`\n13: `CRM_INITOK`\n14: `CREATING_DEPENDENCIES`\n15: `DELETE_DONE`", + "type": "integer", + "format": "int32", + "title": "Tracked States", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "TrustPolicy": { + "description": "TrustPolicy defines security restrictions for cluster instances\nnodes scaled up or down.", + "type": "object", + "properties": { + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "key": { + "$ref": "#/definitions/PolicyKey" + }, + "outbound_security_rules": { + "description": "List of outbound security rules for whitelisting traffic", + "type": "array", + "items": { + "$ref": "#/definitions/SecurityRule" + }, + "x-go-name": "OutboundSecurityRules" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "TrustPolicyException": { + "type": "object", + "properties": { + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "key": { + "$ref": "#/definitions/TrustPolicyExceptionKey" + }, + "outbound_security_rules": { + "description": "List of outbound security rules for whitelisting traffic", + "type": "array", + "items": { + "$ref": "#/definitions/SecurityRule" + }, + "x-go-name": "OutboundSecurityRules" + }, + "state": { + "$ref": "#/definitions/TrustPolicyExceptionState" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "TrustPolicyExceptionKey": { + "type": "object", + "properties": { + "app_key": { + "$ref": "#/definitions/AppKey" + }, + "cloudlet_pool_key": { + "$ref": "#/definitions/CloudletPoolKey" + }, + "name": { + "description": "TrustPolicyExceptionKey name", + "type": "string", + "x-go-name": "Name" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "TrustPolicyExceptionState": { + "type": "integer", + "format": "int32", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "Udec64": { + "description": "Udec64 is an unsigned decimal with whole number values\nas uint64, and decimal values in nanos.", + "type": "object", + "title": "Udec64", + "properties": { + "nanos": { + "description": "Decimal value in nanos", + "type": "integer", + "format": "uint32", + "x-go-name": "Nanos" + }, + "whole": { + "description": "Whole number value", + "type": "integer", + "format": "uint64", + "x-go-name": "Whole" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "User": { + "type": "object", + "required": ["Name"], + "properties": { + "CreatedAt": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "Email": { + "description": "User email", + "type": "string" + }, + "EmailVerified": { + "description": "Email address has been verified", + "type": "boolean", + "readOnly": true + }, + "EnableTOTP": { + "description": "Enable or disable temporary one-time passwords for the account", + "type": "boolean" + }, + "FailedLogins": { + "description": "Number of failed login attempts since last successful login", + "type": "integer", + "format": "int64" + }, + "FamilyName": { + "description": "Family Name", + "type": "string" + }, + "GivenName": { + "description": "Given Name", + "type": "string" + }, + "Iter": { + "type": "integer", + "format": "int64", + "readOnly": true + }, + "LastFailedLogin": { + "description": "Last failed login time", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "LastLogin": { + "description": "Last successful login time", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "Locked": { + "description": "Account is locked", + "type": "boolean", + "readOnly": true + }, + "Metadata": { + "description": "Metadata", + "type": "string" + }, + "Name": { + "description": "User name. Can only contain letters, digits, underscore, period, hyphen. It cannot have leading or trailing spaces or period. It cannot start with hyphen", + "type": "string" + }, + "Nickname": { + "description": "Nick Name", + "type": "string" + }, + "PassCrackTimeSec": { + "type": "number", + "format": "double", + "readOnly": true + }, + "Passhash": { + "type": "string", + "readOnly": true + }, + "Picture": { + "type": "string", + "readOnly": true + }, + "Salt": { + "type": "string", + "readOnly": true + }, + "TOTPSharedKey": { + "type": "string", + "readOnly": true + }, + "UpdatedAt": { + "type": "string", + "format": "date-time", + "readOnly": true + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "UserLogin": { + "type": "object", + "required": ["username", "password"], + "properties": { + "apikey": { + "description": "API key if logging in using API key", + "type": "string", + "x-go-name": "ApiKey" + }, + "apikeyid": { + "description": "API key ID if logging in using API key", + "type": "string", + "x-go-name": "ApiKeyId" + }, + "password": { + "description": "User's password", + "type": "string", + "x-go-name": "Password" + }, + "totp": { + "description": "Temporary one-time password if 2-factor authentication is enabled", + "type": "string", + "x-go-name": "TOTP" + }, + "username": { + "description": "User's name or email address", + "type": "string", + "x-go-name": "Username" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/ormapi" + }, + "VM": { + "type": "object", + "properties": { + "flavor": { + "$ref": "#/definitions/FlavorInfo" + }, + "group_name": { + "description": "VM Group Name", + "type": "string", + "x-go-name": "GroupName" + }, + "internal_name": { + "description": "VM Internal Name", + "type": "string", + "x-go-name": "InternalName" + }, + "name": { + "description": "VM Name", + "type": "string", + "x-go-name": "Name" + }, + "net_info": { + "$ref": "#/definitions/VMNetInfo" + }, + "state": { + "$ref": "#/definitions/VMState" + }, + "updated_at": { + "$ref": "#/definitions/Timestamp" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "VMNetInfo": { + "type": "object", + "properties": { + "external_ip": { + "description": "External IP", + "type": "string", + "x-go-name": "ExternalIp" + }, + "internal_ip": { + "description": "Internal IP", + "type": "string", + "x-go-name": "InternalIp" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "VMPool": { + "description": "VMPool defines a pool of VMs to be part of a Cloudlet", + "type": "object", + "properties": { + "crm_override": { + "$ref": "#/definitions/CRMOverride" + }, + "delete_prepare": { + "description": "Preparing to be deleted", + "type": "boolean", + "x-go-name": "DeletePrepare" + }, + "errors": { + "description": "Any errors trying to add/remove VM to/from VM Pool", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Errors" + }, + "fields": { + "description": "Fields are used for the Update API to specify which fields to apply", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Fields" + }, + "key": { + "$ref": "#/definitions/VMPoolKey" + }, + "state": { + "$ref": "#/definitions/TrackedState" + }, + "vms": { + "description": "list of VMs to be part of VM pool", + "type": "array", + "items": { + "$ref": "#/definitions/VM" + }, + "x-go-name": "Vms" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "VMPoolKey": { + "description": "VMPoolKey uniquely identifies a VMPool.", + "type": "object", + "title": "VMPool unique key", + "properties": { + "name": { + "description": "Name of the vmpool", + "type": "string", + "x-go-name": "Name" + }, + "organization": { + "description": "Organization of the vmpool", + "type": "string", + "x-go-name": "Organization" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "VMPoolMember": { + "description": "VMPoolMember is used to add and remove VM from VM Pool", + "type": "object", + "properties": { + "crm_override": { + "$ref": "#/definitions/CRMOverride" + }, + "key": { + "$ref": "#/definitions/VMPoolKey" + }, + "vm": { + "$ref": "#/definitions/VM" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "VMState": { + "description": "VMState is the state of the VM\n\n0: `VM_FREE`\n1: `VM_IN_PROGRESS`\n2: `VM_IN_USE`\n3: `VM_ADD`\n4: `VM_REMOVE`\n5: `VM_UPDATE`\n6: `VM_FORCE_FREE`", + "type": "integer", + "format": "int32", + "title": "VM State", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "VirtualClusterInstKey": { + "description": "Virtual ClusterInstKey", + "type": "object", + "properties": { + "cloudlet_key": { + "$ref": "#/definitions/CloudletKey" + }, + "cluster_key": { + "$ref": "#/definitions/ClusterKey" + }, + "organization": { + "description": "Name of Developer organization that this cluster belongs to", + "type": "string", + "x-go-name": "Organization" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "VmAppOsType": { + "type": "integer", + "format": "int32", + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "VmInfo": { + "description": "VmInfo is information about Virtual Machine resources.", + "type": "object", + "title": "VmInfo", + "properties": { + "containers": { + "description": "Information about containers running in the VM", + "type": "array", + "items": { + "$ref": "#/definitions/ContainerInfo" + }, + "x-go-name": "Containers" + }, + "infraFlavor": { + "description": "Flavor allocated within the cloudlet infrastructure, distinct from the control plane flavor", + "type": "string", + "x-go-name": "InfraFlavor" + }, + "ipaddresses": { + "description": "IP addresses allocated to the VM", + "type": "array", + "items": { + "$ref": "#/definitions/IpAddr" + }, + "x-go-name": "Ipaddresses" + }, + "name": { + "description": "Virtual machine name", + "type": "string", + "x-go-name": "Name" + }, + "status": { + "description": "Runtime status of the VM", + "type": "string", + "x-go-name": "Status" + }, + "type": { + "description": "Type can be platformvm, platform-cluster-master, platform-cluster-primary-node, platform-cluster-secondary-node, sharedrootlb, dedicatedrootlb, cluster-master, cluster-k8s-node, cluster-docker-node, appvm", + "type": "string", + "x-go-name": "Type" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/api/edgeproto" + }, + "alert": { + "description": "Alert alert", + "type": "object", + "required": ["labels"], + "properties": { + "generatorURL": { + "description": "generator URL\nFormat: uri", + "type": "string", + "format": "uri", + "x-go-name": "GeneratorURL" + }, + "labels": { + "$ref": "#/definitions/labelSet" + } + }, + "x-go-name": "Alert", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "alertGroup": { + "description": "AlertGroup alert group", + "type": "object", + "required": ["alerts", "labels", "receiver"], + "properties": { + "alerts": { + "description": "alerts", + "type": "array", + "items": { + "$ref": "#/definitions/gettableAlert" + }, + "x-go-name": "Alerts" + }, + "labels": { + "$ref": "#/definitions/labelSet" + }, + "receiver": { + "$ref": "#/definitions/receiver" + } + }, + "x-go-name": "AlertGroup", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "alertGroups": { + "description": "AlertGroups alert groups", + "type": "array", + "items": { + "$ref": "#/definitions/alertGroup" + }, + "x-go-name": "AlertGroups", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "alertStatus": { + "description": "AlertStatus alert status", + "type": "object", + "required": ["inhibitedBy", "silencedBy", "state"], + "properties": { + "inhibitedBy": { + "description": "inhibited by", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "InhibitedBy" + }, + "silencedBy": { + "description": "silenced by", + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "SilencedBy" + }, + "state": { + "description": "state", + "type": "string", + "enum": ["[unprocessed active suppressed]"], + "x-go-name": "State" + } + }, + "x-go-name": "AlertStatus", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "alertmanagerConfig": { + "description": "AlertmanagerConfig alertmanager config", + "type": "object", + "required": ["original"], + "properties": { + "original": { + "description": "original", + "type": "string", + "x-go-name": "Original" + } + }, + "x-go-name": "AlertmanagerConfig", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "alertmanagerStatus": { + "description": "AlertmanagerStatus alertmanager status", + "type": "object", + "required": ["cluster", "config", "uptime", "versionInfo"], + "properties": { + "cluster": { + "$ref": "#/definitions/clusterStatus" + }, + "config": { + "$ref": "#/definitions/alertmanagerConfig" + }, + "uptime": { + "description": "uptime", + "type": "string", + "format": "date-time", + "x-go-name": "Uptime" + }, + "versionInfo": { + "$ref": "#/definitions/versionInfo" + } + }, + "x-go-name": "AlertmanagerStatus", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "clusterStatus": { + "description": "ClusterStatus cluster status", + "type": "object", + "required": ["status"], + "properties": { + "name": { + "description": "name", + "type": "string", + "x-go-name": "Name" + }, + "peers": { + "description": "peers", + "type": "array", + "items": { + "$ref": "#/definitions/peerStatus" + }, + "x-go-name": "Peers" + }, + "status": { + "description": "status", + "type": "string", + "enum": ["[ready settling disabled]"], + "x-go-name": "Status" + } + }, + "x-go-name": "ClusterStatus", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "gettableAlert": { + "description": "GettableAlert gettable alert", + "type": "object", + "required": [ + "labels", + "annotations", + "endsAt", + "fingerprint", + "receivers", + "startsAt", + "status", + "updatedAt" + ], + "properties": { + "annotations": { + "$ref": "#/definitions/labelSet" + }, + "endsAt": { + "description": "ends at", + "type": "string", + "format": "date-time", + "x-go-name": "EndsAt" + }, + "fingerprint": { + "description": "fingerprint", + "type": "string", + "x-go-name": "Fingerprint" + }, + "generatorURL": { + "description": "generator URL\nFormat: uri", + "type": "string", + "format": "uri", + "x-go-name": "GeneratorURL" + }, + "labels": { + "$ref": "#/definitions/labelSet" + }, + "receivers": { + "description": "receivers", + "type": "array", + "items": { + "$ref": "#/definitions/receiver" + }, + "x-go-name": "Receivers" + }, + "startsAt": { + "description": "starts at", + "type": "string", + "format": "date-time", + "x-go-name": "StartsAt" + }, + "status": { + "$ref": "#/definitions/alertStatus" + }, + "updatedAt": { + "description": "updated at", + "type": "string", + "format": "date-time", + "x-go-name": "UpdatedAt" + } + }, + "x-go-name": "GettableAlert", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "gettableAlerts": { + "description": "GettableAlerts gettable alerts", + "type": "array", + "items": { + "$ref": "#/definitions/gettableAlert" + }, + "x-go-name": "GettableAlerts", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "gettableSilence": { + "description": "GettableSilence gettable silence", + "type": "object", + "required": [ + "comment", + "createdBy", + "endsAt", + "matchers", + "startsAt", + "id", + "status", + "updatedAt" + ], + "properties": { + "comment": { + "description": "comment", + "type": "string", + "x-go-name": "Comment" + }, + "createdBy": { + "description": "created by", + "type": "string", + "x-go-name": "CreatedBy" + }, + "endsAt": { + "description": "ends at", + "type": "string", + "format": "date-time", + "x-go-name": "EndsAt" + }, + "id": { + "description": "id", + "type": "string", + "x-go-name": "ID" + }, + "matchers": { + "$ref": "#/definitions/matchers" + }, + "startsAt": { + "description": "starts at", + "type": "string", + "format": "date-time", + "x-go-name": "StartsAt" + }, + "status": { + "$ref": "#/definitions/silenceStatus" + }, + "updatedAt": { + "description": "updated at", + "type": "string", + "format": "date-time", + "x-go-name": "UpdatedAt" + } + }, + "x-go-name": "GettableSilence", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "gettableSilences": { + "description": "GettableSilences gettable silences", + "type": "array", + "items": { + "$ref": "#/definitions/gettableSilence" + }, + "x-go-name": "GettableSilences", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "labelSet": { + "description": "LabelSet label set", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-go-name": "LabelSet", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "matcher": { + "description": "Matcher matcher", + "type": "object", + "required": ["isRegex", "name", "value"], + "properties": { + "isRegex": { + "description": "is regex", + "type": "boolean", + "x-go-name": "IsRegex" + }, + "name": { + "description": "name", + "type": "string", + "x-go-name": "Name" + }, + "value": { + "description": "value", + "type": "string", + "x-go-name": "Value" + } + }, + "x-go-name": "Matcher", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "matchers": { + "description": "Matchers matchers", + "type": "array", + "items": { + "$ref": "#/definitions/matcher" + }, + "x-go-name": "Matchers", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "peerStatus": { + "description": "PeerStatus peer status", + "type": "object", + "required": ["address", "name"], + "properties": { + "address": { + "description": "address", + "type": "string", + "x-go-name": "Address" + }, + "name": { + "description": "name", + "type": "string", + "x-go-name": "Name" + } + }, + "x-go-name": "PeerStatus", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "postableAlert": { + "description": "PostableAlert postable alert", + "type": "object", + "required": ["labels"], + "properties": { + "annotations": { + "$ref": "#/definitions/labelSet" + }, + "endsAt": { + "description": "ends at\nFormat: date-time", + "type": "string", + "format": "date-time", + "x-go-name": "EndsAt" + }, + "generatorURL": { + "description": "generator URL\nFormat: uri", + "type": "string", + "format": "uri", + "x-go-name": "GeneratorURL" + }, + "labels": { + "$ref": "#/definitions/labelSet" + }, + "startsAt": { + "description": "starts at\nFormat: date-time", + "type": "string", + "format": "date-time", + "x-go-name": "StartsAt" + } + }, + "x-go-name": "PostableAlert", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "postableAlerts": { + "description": "PostableAlerts postable alerts", + "type": "array", + "items": { + "$ref": "#/definitions/postableAlert" + }, + "x-go-name": "PostableAlerts", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "postableSilence": { + "description": "PostableSilence postable silence", + "type": "object", + "required": ["comment", "createdBy", "endsAt", "matchers", "startsAt"], + "properties": { + "comment": { + "description": "comment", + "type": "string", + "x-go-name": "Comment" + }, + "createdBy": { + "description": "created by", + "type": "string", + "x-go-name": "CreatedBy" + }, + "endsAt": { + "description": "ends at", + "type": "string", + "format": "date-time", + "x-go-name": "EndsAt" + }, + "id": { + "description": "id", + "type": "string", + "x-go-name": "ID" + }, + "matchers": { + "$ref": "#/definitions/matchers" + }, + "startsAt": { + "description": "starts at", + "type": "string", + "format": "date-time", + "x-go-name": "StartsAt" + } + }, + "x-go-name": "PostableSilence", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "receiver": { + "description": "Receiver receiver", + "type": "object", + "required": ["name"], + "properties": { + "name": { + "description": "name", + "type": "string", + "x-go-name": "Name" + } + }, + "x-go-name": "Receiver", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "silence": { + "description": "Silence silence", + "type": "object", + "required": ["comment", "createdBy", "endsAt", "matchers", "startsAt"], + "properties": { + "comment": { + "description": "comment", + "type": "string", + "x-go-name": "Comment" + }, + "createdBy": { + "description": "created by", + "type": "string", + "x-go-name": "CreatedBy" + }, + "endsAt": { + "description": "ends at", + "type": "string", + "format": "date-time", + "x-go-name": "EndsAt" + }, + "matchers": { + "$ref": "#/definitions/matchers" + }, + "startsAt": { + "description": "starts at", + "type": "string", + "format": "date-time", + "x-go-name": "StartsAt" + } + }, + "x-go-name": "Silence", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "silenceStatus": { + "description": "SilenceStatus silence status", + "type": "object", + "required": ["state"], + "properties": { + "state": { + "description": "state", + "type": "string", + "enum": ["[expired active pending]"], + "x-go-name": "State" + } + }, + "x-go-name": "SilenceStatus", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + }, + "swaggerHttpResponse": { + "type": "object", + "properties": { + "message": { + "type": "string", + "x-go-name": "Message" + } + }, + "x-go-package": "github.com/edgexr/edge-cloud-platform/doc/swagger" + }, + "versionInfo": { + "description": "VersionInfo version info", + "type": "object", + "required": [ + "branch", + "buildDate", + "buildUser", + "goVersion", + "revision", + "version" + ], + "properties": { + "branch": { + "description": "branch", + "type": "string", + "x-go-name": "Branch" + }, + "buildDate": { + "description": "build date", + "type": "string", + "x-go-name": "BuildDate" + }, + "buildUser": { + "description": "build user", + "type": "string", + "x-go-name": "BuildUser" + }, + "goVersion": { + "description": "go version", + "type": "string", + "x-go-name": "GoVersion" + }, + "revision": { + "description": "revision", + "type": "string", + "x-go-name": "Revision" + }, + "version": { + "description": "version", + "type": "string", + "x-go-name": "Version" + } + }, + "x-go-name": "VersionInfo", + "x-go-package": "github.com/edgexr/edge-cloud-platform/pkg/mc/orm/alertmgr/prometheus_structs/models" + } + }, + "responses": { + "authToken": { + "description": "Authentication Token", + "schema": { + "$ref": "#/definitions/Token" + } + }, + "badRequest": { + "description": "Status Bad Request", + "schema": { + "$ref": "#/definitions/Result" + } + }, + "forbidden": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/Result" + } + }, + "listBillingOrgs": { + "description": "List of BillingOrgs", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/BillingOrganization" + } + } + }, + "listOrgs": { + "description": "List of Orgs", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Organization" + } + } + }, + "listPerms": { + "description": "List of Permissions", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/RolePerm" + } + } + }, + "listRoles": { + "description": "List of Roles", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Role" + } + } + }, + "listUsers": { + "description": "List of Users", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/User" + } + } + }, + "loginBadRequest": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/swaggerHttpResponse" + } + }, + "notFound": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/Result" + } + }, + "success": { + "description": "Success", + "schema": { + "$ref": "#/definitions/swaggerHttpResponse" + } + } + }, + "securityDefinitions": { + "Bearer": { + "description": "Use [login API](#operation/Login) to generate bearer token (JWT) for authorization. Usage format - `Bearer \u003cJWT\u003e`", + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + }, + "tags": [ + { + "description": "Authentication is done by a user name or email plus a password. The login function returns a JSON Web Token (JWT) once authenticated, that should be included with subsequent API calls to authenticate the user. The JWT will expire after a while for security, at which point you may need to log in again.", + "name": "Security" + }, + { + "description": "Users can be assigned roles for Organizations, allowing them to view or manage resources associated with the Organizations.", + "name": "User" + }, + { + "description": "Roles can be assigned to users for Organizations, allowing the users to view or manage resources associated with the Organizations.", + "name": "Role" + }, + { + "description": "Organizations group a set of resources together, for example Apps, App Instances, or Cloudlets. Users given a role in an Organization can operate on those resources in the scope provided by their role.", + "name": "Organization" + }, + { + "description": "OperatorCode maps a carrier code to an Operator organization name.", + "name": "OperatorCode" + }, + { + "description": "Flavors define the compute, memory and storage capacity of computing instances. To put it simply, a flavor is an available hardware configuration for a server. It defines the size of a virtual server that can be launched.", + "name": "Flavor" + }, + { + "description": "AutoProvPolicy defines the automated provisioning policy.", + "name": "AutoProvPolicy" + }, + { + "description": "AutoProvPolicy belonging to an app.", + "name": "AppAutoProvPolicy" + }, + { + "description": "AutoScalePolicy defines when and how ClusterInsts will have their nodes scaled up or down.", + "name": "AutoScalePolicy" + }, + { + "description": "PrivacyPolicy defines security restrictions for cluster instances nodes scaled up or down.", + "name": "PrivacyPolicy" + }, + { + "description": "AutoProvPolicyCloudlet belong to a cloudlet.", + "name": "AutoProvPolicyCloudlet" + }, + { + "description": "Pool of VMs to be part of a Cloudlet.", + "name": "VMPool" + }, + { + "description": "Members belong to a VMPool.", + "name": "VMPoolMember" + }, + { + "description": "Cloudlet is a set of compute resources at a particular location, provided by an Operator.", + "name": "Cloudlet" + }, + { + "description": "CloudletPool defines a pool of Cloudlets that have restricted access.", + "name": "CloudletPool" + }, + { + "description": "Member belong to a cloudlet pool.", + "name": "CloudletPoolMember" + }, + { + "description": "ClusterInst is an instance of a Cluster on a Cloudlet. It is defined by a Cluster, Cloudlet, and Developer key.", + "name": "ClusterInst" + }, + { + "description": "Provides information about the developer's application.", + "name": "App" + }, + { + "description": "AppInst is an instance of an App on a Cloudlet where it is defined by an App plus a ClusterInst key.", + "name": "AppInst" + }, + { + "description": "Infra properties used to setup cloudlet.", + "name": "CloudletProps" + }, + { + "description": "Cloudlet resouce mapping.", + "name": "CloudletResMap" + }, + { + "description": "To match a flavor with platform flavor.", + "name": "FlavorMatch" + }, + { + "description": "Client is an AppInst client that called FindCloudlet DME Api.", + "name": "AppInstClientKey" + }, + { + "description": "ExecRequest is a common struct for enabling a connection to execute some work on a container.", + "name": "ExecRequest" + }, + { + "description": "Collection of statistics related to Client/App/Cluster.", + "name": "DeveloperMetrics" + }, + { + "description": "Collection of statistics related to Cloudlet.", + "name": "OperatorMetrics" + }, + { + "description": "Collection of event/audit logs from edge services.", + "name": "Events" + }, + { + "description": "Usage details of App/Cluster.", + "name": "DeveloperUsage" + }, + { + "description": "Usage details of Cloudlet.", + "name": "OperatorUsage" + }, + { + "description": "Manage receiver for alerts from edge services.", + "name": "AlertReceiver" + }, + { + "description": "Manage additional networks which can be added to Cluster Instances.", + "name": "Network" + } + ], + "x-tagGroups": [ + { + "name": "Auth \u0026 User Management API", + "tags": ["Security", "User", "Role", "Organization"] + }, + { + "name": "Operator API", + "tags": [ + "Cloudlet", + "OperatorCode", + "Flavor", + "CloudletProps", + "CloudletResMap", + "FlavorMatch", + "CloudletPool", + "CloudletPoolMember", + "VMPool", + "VMPoolMember", + "OperatorMetrics", + "Events", + "OperatorUsage", + "AlertReceiver", + "Network" + ] + }, + { + "name": "Developer API", + "tags": [ + "ClusterInst", + "App", + "AppInst", + "AutoProvPolicy", + "AppAutoProvPolicy", + "AutoScalePolicy", + "PrivacyPolicy", + "AutoProvPolicyCloudlet", + "AppInstClientKey", + "ExecRequest", + "DeveloperMetrics", + "Events", + "DeveloperUsage", + "AlertReceiver" + ] + } + ] +} diff --git a/go.mod b/go.mod index a54303b..9611b9e 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,21 @@ module edp.buildth.ing/DevFW-CICD/edge-connect-client go 1.25.1 require ( + github.com/hashicorp/go-retryablehttp v0.7.8 github.com/spf13/cobra v1.10.1 github.com/spf13/viper v1.21.0 + github.com/stretchr/testify v1.11.1 ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/sagikazarmark/locafero v0.11.0 // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/afero v1.15.0 // indirect @@ -19,6 +25,8 @@ require ( github.com/spf13/pflag v1.0.10 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/sys v0.29.0 // indirect + golang.org/x/sys v0.34.0 // indirect golang.org/x/text v0.28.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 450a91f..7f0fa41 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= @@ -9,18 +11,31 @@ github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9L github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= +github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= @@ -43,12 +58,12 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/oapi-codegen.yaml b/oapi-codegen.yaml new file mode 100644 index 0000000..3e05cf0 --- /dev/null +++ b/oapi-codegen.yaml @@ -0,0 +1,8 @@ +package: client +output: sdk/client/types_generated.go +generate: + models: true + client: false + embedded-spec: false +output-options: + skip-prune: true \ No newline at end of file diff --git a/plan.md b/plan.md new file mode 100644 index 0000000..cc216ea --- /dev/null +++ b/plan.md @@ -0,0 +1,217 @@ +# EdgeXR Master Controller Go SDK - Implementation Plan + +## Project Overview + +Develop a comprehensive Go SDK for the EdgeXR Master Controller API, building upon the existing `edge-connect-client` prototype. The SDK will provide typed, idiomatic Go interfaces for app lifecycle management, cloudlet orchestration, and edge deployment workflows. + +## Technology Stack + +- **Code Generation**: oapi-codegen for swagger-to-Go type generation +- **HTTP Client**: go-retryablehttp for robust networking with retry/backoff +- **CLI Framework**: Cobra + Viper (extending existing CLI) +- **Authentication**: Static Bearer token provider (MVP) +- **Testing**: testify + httptest for comprehensive testing +- **Tooling**: golangci-lint, standard Go toolchain + +## Implementation Phases + +### Phase 1: Foundation & Code Generation (Week 1) + +#### 1.1 Project Structure Setup +- Add `/sdk` directory to existing edge-connect-client project +- Create subdirectories: `/sdk/client`, `/sdk/internal/http`, `/sdk/examples` +- Update go.mod with dependencies: oapi-codegen, go-retryablehttp, testify +- Set up code generation tooling and make targets + +#### 1.2 Code Generation Setup +- Install and configure oapi-codegen +- Create generation configuration targeting key swagger definitions +- Set up automated generation pipeline in Makefile/scripts + +#### 1.3 Generate Core Types +- Generate Go types from swagger: RegionApp, RegionAppInst, RegionCloudlet +- Generate GPU driver types: RegionGPUDriver, GPUDriverBuildMember +- Create sdk/client/types.go with generated + manually curated types +- Add JSON tags and validation as needed + +#### 1.4 Core Client Infrastructure +- Implement Client struct extending existing client patterns from prototype +- Create AuthProvider interface with StaticTokenProvider implementation +- Add configuration options pattern (WithHTTPClient, WithAuth, WithRetry) +- Implement NewClient() constructor with sensible defaults + +#### 1.5 Basic HTTP Transport +- Create internal/http package with retryable HTTP client wrapper +- Implement context-aware request building and execution +- Add basic error wrapping for HTTP failures +- Create generic call[T]() function similar to existing prototype + +### Phase 2: Core API Implementation (Week 2) + +#### 2.1 App Management APIs +- Implement CreateApp() mapping to POST /auth/ctrl/CreateApp +- Add input validation and structured error handling +- Create unit tests with httptest mock server +- Document API mapping to swagger endpoints + +#### 2.2 App Query and Lifecycle APIs +- Implement ShowApp() and ShowApps() mapping to POST /auth/ctrl/ShowApp +- Implement DeleteApp() mapping to POST /auth/ctrl/DeleteApp +- Add filtering and pagination support where applicable +- Create comprehensive unit test coverage + +#### 2.3 AppInstance Creation APIs +- Implement CreateAppInst() mapping to POST /auth/ctrl/CreateAppInst +- Handle complex nested structures (AppKey, CloudletKey, Flavor) +- Add validation for required fields and relationships +- Test with realistic app instance configurations + +#### 2.4 AppInstance Management APIs +- Implement ShowAppInst()/ShowAppInstances() for querying instances +- Implement RefreshAppInst() mapping to POST /auth/ctrl/RefreshAppInst +- Implement DeleteAppInst() mapping to POST /auth/ctrl/DeleteAppInst +- Add state management and status tracking + +#### 2.5 HTTP Reliability - Basic Features +- Integrate go-retryablehttp with configurable retry policies +- Add exponential backoff with jitter for transient failures +- Implement context timeout and cancellation propagation +- Add request/response debug logging hooks + +#### 2.6 Testing Framework +- Create comprehensive httptest-based mock server +- Write unit tests for all implemented API methods +- Test error conditions, timeouts, and retry behavior +- Add authentication provider unit tests + +### Phase 3: Extended APIs & Reliability (Week 3) + +#### 3.1 Cloudlet Management APIs +- Implement CreateCloudlet() and DeleteCloudlet() operations +- Add cloudlet state management and validation +- Create unit tests for cloudlet lifecycle operations +- Handle cloudlet-specific error conditions + +#### 3.2 Cloudlet Resource APIs +- Implement GetCloudletManifest() mapping to POST /auth/ctrl/GetCloudletManifest +- Implement GetCloudletResourceUsage() mapping to POST /auth/ctrl/GetCloudletResourceUsage +- Add resource usage monitoring and reporting capabilities +- Test with various cloudlet configurations + +#### 3.3 Enhanced Error Handling +- Create APIError struct with StatusCode, Code, Message, Body fields +- Map HTTP status codes to meaningful error types and constants +- Implement ErrResourceNotFound and other semantic error types +- Add error context with full request/response details for debugging + +#### 3.4 Advanced Reliability Features +- Add retry policy configuration per operation type (idempotent vs stateful) +- Implement operation-specific timeout configurations +- Add circuit breaker hooks for optional client-side protection +- Create observability interfaces for metrics collection + +#### 3.5 GPU Driver APIs (Optional Extension) +- Implement CreateGPUDriver() mapping to swagger GPU driver endpoints +- Implement GetGPUDriverBuildURL() for driver download workflows +- Add GPU driver lifecycle management +- Test GPU driver build and deployment scenarios + +#### 3.6 Integration Testing +- Create integration test suite with configurable API endpoints +- Add environment-based test configuration (staging/prod endpoints) +- Test end-to-end workflows: app creation β†’ instance deployment β†’ cleanup +- Add performance benchmarks for critical API paths + +### Phase 4: CLI Integration & Polish (Week 4) + +#### 4.1 CLI Refactoring +- Refactor existing cmd/app.go to use new SDK instead of direct HTTP client +- Maintain full backward compatibility with existing CLI interface +- Update cmd/instance.go to leverage SDK's enhanced error handling +- Ensure configuration continuity (same config files, env vars, flags) + +#### 4.2 New CLI Commands +- Add cloudlet management commands: `edge-connect cloudlet create/show/delete` +- Add cloudlet resource commands: `edge-connect cloudlet manifest/usage` +- Implement `edge-connect gpu` commands for GPU driver management +- Add batch operation commands for common deployment workflows + +#### 4.3 Comprehensive Examples +- Write examples/deploy_app.go: complete app creation and deployment workflow +- Create examples/cloudlet_management.go: cloudlet lifecycle and monitoring +- Add examples/batch_operations.go: bulk app deployment and management +- Create examples/error_handling.go: demonstrating robust error handling patterns + +#### 4.4 Documentation +- Write comprehensive README with API mapping to swagger endpoints +- Create godoc documentation for all public APIs and types +- Add migration guide from existing client patterns to new SDK +- Document authentication, configuration, and best practices + +#### 4.5 Testing and Quality +- Add golangci-lint configuration and resolve all linting issues +- Achieve >90% test coverage across all packages +- Add integration test CI pipeline with test API endpoints +- Create performance regression test suite + +#### 4.6 Release Preparation +- Add semantic versioning and release automation (goreleaser) +- Create changelog and release notes templates +- Add cross-platform build and distribution +- Performance optimization and memory usage analysis + +## Acceptance Criteria + +### MVP Completion +- [ ] SDK compiles and passes all tests with zero linter warnings +- [ ] Core APIs implemented: App and AppInstance full lifecycle management +- [ ] Authentication works with Bearer token against real MC endpoints +- [ ] CLI maintains backward compatibility while using new SDK internally +- [ ] Examples demonstrate real-world workflows with proper error handling +- [ ] Documentation maps SDK functions to swagger endpoints with citations + +### Quality Gates +- [ ] >90% test coverage across sdk/client and sdk/internal packages +- [ ] Integration tests pass against staging MC environment +- [ ] Performance benchmarks show <500ms p95 for core operations +- [ ] Memory usage remains constant under load (no leaks) +- [ ] All examples run successfully and produce expected outputs + +### Documentation Standards +- [ ] All public APIs have comprehensive godoc comments +- [ ] README includes quick start guide and common usage patterns +- [ ] Migration guide helps users transition from prototype client +- [ ] API mapping documentation references specific swagger endpoints +- [ ] Security and authentication best practices documented + +## Risk Mitigation + +### Technical Risks +- **Swagger spec changes**: Pin to specific swagger version, add change detection +- **API authentication changes**: Abstract auth via provider interface +- **Performance at scale**: Implement connection pooling and request batching +- **Breaking changes in dependencies**: Pin versions, gradual upgrade strategy + +### Project Risks +- **Scope creep**: Focus on MVP core APIs first, defer advanced features to v1+ +- **Integration complexity**: Maintain existing CLI behavior exactly during refactoring +- **Testing coverage gaps**: Prioritize integration tests for critical user workflows +- **Documentation debt**: Write docs incrementally during implementation, not after + +## Success Metrics + +- **Developer Adoption**: SDK reduces boilerplate code by >60% vs direct HTTP calls +- **Reliability**: <1% failure rate on retry-eligible operations under normal load +- **Performance**: API calls complete within 2x timeout of direct HTTP equivalent +- **Maintainability**: New API endpoints can be added with <4 hours effort +- **Documentation**: Developers can complete first integration within 30 minutes + +## Next Steps + +Upon approval of this plan: +1. Begin Phase 1.1 (Project Structure Setup) +2. Set up development environment with all required dependencies +3. Create initial PR with project structure and tooling setup +4. Begin iterative development following the phase breakdown above + +This plan leverages the existing prototype's proven patterns while adding the robustness, typing, and extensibility needed for production SDK usage. \ No newline at end of file diff --git a/project.md b/project.md new file mode 100644 index 0000000..4447562 --- /dev/null +++ b/project.md @@ -0,0 +1,157 @@ +# Edge Connect Client - Project Analysis + +## Overview +The Edge Connect Client is a command-line interface (CLI) tool built in Go for managing Edge Connect applications and their instances. It provides a structured way to interact with Edge Connect APIs for creating, showing, listing, and deleting applications and application instances. + +## Project Structure + +``` +edge-connect-client/ +β”œβ”€β”€ .claude/ # Claude Code configuration and commands +β”œβ”€β”€ api/ +β”‚ └── swagger.json # API specification (370KB) +β”œβ”€β”€ client/ # Core client library +β”‚ β”œβ”€β”€ client.go # HTTP client implementation +β”‚ └── models.go # Data models and types +β”œβ”€β”€ cmd/ # CLI command implementations +β”‚ β”œβ”€β”€ root.go # Root command and configuration +β”‚ β”œβ”€β”€ app.go # Application management commands +β”‚ └── instance.go # Instance management commands +β”œβ”€β”€ main.go # Application entry point +β”œβ”€β”€ go.mod # Go module definition +β”œβ”€β”€ go.sum # Dependency checksums +β”œβ”€β”€ README.md # Documentation +β”œβ”€β”€ config.yaml.example # Configuration template +β”œβ”€β”€ Dockerfile # Empty container definition +└── .gitignore # Git ignore rules +``` + +## Architecture + +### Core Components + +#### 1. Main Entry Point (`main.go`) +- Simple entry point that delegates to the command package +- Follows standard Go CLI application pattern + +#### 2. Command Layer (`cmd/`) +- **Root Command** (`root.go`): Base command with global configuration + - Uses Cobra for CLI framework + - Uses Viper for configuration management + - Supports config files, environment variables, and command-line flags + - Configuration precedence: flags β†’ env vars β†’ config file + +- **App Commands** (`app.go`): Application lifecycle management + - Create, show, list, delete applications + - Handles organization, name, version, and region parameters + +- **Instance Commands** (`instance.go`): Instance lifecycle management + - Create, show, list, delete application instances + - Manages cloudlet assignments and flavors + +#### 3. Client Layer (`client/`) +- **HTTP Client** (`client.go`): Core API communication + - Token-based authentication with login endpoint + - Generic `call()` function for API requests + - Structured error handling with custom `ErrResourceNotFound` + - JSON-based request/response handling + +- **Models** (`models.go`): Type definitions and data structures + - Generic response handling with `Responses[T]` and `Response[T]` + - Domain models: `App`, `AppInstance`, `AppKey`, `CloudletKey`, `Flavor` + - Input types: `NewAppInput`, `NewAppInstanceInput` + - Message interface for error handling + +### Configuration Management +- **File-based**: `$HOME/.edge-connect.yaml` (default) or custom via `--config` +- **Environment Variables**: Prefixed with `EDGE_CONNECT_` + - `EDGE_CONNECT_BASE_URL` + - `EDGE_CONNECT_USERNAME` + - `EDGE_CONNECT_PASSWORD` +- **Command-line Flags**: Override other sources + +## Dependencies + +### Direct Dependencies +- **Cobra v1.10.1**: CLI framework for command structure and parsing +- **Viper v1.21.0**: Configuration management (files, env vars, flags) + +### Key Indirect Dependencies +- `fsnotify`: File system watching for config changes +- `go-viper/mapstructure`: Configuration unmarshaling +- `pelletier/go-toml`: TOML configuration support +- Standard Go libraries for HTTP, JSON, system operations + +## API Integration + +### Authentication Flow +1. Client sends username/password to `/api/v1/login` +2. Receives JWT token in response +3. Token included in `Authorization: Bearer` header for subsequent requests + +### API Endpoints +- `/api/v1/auth/ctrl/CreateApp` - Create applications +- `/api/v1/auth/ctrl/ShowApp` - Retrieve applications +- `/api/v1/auth/ctrl/DeleteApp` - Delete applications +- `/api/v1/auth/ctrl/CreateAppInst` - Create instances +- `/api/v1/auth/ctrl/ShowAppInst` - Retrieve instances +- `/api/v1/auth/ctrl/DeleteAppInst` - Delete instances + +### Response Handling +- Streaming JSON responses parsed line-by-line +- Generic type-safe response wrapper +- Comprehensive error handling with status codes +- Built-in logging for debugging + +## Key Features + +### Application Management +- Multi-tenant support with organization scoping +- Version-aware application handling +- Region-based deployments +- Configurable security rules and deployment options + +### Instance Management +- Cloudlet-based instance deployment +- Flavor selection for resource allocation +- Application-to-instance relationship tracking +- State and power state monitoring + +### Error Handling +- Custom error types (`ErrResourceNotFound`) +- HTTP status code awareness +- Detailed error messages with context +- Graceful handling of missing resources + +## Development Notes + +### Code Quality +- Clean separation of concerns (CLI/Client/Models) +- Generic programming for type safety +- Consistent error handling patterns +- Comprehensive logging for troubleshooting + +### Configuration +- Flexible configuration system supporting multiple sources +- Secure credential handling via environment variables +- Example configuration provided for easy setup + +### API Design +- RESTful API integration with structured endpoints +- Token-based security model +- Streaming response handling for efficiency +- Comprehensive swagger specification (370KB) + +## Missing Components +- Empty Dockerfile suggests containerization is planned but not implemented +- No tests directory - testing framework needs to be established +- No CI/CD configuration visible +- Limited error recovery and retry mechanisms + +## Potential Improvements +1. **Testing**: Implement unit and integration tests +2. **Containerization**: Complete Docker implementation +3. **Retry Logic**: Add resilient API call mechanisms +4. **Configuration Validation**: Validate config before use +5. **Output Formatting**: Add JSON/YAML output options +6. **Caching**: Implement token caching to reduce login calls \ No newline at end of file diff --git a/sdk/client/apps.go b/sdk/client/apps.go new file mode 100644 index 0000000..f6fbe2a --- /dev/null +++ b/sdk/client/apps.go @@ -0,0 +1,214 @@ +// ABOUTME: Application lifecycle management APIs for EdgeXR Master Controller +// ABOUTME: Provides typed methods for creating, querying, and deleting applications + +package client + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + + sdkhttp "edp.buildth.ing/DevFW-CICD/edge-connect-client/sdk/internal/http" +) + +var ( + // ErrResourceNotFound indicates the requested resource was not found + ErrResourceNotFound = fmt.Errorf("resource not found") +) + +// CreateApp creates a new application in the specified region +// Maps to POST /auth/ctrl/CreateApp +func (c *Client) CreateApp(ctx context.Context, input *NewAppInput) error { + transport := c.getTransport() + url := c.BaseURL + "/api/v1/auth/ctrl/CreateApp" + + resp, err := transport.Call(ctx, "POST", url, input) + if err != nil { + return fmt.Errorf("CreateApp failed: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode >= 400 { + return c.handleErrorResponse(resp, "CreateApp") + } + + c.logf("CreateApp: %s/%s version %s created successfully", + input.App.Key.Organization, input.App.Key.Name, input.App.Key.Version) + + return nil +} + +// ShowApp retrieves a single application by key and region +// Maps to POST /auth/ctrl/ShowApp +func (c *Client) ShowApp(ctx context.Context, appKey AppKey, region string) (App, error) { + transport := c.getTransport() + url := c.BaseURL + "/api/v1/auth/ctrl/ShowApp" + + filter := AppFilter{ + AppKey: appKey, + Region: region, + } + + resp, err := transport.Call(ctx, "POST", url, filter) + if err != nil { + return App{}, fmt.Errorf("ShowApp failed: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode == http.StatusNotFound { + return App{}, fmt.Errorf("app %s/%s version %s in region %s: %w", + appKey.Organization, appKey.Name, appKey.Version, region, ErrResourceNotFound) + } + + if resp.StatusCode >= 400 { + return App{}, c.handleErrorResponse(resp, "ShowApp") + } + + // Parse streaming JSON response + var apps []App + if err := c.parseStreamingResponse(resp, &apps); err != nil { + return App{}, fmt.Errorf("ShowApp failed to parse response: %w", err) + } + + if len(apps) == 0 { + return App{}, fmt.Errorf("app %s/%s version %s in region %s: %w", + appKey.Organization, appKey.Name, appKey.Version, region, ErrResourceNotFound) + } + + return apps[0], nil +} + +// ShowApps retrieves all applications matching the filter criteria +// Maps to POST /auth/ctrl/ShowApp +func (c *Client) ShowApps(ctx context.Context, appKey AppKey, region string) ([]App, error) { + transport := c.getTransport() + url := c.BaseURL + "/api/v1/auth/ctrl/ShowApp" + + filter := AppFilter{ + AppKey: appKey, + Region: region, + } + + resp, err := transport.Call(ctx, "POST", url, filter) + if err != nil { + return nil, fmt.Errorf("ShowApps failed: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode >= 400 && resp.StatusCode != http.StatusNotFound { + return nil, c.handleErrorResponse(resp, "ShowApps") + } + + var apps []App + if resp.StatusCode == http.StatusNotFound { + return apps, nil // Return empty slice for not found + } + + if err := c.parseStreamingResponse(resp, &apps); err != nil { + return nil, fmt.Errorf("ShowApps failed to parse response: %w", err) + } + + c.logf("ShowApps: found %d apps matching criteria", len(apps)) + return apps, nil +} + +// DeleteApp removes an application from the specified region +// Maps to POST /auth/ctrl/DeleteApp +func (c *Client) DeleteApp(ctx context.Context, appKey AppKey, region string) error { + transport := c.getTransport() + url := c.BaseURL + "/api/v1/auth/ctrl/DeleteApp" + + filter := AppFilter{ + AppKey: appKey, + Region: region, + } + + resp, err := transport.Call(ctx, "POST", url, filter) + if err != nil { + return fmt.Errorf("DeleteApp failed: %w", err) + } + defer resp.Body.Close() + + // 404 is acceptable for delete operations (already deleted) + if resp.StatusCode >= 400 && resp.StatusCode != http.StatusNotFound { + return c.handleErrorResponse(resp, "DeleteApp") + } + + c.logf("DeleteApp: %s/%s version %s deleted successfully", + appKey.Organization, appKey.Name, appKey.Version) + + return nil +} + +// parseStreamingResponse parses the EdgeXR streaming JSON response format +func (c *Client) parseStreamingResponse(resp *http.Response, result interface{}) error { + var responses []Response[App] + + parseErr := sdkhttp.ParseJSONLines(resp.Body, func(line []byte) error { + var response Response[App] + if err := json.Unmarshal(line, &response); err != nil { + return err + } + responses = append(responses, response) + return nil + }) + + if parseErr != nil { + return parseErr + } + + // Extract data from responses + var apps []App + var messages []string + + for _, response := range responses { + if response.HasData() { + apps = append(apps, response.Data) + } + if response.IsMessage() { + messages = append(messages, response.Data.GetMessage()) + } + } + + // If we have error messages, return them + if len(messages) > 0 { + return &APIError{ + StatusCode: resp.StatusCode, + Messages: messages, + } + } + + // Set result based on type + switch v := result.(type) { + case *[]App: + *v = apps + default: + return fmt.Errorf("unsupported result type: %T", result) + } + + return nil +} + +// getTransport creates an HTTP transport with current client settings +func (c *Client) getTransport() *sdkhttp.Transport { + return sdkhttp.NewTransport( + sdkhttp.RetryOptions{ + MaxRetries: c.RetryOpts.MaxRetries, + InitialDelay: c.RetryOpts.InitialDelay, + MaxDelay: c.RetryOpts.MaxDelay, + Multiplier: c.RetryOpts.Multiplier, + RetryableHTTPStatusCodes: c.RetryOpts.RetryableHTTPStatusCodes, + }, + c.AuthProvider, + c.Logger, + ) +} + +// handleErrorResponse creates an appropriate error from HTTP error response +func (c *Client) handleErrorResponse(resp *http.Response, operation string) error { + return &APIError{ + StatusCode: resp.StatusCode, + Messages: []string{fmt.Sprintf("%s failed with status %d", operation, resp.StatusCode)}, + } +} \ No newline at end of file diff --git a/sdk/client/apps_test.go b/sdk/client/apps_test.go new file mode 100644 index 0000000..052ee03 --- /dev/null +++ b/sdk/client/apps_test.go @@ -0,0 +1,319 @@ +// ABOUTME: Unit tests for App management APIs using httptest mock server +// ABOUTME: Tests create, show, list, and delete operations with error conditions + +package client + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestCreateApp(t *testing.T) { + tests := []struct { + name string + input *NewAppInput + mockStatusCode int + mockResponse string + expectError bool + }{ + { + name: "successful creation", + input: &NewAppInput{ + Region: "us-west", + App: App{ + Key: AppKey{ + Organization: "testorg", + Name: "testapp", + Version: "1.0.0", + }, + Deployment: "kubernetes", + }, + }, + mockStatusCode: 200, + mockResponse: `{"message": "success"}`, + expectError: false, + }, + { + name: "validation error", + input: &NewAppInput{ + Region: "us-west", + App: App{ + Key: AppKey{ + Organization: "", + Name: "testapp", + Version: "1.0.0", + }, + }, + }, + mockStatusCode: 400, + mockResponse: `{"message": "organization is required"}`, + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Create mock server + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "POST", r.Method) + assert.Equal(t, "/api/v1/auth/ctrl/CreateApp", r.URL.Path) + assert.Equal(t, "application/json", r.Header.Get("Content-Type")) + + w.WriteHeader(tt.mockStatusCode) + w.Write([]byte(tt.mockResponse)) + })) + defer server.Close() + + // Create client + client := NewClient(server.URL, + WithHTTPClient(&http.Client{Timeout: 5 * time.Second}), + WithAuthProvider(NewStaticTokenProvider("test-token")), + ) + + // Execute test + ctx := context.Background() + err := client.CreateApp(ctx, tt.input) + + // Verify results + if tt.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} + +func TestShowApp(t *testing.T) { + tests := []struct { + name string + appKey AppKey + region string + mockStatusCode int + mockResponse string + expectError bool + expectNotFound bool + }{ + { + name: "successful show", + appKey: AppKey{ + Organization: "testorg", + Name: "testapp", + Version: "1.0.0", + }, + region: "us-west", + mockStatusCode: 200, + mockResponse: `{"data": {"key": {"organization": "testorg", "name": "testapp", "version": "1.0.0"}, "deployment": "kubernetes"}} +`, + expectError: false, + expectNotFound: false, + }, + { + name: "app not found", + appKey: AppKey{ + Organization: "testorg", + Name: "nonexistent", + Version: "1.0.0", + }, + region: "us-west", + mockStatusCode: 404, + mockResponse: "", + expectError: true, + expectNotFound: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Create mock server + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "POST", r.Method) + assert.Equal(t, "/api/v1/auth/ctrl/ShowApp", r.URL.Path) + + w.WriteHeader(tt.mockStatusCode) + if tt.mockResponse != "" { + w.Write([]byte(tt.mockResponse)) + } + })) + defer server.Close() + + // Create client + client := NewClient(server.URL, + WithHTTPClient(&http.Client{Timeout: 5 * time.Second}), + ) + + // Execute test + ctx := context.Background() + app, err := client.ShowApp(ctx, tt.appKey, tt.region) + + // Verify results + if tt.expectError { + assert.Error(t, err) + if tt.expectNotFound { + assert.Contains(t, err.Error(), "resource not found") + } + } else { + require.NoError(t, err) + assert.Equal(t, tt.appKey.Organization, app.Key.Organization) + assert.Equal(t, tt.appKey.Name, app.Key.Name) + assert.Equal(t, tt.appKey.Version, app.Key.Version) + } + }) + } +} + +func TestShowApps(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "POST", r.Method) + assert.Equal(t, "/api/v1/auth/ctrl/ShowApp", r.URL.Path) + + // Verify request body + var filter AppFilter + err := json.NewDecoder(r.Body).Decode(&filter) + require.NoError(t, err) + assert.Equal(t, "testorg", filter.AppKey.Organization) + assert.Equal(t, "us-west", filter.Region) + + // Return multiple apps + response := `{"data": {"key": {"organization": "testorg", "name": "app1", "version": "1.0.0"}, "deployment": "kubernetes"}} +{"data": {"key": {"organization": "testorg", "name": "app2", "version": "1.0.0"}, "deployment": "docker"}} +` + w.WriteHeader(200) + w.Write([]byte(response)) + })) + defer server.Close() + + client := NewClient(server.URL) + ctx := context.Background() + + apps, err := client.ShowApps(ctx, AppKey{Organization: "testorg"}, "us-west") + + require.NoError(t, err) + assert.Len(t, apps, 2) + assert.Equal(t, "app1", apps[0].Key.Name) + assert.Equal(t, "app2", apps[1].Key.Name) +} + +func TestDeleteApp(t *testing.T) { + tests := []struct { + name string + appKey AppKey + region string + mockStatusCode int + expectError bool + }{ + { + name: "successful deletion", + appKey: AppKey{ + Organization: "testorg", + Name: "testapp", + Version: "1.0.0", + }, + region: "us-west", + mockStatusCode: 200, + expectError: false, + }, + { + name: "already deleted (404 ok)", + appKey: AppKey{ + Organization: "testorg", + Name: "testapp", + Version: "1.0.0", + }, + region: "us-west", + mockStatusCode: 404, + expectError: false, + }, + { + name: "server error", + appKey: AppKey{ + Organization: "testorg", + Name: "testapp", + Version: "1.0.0", + }, + region: "us-west", + mockStatusCode: 500, + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "POST", r.Method) + assert.Equal(t, "/api/v1/auth/ctrl/DeleteApp", r.URL.Path) + + w.WriteHeader(tt.mockStatusCode) + })) + defer server.Close() + + client := NewClient(server.URL) + ctx := context.Background() + + err := client.DeleteApp(ctx, tt.appKey, tt.region) + + if tt.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} + +func TestClientOptions(t *testing.T) { + t.Run("with auth provider", func(t *testing.T) { + authProvider := NewStaticTokenProvider("test-token") + client := NewClient("https://example.com", + WithAuthProvider(authProvider), + ) + + assert.Equal(t, authProvider, client.AuthProvider) + }) + + t.Run("with custom HTTP client", func(t *testing.T) { + httpClient := &http.Client{Timeout: 10 * time.Second} + client := NewClient("https://example.com", + WithHTTPClient(httpClient), + ) + + assert.Equal(t, httpClient, client.HTTPClient) + }) + + t.Run("with retry options", func(t *testing.T) { + retryOpts := RetryOptions{MaxRetries: 5} + client := NewClient("https://example.com", + WithRetryOptions(retryOpts), + ) + + assert.Equal(t, 5, client.RetryOpts.MaxRetries) + }) +} + +func TestAPIError(t *testing.T) { + err := &APIError{ + StatusCode: 400, + Messages: []string{"validation failed", "name is required"}, + } + + assert.Equal(t, "validation failed", err.Error()) + assert.Equal(t, 400, err.StatusCode) + assert.Len(t, err.Messages, 2) +} + +// Helper function to create a test server that handles streaming JSON responses +func createStreamingJSONServer(responses []string, statusCode int) *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(statusCode) + for _, response := range responses { + w.Write([]byte(response + "\n")) + } + })) +} \ No newline at end of file diff --git a/sdk/client/auth.go b/sdk/client/auth.go new file mode 100644 index 0000000..1f19450 --- /dev/null +++ b/sdk/client/auth.go @@ -0,0 +1,46 @@ +// ABOUTME: Authentication providers for EdgeXR Master Controller API +// ABOUTME: Supports Bearer token authentication with pluggable provider interface + +package client + +import ( + "context" + "net/http" +) + +// AuthProvider interface for attaching authentication to requests +type AuthProvider interface { + // Attach adds authentication headers to the request + Attach(ctx context.Context, req *http.Request) error +} + +// StaticTokenProvider implements Bearer token authentication with a fixed token +type StaticTokenProvider struct { + Token string +} + +// NewStaticTokenProvider creates a new static token provider +func NewStaticTokenProvider(token string) *StaticTokenProvider { + return &StaticTokenProvider{Token: token} +} + +// Attach adds the Bearer token to the request Authorization header +func (s *StaticTokenProvider) Attach(ctx context.Context, req *http.Request) error { + if s.Token != "" { + req.Header.Set("Authorization", "Bearer "+s.Token) + } + return nil +} + +// NoAuthProvider implements no authentication (for testing or public endpoints) +type NoAuthProvider struct{} + +// NewNoAuthProvider creates a new no-auth provider +func NewNoAuthProvider() *NoAuthProvider { + return &NoAuthProvider{} +} + +// Attach does nothing (no authentication) +func (n *NoAuthProvider) Attach(ctx context.Context, req *http.Request) error { + return nil +} \ No newline at end of file diff --git a/sdk/client/client.go b/sdk/client/client.go new file mode 100644 index 0000000..adc5294 --- /dev/null +++ b/sdk/client/client.go @@ -0,0 +1,105 @@ +// ABOUTME: Core EdgeXR Master Controller SDK client with HTTP transport and auth +// ABOUTME: Provides typed APIs for app, instance, and cloudlet management operations + +package client + +import ( + "net/http" + "strings" + "time" +) + +// Client represents the EdgeXR Master Controller SDK client +type Client struct { + BaseURL string + HTTPClient *http.Client + AuthProvider AuthProvider + RetryOpts RetryOptions + Logger Logger +} + +// RetryOptions configures retry behavior for API calls +type RetryOptions struct { + MaxRetries int + InitialDelay time.Duration + MaxDelay time.Duration + Multiplier float64 + RetryableHTTPStatusCodes []int +} + +// Logger interface for optional logging +type Logger interface { + Printf(format string, v ...interface{}) +} + +// DefaultRetryOptions returns sensible default retry configuration +func DefaultRetryOptions() RetryOptions { + return RetryOptions{ + MaxRetries: 3, + InitialDelay: 1 * time.Second, + MaxDelay: 30 * time.Second, + Multiplier: 2.0, + RetryableHTTPStatusCodes: []int{ + http.StatusRequestTimeout, + http.StatusTooManyRequests, + http.StatusInternalServerError, + http.StatusBadGateway, + http.StatusServiceUnavailable, + http.StatusGatewayTimeout, + }, + } +} + +// Option represents a configuration option for the client +type Option func(*Client) + +// WithHTTPClient sets a custom HTTP client +func WithHTTPClient(client *http.Client) Option { + return func(c *Client) { + c.HTTPClient = client + } +} + +// WithAuthProvider sets the authentication provider +func WithAuthProvider(auth AuthProvider) Option { + return func(c *Client) { + c.AuthProvider = auth + } +} + +// WithRetryOptions sets retry configuration +func WithRetryOptions(opts RetryOptions) Option { + return func(c *Client) { + c.RetryOpts = opts + } +} + +// WithLogger sets a logger for debugging +func WithLogger(logger Logger) Option { + return func(c *Client) { + c.Logger = logger + } +} + +// NewClient creates a new EdgeXR SDK client +func NewClient(baseURL string, options ...Option) *Client { + client := &Client{ + BaseURL: strings.TrimRight(baseURL, "/"), + HTTPClient: &http.Client{Timeout: 30 * time.Second}, + AuthProvider: NewNoAuthProvider(), + RetryOpts: DefaultRetryOptions(), + } + + for _, opt := range options { + opt(client) + } + + return client +} + +// logf logs a message if a logger is configured +func (c *Client) logf(format string, v ...interface{}) { + if c.Logger != nil { + c.Logger.Printf(format, v...) + } +} \ No newline at end of file diff --git a/sdk/client/types.go b/sdk/client/types.go new file mode 100644 index 0000000..16b14e4 --- /dev/null +++ b/sdk/client/types.go @@ -0,0 +1,221 @@ +// ABOUTME: Core type definitions for EdgeXR Master Controller SDK +// ABOUTME: These types are based on the swagger API specification and existing client patterns + +package client + +import "time" + +// Message interface for types that can provide error messages +type Message interface { + GetMessage() string +} + +// Base message type for API responses +type msg struct { + Message string `json:"message,omitempty"` +} + +func (m msg) GetMessage() string { + return m.Message +} + +// AppKey uniquely identifies an application +type AppKey struct { + Organization string `json:"organization"` + Name string `json:"name,omitempty"` + Version string `json:"version,omitempty"` +} + +// CloudletKey uniquely identifies a cloudlet +type CloudletKey struct { + Organization string `json:"organization"` + Name string `json:"name"` +} + +// AppInstanceKey uniquely identifies an application instance +type AppInstanceKey struct { + Organization string `json:"organization"` + Name string `json:"name"` + CloudletKey CloudletKey `json:"cloudlet_key"` +} + +// Flavor defines resource allocation for instances +type Flavor struct { + Name string `json:"name"` +} + +// SecurityRule defines network access rules +type SecurityRule struct { + PortRangeMax int `json:"port_range_max"` + PortRangeMin int `json:"port_range_min"` + Protocol string `json:"protocol"` + RemoteCIDR string `json:"remote_cidr"` +} + +// App represents an application definition +type App struct { + msg `json:",inline"` + Key AppKey `json:"key"` + Deployment string `json:"deployment,omitempty"` + ImageType string `json:"image_type,omitempty"` + ImagePath string `json:"image_path,omitempty"` + AllowServerless bool `json:"allow_serverless,omitempty"` + DefaultFlavor Flavor `json:"defaultFlavor,omitempty"` + ServerlessConfig interface{} `json:"serverless_config,omitempty"` + DeploymentGenerator string `json:"deployment_generator,omitempty"` + DeploymentManifest string `json:"deployment_manifest,omitempty"` + RequiredOutboundConnections []SecurityRule `json:"required_outbound_connections"` +} + +// AppInstance represents a deployed application instance +type AppInstance struct { + msg `json:",inline"` + Key AppInstanceKey `json:"key"` + AppKey AppKey `json:"app_key,omitempty"` + Flavor Flavor `json:"flavor,omitempty"` + State string `json:"state,omitempty"` + PowerState string `json:"power_state,omitempty"` +} + +// Cloudlet represents edge infrastructure +type Cloudlet struct { + msg `json:",inline"` + Key CloudletKey `json:"key"` + Location Location `json:"location"` + IpSupport string `json:"ip_support,omitempty"` + NumDynamicIps int32 `json:"num_dynamic_ips,omitempty"` + State string `json:"state,omitempty"` + Flavor Flavor `json:"flavor,omitempty"` + PhysicalName string `json:"physical_name,omitempty"` + Region string `json:"region,omitempty"` + NotifySrvAddr string `json:"notify_srv_addr,omitempty"` +} + +// Location represents geographical coordinates +type Location struct { + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` +} + +// Input types for API operations + +// NewAppInput represents input for creating an application +type NewAppInput struct { + Region string `json:"region"` + App App `json:"app"` +} + +// NewAppInstanceInput represents input for creating an app instance +type NewAppInstanceInput struct { + Region string `json:"region"` + AppInst AppInstance `json:"appinst"` +} + +// NewCloudletInput represents input for creating a cloudlet +type NewCloudletInput struct { + Region string `json:"region"` + Cloudlet Cloudlet `json:"cloudlet"` +} + +// Response wrapper types + +// Response wraps a single API response +type Response[T Message] struct { + Data T `json:"data"` +} + +func (res *Response[T]) HasData() bool { + return !res.IsMessage() +} + +func (res *Response[T]) IsMessage() bool { + return res.Data.GetMessage() != "" +} + +// Responses wraps multiple API responses with metadata +type Responses[T Message] struct { + Responses []Response[T] `json:"responses,omitempty"` + StatusCode int `json:"-"` +} + +func (r *Responses[T]) GetData() []T { + var data []T + for _, v := range r.Responses { + if v.HasData() { + data = append(data, v.Data) + } + } + return data +} + +func (r *Responses[T]) GetMessages() []string { + var messages []string + for _, v := range r.Responses { + if v.IsMessage() { + messages = append(messages, v.Data.GetMessage()) + } + } + return messages +} + +func (r *Responses[T]) IsSuccessful() bool { + return r.StatusCode >= 200 && r.StatusCode < 400 +} + +func (r *Responses[T]) Error() error { + if r.IsSuccessful() { + return nil + } + return &APIError{ + StatusCode: r.StatusCode, + Messages: r.GetMessages(), + } +} + +// APIError represents an API error with details +type APIError struct { + StatusCode int `json:"status_code"` + Code string `json:"code,omitempty"` + Messages []string `json:"messages,omitempty"` + Body []byte `json:"-"` +} + +func (e *APIError) Error() string { + if len(e.Messages) > 0 { + return e.Messages[0] + } + return "API error" +} + +// Filter types for querying + +// AppFilter represents filters for app queries +type AppFilter struct { + AppKey AppKey `json:"app"` + Region string `json:"region"` +} + +// AppInstanceFilter represents filters for app instance queries +type AppInstanceFilter struct { + AppInstanceKey AppInstanceKey `json:"appinst"` + Region string `json:"region"` +} + +// CloudletFilter represents filters for cloudlet queries +type CloudletFilter struct { + CloudletKey CloudletKey `json:"cloudlet"` + Region string `json:"region"` +} + +// CloudletManifest represents cloudlet deployment manifest +type CloudletManifest struct { + Manifest string `json:"manifest"` + LastModified time.Time `json:"last_modified,omitempty"` +} + +// CloudletResourceUsage represents cloudlet resource utilization +type CloudletResourceUsage struct { + CloudletKey CloudletKey `json:"cloudlet_key"` + Region string `json:"region"` + Usage map[string]interface{} `json:"usage"` +} \ No newline at end of file diff --git a/sdk/examples/deploy_app.go b/sdk/examples/deploy_app.go new file mode 100644 index 0000000..1b88594 --- /dev/null +++ b/sdk/examples/deploy_app.go @@ -0,0 +1,119 @@ +// ABOUTME: Example demonstrating EdgeXR SDK usage for app deployment workflow +// ABOUTME: Shows app creation, querying, and cleanup using the typed SDK APIs + +package main + +import ( + "context" + "fmt" + "log" + "net/http" + "os" + "time" + + "edp.buildth.ing/DevFW-CICD/edge-connect-client/sdk/client" +) + +func main() { + // Configure SDK client + baseURL := getEnvOrDefault("EDGEXR_BASE_URL", "https://hub.apps.edge.platform.mg3.mdb.osc.live/api/v1") + token := getEnvOrDefault("EDGEXR_TOKEN", "") + + if token == "" { + log.Fatal("EDGEXR_TOKEN environment variable is required") + } + + // Create SDK client with authentication and logging + client := client.NewClient(baseURL, + client.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}), + client.WithAuthProvider(client.NewStaticTokenProvider(token)), + client.WithLogger(log.Default()), + ) + + ctx := context.Background() + + // Example application to deploy + app := &client.NewAppInput{ + Region: "us-west", + App: client.App{ + Key: client.AppKey{ + Organization: "myorg", + Name: "my-edge-app", + Version: "1.0.0", + }, + Deployment: "kubernetes", + ImageType: "ImageTypeDocker", + ImagePath: "nginx:latest", + DefaultFlavor: client.Flavor{Name: "m4.small"}, + }, + } + + // Demonstrate app lifecycle + if err := demonstrateAppLifecycle(ctx, client, app); err != nil { + log.Fatalf("App lifecycle demonstration failed: %v", err) + } + + fmt.Println("βœ… SDK example completed successfully!") +} + +func demonstrateAppLifecycle(ctx context.Context, c *client.Client, input *client.NewAppInput) error { + appKey := input.App.Key + region := input.Region + + fmt.Printf("πŸš€ Demonstrating EdgeXR SDK with app: %s/%s v%s\n", + appKey.Organization, appKey.Name, appKey.Version) + + // Step 1: Create the application + fmt.Println("\n1. Creating application...") + if err := c.CreateApp(ctx, input); err != nil { + return fmt.Errorf("failed to create app: %w", err) + } + fmt.Printf("βœ… App created: %s/%s v%s\n", appKey.Organization, appKey.Name, appKey.Version) + + // Step 2: Query the application + fmt.Println("\n2. Querying application...") + app, err := c.ShowApp(ctx, appKey, region) + if err != nil { + return fmt.Errorf("failed to show app: %w", err) + } + fmt.Printf("βœ… App found: %s/%s v%s (deployment: %s)\n", + app.Key.Organization, app.Key.Name, app.Key.Version, app.Deployment) + + // Step 3: List applications in the organization + fmt.Println("\n3. Listing applications...") + filter := client.AppKey{Organization: appKey.Organization} + apps, err := c.ShowApps(ctx, filter, region) + if err != nil { + return fmt.Errorf("failed to list apps: %w", err) + } + fmt.Printf("βœ… Found %d applications in organization '%s'\n", len(apps), appKey.Organization) + + // Step 4: Clean up - delete the application + fmt.Println("\n4. Cleaning up...") + if err := c.DeleteApp(ctx, appKey, region); err != nil { + return fmt.Errorf("failed to delete app: %w", err) + } + fmt.Printf("βœ… App deleted: %s/%s v%s\n", appKey.Organization, appKey.Name, appKey.Version) + + // Step 5: Verify deletion + fmt.Println("\n5. Verifying deletion...") + _, err = c.ShowApp(ctx, appKey, region) + if err != nil { + if fmt.Sprintf("%v", err) == client.ErrResourceNotFound.Error() { + fmt.Printf("βœ… App successfully deleted (not found)\n") + } else { + return fmt.Errorf("unexpected error verifying deletion: %w", err) + } + } else { + return fmt.Errorf("app still exists after deletion") + } + + return nil +} + +func getEnvOrDefault(key, defaultValue string) string { + if value := os.Getenv(key); value != "" { + return value + } + return defaultValue +} \ No newline at end of file diff --git a/sdk/internal/http/transport.go b/sdk/internal/http/transport.go new file mode 100644 index 0000000..5766d7d --- /dev/null +++ b/sdk/internal/http/transport.go @@ -0,0 +1,218 @@ +// ABOUTME: HTTP transport layer with retry logic and request/response handling +// ABOUTME: Provides resilient HTTP communication with context support and error wrapping + +package http + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "math" + "math/rand" + "net/http" + "time" + + "github.com/hashicorp/go-retryablehttp" +) + +// Transport wraps HTTP operations with retry logic and error handling +type Transport struct { + client *retryablehttp.Client + authProvider AuthProvider + logger Logger +} + +// AuthProvider interface for attaching authentication +type AuthProvider interface { + Attach(ctx context.Context, req *http.Request) error +} + +// Logger interface for request/response logging +type Logger interface { + Printf(format string, v ...interface{}) +} + +// RetryOptions configures retry behavior +type RetryOptions struct { + MaxRetries int + InitialDelay time.Duration + MaxDelay time.Duration + Multiplier float64 + RetryableHTTPStatusCodes []int +} + +// NewTransport creates a new HTTP transport with retry capabilities +func NewTransport(opts RetryOptions, auth AuthProvider, logger Logger) *Transport { + client := retryablehttp.NewClient() + + // Configure retry policy + client.RetryMax = opts.MaxRetries + client.RetryWaitMin = opts.InitialDelay + client.RetryWaitMax = opts.MaxDelay + + // Custom retry policy that considers both network errors and HTTP status codes + client.CheckRetry = func(ctx context.Context, resp *http.Response, err error) (bool, error) { + // Default retry for network errors + if err != nil { + return true, nil + } + + // Check if status code is retryable + if resp != nil { + for _, code := range opts.RetryableHTTPStatusCodes { + if resp.StatusCode == code { + return true, nil + } + } + } + + return false, nil + } + + // Custom backoff with jitter + client.Backoff = func(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { + mult := math.Pow(opts.Multiplier, float64(attemptNum)) + sleep := time.Duration(mult) * min + if sleep > max { + sleep = max + } + // Add jitter + jitter := time.Duration(rand.Float64() * float64(sleep) * 0.1) + return sleep + jitter + } + + // Disable default logging if no logger provided + if logger == nil { + client.Logger = nil + } + + return &Transport{ + client: client, + authProvider: auth, + logger: logger, + } +} + +// Call executes an HTTP request with retry logic and returns typed response +func (t *Transport) Call(ctx context.Context, method, url string, body interface{}) (*http.Response, error) { + var reqBody io.Reader + + // Marshal request body if provided + if body != nil { + jsonData, err := json.Marshal(body) + if err != nil { + return nil, fmt.Errorf("failed to marshal request body: %w", err) + } + reqBody = bytes.NewReader(jsonData) + } + + // Create retryable request + req, err := retryablehttp.NewRequestWithContext(ctx, method, url, reqBody) + if err != nil { + return nil, fmt.Errorf("failed to create request: %w", err) + } + + // Set headers + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") + + // Add authentication + if t.authProvider != nil { + if err := t.authProvider.Attach(ctx, req.Request); err != nil { + return nil, fmt.Errorf("failed to attach auth: %w", err) + } + } + + // Log request + if t.logger != nil { + t.logger.Printf("HTTP %s %s", method, url) + } + + // Execute request + resp, err := t.client.Do(req) + if err != nil { + return nil, fmt.Errorf("HTTP request failed: %w", err) + } + + // Log response + if t.logger != nil { + t.logger.Printf("HTTP %s %s -> %d", method, url, resp.StatusCode) + } + + return resp, nil +} + +// CallJSON executes a request and unmarshals the response into a typed result +func (t *Transport) CallJSON(ctx context.Context, method, url string, body interface{}, result interface{}) (*http.Response, error) { + resp, err := t.Call(ctx, method, url, body) + if err != nil { + return resp, err + } + defer resp.Body.Close() + + // Read response body + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return resp, fmt.Errorf("failed to read response body: %w", err) + } + + // For error responses, don't try to unmarshal into result type + if resp.StatusCode >= 400 { + return resp, &HTTPError{ + StatusCode: resp.StatusCode, + Status: resp.Status, + Body: respBody, + } + } + + // Unmarshal successful response + if result != nil && len(respBody) > 0 { + if err := json.Unmarshal(respBody, result); err != nil { + return resp, fmt.Errorf("failed to unmarshal response: %w", err) + } + } + + return resp, nil +} + +// HTTPError represents an HTTP error response +type HTTPError struct { + StatusCode int `json:"status_code"` + Status string `json:"status"` + Body []byte `json:"-"` +} + +func (e *HTTPError) Error() string { + if len(e.Body) > 0 { + return fmt.Sprintf("HTTP %d %s: %s", e.StatusCode, e.Status, string(e.Body)) + } + return fmt.Sprintf("HTTP %d %s", e.StatusCode, e.Status) +} + +// IsRetryable returns true if the error indicates a retryable condition +func (e *HTTPError) IsRetryable() bool { + return e.StatusCode >= 500 || e.StatusCode == 429 || e.StatusCode == 408 +} + +// ParseJSONLines parses streaming JSON response line by line +func ParseJSONLines(body io.Reader, callback func([]byte) error) error { + decoder := json.NewDecoder(body) + + for { + var raw json.RawMessage + if err := decoder.Decode(&raw); err != nil { + if err == io.EOF { + break + } + return fmt.Errorf("failed to decode JSON line: %w", err) + } + + if err := callback(raw); err != nil { + return err + } + } + + return nil +} \ No newline at end of file