diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 0000000..31a2528
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,42 @@
+name: "Update docs"
+
+on:
+ push:
+ tags-ignore:
+ - '*'
+ branches-ignore:
+ - main
+jobs:
+ docs:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Set up Go
+ uses: actions/setup-go@v3
+ with:
+ go-version: 1.21
+
+ - name: Update Swagger
+ run: |
+ go install github.com/swaggo/swag/cmd/swag@latest
+ swag init -g ./cmd/serve.go -o cmd/docs
+
+ - name: Update API.md
+ uses: addnab/docker-run-action@v3
+ with:
+ image: quay.io/goswagger/swagger:latest
+ options: -v ${{ github.workspace }}:/api
+ run: |
+ cd /api
+ swagger generate markdown -f cmd/docs/swagger.json --output api.md
+
+ - name: Add & Commit
+ uses: EndBug/add-and-commit@v9.1.3
+ with:
+ add: '["cmd/docs", "api.md"]'
+ author_name: "DO! DevOps bot"
+ author_email: "info@dodevops.io"
+ message: "docs: Automatic docs update"
+ push: true
diff --git a/README.md b/README.md
index b114f30..bfa481b 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,8 @@ Start the server by running
go run cmd/serve.go
+# Configuration
+
The following environment variables are used for configuration:
* BASE_URL (required): The base URL of the vCenter to connect to like https://vcenter.company.com
@@ -15,23 +17,10 @@ The following environment variables are used for configuration:
* LOG_LEVEL: Maximum log level to use (see (https://pkg.go.dev/github.com/sirupsen/logrus#readme-level-logging)) [INFO]
* TLS_INSECURE_SKIP_VERIFY: If set, will disable TLS verification for the API client
* VCENTER_PROXY_URL: Connect to the vCenter using this proxy
+* EXTERNAL_BASE_URL: Base URL the service is hosted on. Will be used for the Swagger API docs
# APIs
-## /vms
-
-### GET
-
-Return all VM names and their IDs
-
-## /vms/:vm/tags
-
-### GET
-
-Return all assigned tags and their categories for the specified vm `:vm`.
-
-## /vms/:vm/fqdn
-
-### GET
+The service includes a generated OpenAPI documentation available at `/swagger`.
-Return the fqdn of the specified vm `:vm` from the VMware guest tools
\ No newline at end of file
+See [the generated API documentation](api.md)
\ No newline at end of file
diff --git a/api.md b/api.md
new file mode 100644
index 0000000..4359533
--- /dev/null
+++ b/api.md
@@ -0,0 +1,624 @@
+
+
+
+# vmware-rest-proxy
+
+
+## Informations
+
+### Version
+
+0.1.0
+
+### Contact
+
+DO!DevOps info@dodevops.io http://dodevops.io
+
+## Content negotiation
+
+### URI Schemes
+ * http
+
+### Consumes
+ * application/json
+
+### Produces
+ * application/json
+
+## Access control
+
+### Security Schemes
+
+#### BasicAuth
+
+
+
+> **Type**: basic
+
+## All endpoints
+
+### datastore
+
+| Method | URI | Name | Summary |
+|---------|---------|--------|---------|
+| GET | /datastores | [get datastores](#get-datastores) | Retrieve a list of datastores |
+
+
+
+### host
+
+| Method | URI | Name | Summary |
+|---------|---------|--------|---------|
+| GET | /hosts | [get hosts](#get-hosts) | Retrieve a list of ESXi hosts |
+
+
+
+### operations
+
+| Method | URI | Name | Summary |
+|---------|---------|--------|---------|
+| GET | /status | [get status](#get-status) | Checks whether the service is running |
+
+
+
+### vm
+
+| Method | URI | Name | Summary |
+|---------|---------|--------|---------|
+| GET | /vms | [get vms](#get-vms) | Retrieve a list of all vms |
+| GET | /vms/{id}/fqdn | [get vms ID fqdn](#get-vms-id-fqdn) | Get fqdn of VM |
+| GET | /vms/{id}/info | [get vms ID info](#get-vms-id-info) | Get informational data about a VM |
+| GET | /vms/{id}/tags | [get vms ID tags](#get-vms-id-tags) | Retrieve tags |
+
+
+
+## Paths
+
+### Retrieve a list of datastores (*GetDatastores*)
+
+```
+GET /datastores
+```
+
+Fetches a list of registered datastores in the vCenter
+
+#### Produces
+ * application/json
+
+#### Security Requirements
+ * BasicAuth
+
+#### All responses
+| Code | Status | Description | Has headers | Schema |
+|------|--------|-------------|:-----------:|--------|
+| [200](#get-datastores-200) | OK | OK | | [schema](#get-datastores-200-schema) |
+| [400](#get-datastores-400) | Bad Request | Invalid request | | [schema](#get-datastores-400-schema) |
+| [401](#get-datastores-401) | Unauthorized | Authorization is required | | [schema](#get-datastores-401-schema) |
+
+#### Responses
+
+
+##### 200 - OK
+Status: OK
+
+###### Schema
+
+
+
+[EndpointsDatastores](#endpoints-datastores)
+
+##### 400 - Invalid request
+Status: Bad Request
+
+###### Schema
+
+##### 401 - Authorization is required
+Status: Unauthorized
+
+###### Schema
+
+### Retrieve a list of ESXi hosts (*GetHosts*)
+
+```
+GET /hosts
+```
+
+Fetches a list of registered ESXi hosts in the vCenter
+
+#### Produces
+ * application/json
+
+#### Security Requirements
+ * BasicAuth
+
+#### All responses
+| Code | Status | Description | Has headers | Schema |
+|------|--------|-------------|:-----------:|--------|
+| [200](#get-hosts-200) | OK | OK | | [schema](#get-hosts-200-schema) |
+| [400](#get-hosts-400) | Bad Request | Invalid request | | [schema](#get-hosts-400-schema) |
+| [401](#get-hosts-401) | Unauthorized | Authorization is required | | [schema](#get-hosts-401-schema) |
+
+#### Responses
+
+
+##### 200 - OK
+Status: OK
+
+###### Schema
+
+
+
+[EndpointsHosts](#endpoints-hosts)
+
+##### 400 - Invalid request
+Status: Bad Request
+
+###### Schema
+
+##### 401 - Authorization is required
+Status: Unauthorized
+
+###### Schema
+
+### Checks whether the service is running (*GetStatus*)
+
+```
+GET /status
+```
+
+Just responses with a 200 to signal that the service is running
+
+#### Produces
+ * application/json
+
+#### All responses
+| Code | Status | Description | Has headers | Schema |
+|------|--------|-------------|:-----------:|--------|
+| [200](#get-status-200) | OK | OK | | [schema](#get-status-200-schema) |
+
+#### Responses
+
+
+##### 200 - OK
+Status: OK
+
+###### Schema
+
+
+
+[EndpointsStatus](#endpoints-status)
+
+### Retrieve a list of all vms (*GetVms*)
+
+```
+GET /vms
+```
+
+Fetches a list of vms from the vCenter
+
+#### Produces
+ * application/json
+
+#### Security Requirements
+ * BasicAuth
+
+#### All responses
+| Code | Status | Description | Has headers | Schema |
+|------|--------|-------------|:-----------:|--------|
+| [200](#get-vms-200) | OK | OK | | [schema](#get-vms-200-schema) |
+| [400](#get-vms-400) | Bad Request | Invalid request | | [schema](#get-vms-400-schema) |
+| [401](#get-vms-401) | Unauthorized | Authorization is required | | [schema](#get-vms-401-schema) |
+
+#### Responses
+
+
+##### 200 - OK
+Status: OK
+
+###### Schema
+
+
+
+[EndpointsVMS](#endpoints-vm-s)
+
+##### 400 - Invalid request
+Status: Bad Request
+
+###### Schema
+
+##### 401 - Authorization is required
+Status: Unauthorized
+
+###### Schema
+
+### Get fqdn of VM (*GetVmsIDFqdn*)
+
+```
+GET /vms/{id}/fqdn
+```
+
+Try to find out the fqdn of the given VM using the guest tools
+
+#### Produces
+ * application/json
+
+#### Security Requirements
+ * BasicAuth
+
+#### Parameters
+
+| Name | Source | Type | Go type | Separator | Required | Default | Description |
+|------|--------|------|---------|-----------| :------: |---------|-------------|
+| id | `path` | string | `string` | | ✓ | | ID of VM |
+
+#### All responses
+| Code | Status | Description | Has headers | Schema |
+|------|--------|-------------|:-----------:|--------|
+| [200](#get-vms-id-fqdn-200) | OK | OK | | [schema](#get-vms-id-fqdn-200-schema) |
+| [400](#get-vms-id-fqdn-400) | Bad Request | Invalid request | | [schema](#get-vms-id-fqdn-400-schema) |
+| [401](#get-vms-id-fqdn-401) | Unauthorized | Authorization is required | | [schema](#get-vms-id-fqdn-401-schema) |
+
+#### Responses
+
+
+##### 200 - OK
+Status: OK
+
+###### Schema
+
+
+
+[EndpointsFQDN](#endpoints-f-q-d-n)
+
+##### 400 - Invalid request
+Status: Bad Request
+
+###### Schema
+
+##### 401 - Authorization is required
+Status: Unauthorized
+
+###### Schema
+
+### Get informational data about a VM (*GetVmsIDInfo*)
+
+```
+GET /vms/{id}/info
+```
+
+Find out some information about a VM and return them
+
+#### Produces
+ * application/json
+
+#### Security Requirements
+ * BasicAuth
+
+#### Parameters
+
+| Name | Source | Type | Go type | Separator | Required | Default | Description |
+|------|--------|------|---------|-----------| :------: |---------|-------------|
+| id | `path` | string | `string` | | ✓ | | ID of VM |
+
+#### All responses
+| Code | Status | Description | Has headers | Schema |
+|------|--------|-------------|:-----------:|--------|
+| [200](#get-vms-id-info-200) | OK | OK | | [schema](#get-vms-id-info-200-schema) |
+| [400](#get-vms-id-info-400) | Bad Request | Invalid request | | [schema](#get-vms-id-info-400-schema) |
+| [401](#get-vms-id-info-401) | Unauthorized | Authorization is required | | [schema](#get-vms-id-info-401-schema) |
+
+#### Responses
+
+
+##### 200 - OK
+Status: OK
+
+###### Schema
+
+
+
+[APIVMInfo](#api-vm-info)
+
+##### 400 - Invalid request
+Status: Bad Request
+
+###### Schema
+
+##### 401 - Authorization is required
+Status: Unauthorized
+
+###### Schema
+
+### Retrieve tags (*GetVmsIDTags*)
+
+```
+GET /vms/{id}/tags
+```
+
+Retrieve tags and their categories for a vm
+
+#### Produces
+ * application/json
+
+#### Security Requirements
+ * BasicAuth
+
+#### Parameters
+
+| Name | Source | Type | Go type | Separator | Required | Default | Description |
+|------|--------|------|---------|-----------| :------: |---------|-------------|
+| id | `path` | string | `string` | | ✓ | | ID of VM |
+
+#### All responses
+| Code | Status | Description | Has headers | Schema |
+|------|--------|-------------|:-----------:|--------|
+| [200](#get-vms-id-tags-200) | OK | OK | | [schema](#get-vms-id-tags-200-schema) |
+| [400](#get-vms-id-tags-400) | Bad Request | Invalid request | | [schema](#get-vms-id-tags-400-schema) |
+| [401](#get-vms-id-tags-401) | Unauthorized | Authorization is required | | [schema](#get-vms-id-tags-401-schema) |
+
+#### Responses
+
+
+##### 200 - OK
+Status: OK
+
+###### Schema
+
+
+
+[EndpointsTags](#endpoints-tags)
+
+##### 400 - Invalid request
+Status: Bad Request
+
+###### Schema
+
+##### 401 - Authorization is required
+Status: Unauthorized
+
+###### Schema
+
+## Models
+
+### api.Datastore
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| capacity | integer| `int64` | | | | |
+| datastore | string| `string` | | | | |
+| free_space | integer| `int64` | | | | |
+| name | string| `string` | | | | |
+| type | string| `string` | | | | |
+
+
+
+### api.Host
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| connection_state | string| `string` | | | | |
+| host | string| `string` | | | | |
+| name | string| `string` | | | | |
+| power_state | string| `string` | | | | |
+
+
+
+### api.VM
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| name | string| `string` | | | | |
+| power_state | string| `string` | | | | |
+| vm | string| `string` | | | | |
+
+
+
+### api.VMInfo
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| cpu_cores | integer| `int64` | | | | |
+| name | string| `string` | | | | |
+| provisioned_ram | integer| `int64` | | | | |
+| provisioned_storage | integer| `int64` | | | | |
+| used_storage | integer| `int64` | | | | |
+
+
+
+### api.VMTag
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| category | string| `string` | | | Category holds the tag category | |
+| value | string| `string` | | | Value holds the value of the tag | |
+
+
+
+### endpoints.Datastores
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| datastores | [EndpointsDatastoresResult](#endpoints-datastores-result)| `EndpointsDatastoresResult` | | | | |
+
+
+
+### endpoints.DatastoresResult
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| count | integer| `int64` | | | | |
+| datastores | [][APIDatastore](#api-datastore)| `[]*APIDatastore` | | | | |
+
+
+
+### endpoints.FQDN
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| fqdn | string| `string` | | | | |
+
+
+
+### endpoints.Hosts
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| hosts | [EndpointsHostsResult](#endpoints-hosts-result)| `EndpointsHostsResult` | | | | |
+
+
+
+### endpoints.HostsResult
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| count | integer| `int64` | | | | |
+| hosts | [][APIHost](#api-host)| `[]*APIHost` | | | | |
+
+
+
+### endpoints.Status
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| status | string| `string` | | | | |
+
+
+
+### endpoints.Tags
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| tags | [EndpointsTagsResult](#endpoints-tags-result)| `EndpointsTagsResult` | | | | |
+
+
+
+### endpoints.TagsResult
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| count | integer| `int64` | | | | |
+| tags | [][APIVMTag](#api-vm-tag)| `[]*APIVMTag` | | | | |
+
+
+
+### endpoints.VMS
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| vms | [EndpointsVMSResult](#endpoints-vm-s-result)| `EndpointsVMSResult` | | | | |
+
+
+
+### endpoints.VMSResult
+
+
+
+
+
+
+**Properties**
+
+| Name | Type | Go type | Required | Default | Description | Example |
+|------|------|---------|:--------:| ------- |-------------|---------|
+| count | integer| `int64` | | | | |
+| vms | [][APIVM](#api-vm)| `[]*APIVM` | | | | |
+
+
diff --git a/cmd/docs/docs.go b/cmd/docs/docs.go
new file mode 100644
index 0000000..2974152
--- /dev/null
+++ b/cmd/docs/docs.go
@@ -0,0 +1,466 @@
+// Package docs Code generated by swaggo/swag. DO NOT EDIT
+package docs
+
+import "github.com/swaggo/swag"
+
+const docTemplate = `{
+ "schemes": {{ marshal .Schemes }},
+ "swagger": "2.0",
+ "info": {
+ "description": "{{escape .Description}}",
+ "title": "{{.Title}}",
+ "contact": {
+ "name": "DO!DevOps",
+ "url": "http://dodevops.io",
+ "email": "info@dodevops.io"
+ },
+ "version": "{{.Version}}"
+ },
+ "host": "{{.Host}}",
+ "basePath": "{{.BasePath}}",
+ "paths": {
+ "/datastores": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "description": "Fetches a list of registered datastores in the vCenter",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "datastore"
+ ],
+ "summary": "Retrieve a list of datastores",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/endpoints.Datastores"
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Authorization is required"
+ }
+ }
+ }
+ },
+ "/hosts": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "description": "Fetches a list of registered ESXi hosts in the vCenter",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "host"
+ ],
+ "summary": "Retrieve a list of ESXi hosts",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/endpoints.Hosts"
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Authorization is required"
+ }
+ }
+ }
+ },
+ "/status": {
+ "get": {
+ "description": "Just responses with a 200 to signal that the service is running",
+ "produces": [
+ "application/json"
+ ],
+ "summary": "Checks whether the service is running",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/endpoints.Status"
+ }
+ }
+ }
+ }
+ },
+ "/vms": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "description": "Fetches a list of vms from the vCenter",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "vm"
+ ],
+ "summary": "Retrieve a list of all vms",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/endpoints.VMS"
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Authorization is required"
+ }
+ }
+ }
+ },
+ "/vms/{id}/fqdn": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "description": "Try to find out the fqdn of the given VM using the guest tools",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "vm"
+ ],
+ "summary": "Get fqdn of VM",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "ID of VM",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/endpoints.FQDN"
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Authorization is required"
+ }
+ }
+ }
+ },
+ "/vms/{id}/info": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "description": "Find out some information about a VM and return them",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "vm"
+ ],
+ "summary": "Get informational data about a VM",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "ID of VM",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/api.VMInfo"
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Authorization is required"
+ }
+ }
+ }
+ },
+ "/vms/{id}/tags": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "description": "Retrieve tags and their categories for a vm",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "vm"
+ ],
+ "summary": "Retrieve tags",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "ID of VM",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/endpoints.Tags"
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Authorization is required"
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "api.Datastore": {
+ "type": "object",
+ "properties": {
+ "capacity": {
+ "type": "integer"
+ },
+ "datastore": {
+ "type": "string"
+ },
+ "free_space": {
+ "type": "integer"
+ },
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ }
+ }
+ },
+ "api.Host": {
+ "type": "object",
+ "properties": {
+ "connection_state": {
+ "type": "string"
+ },
+ "host": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "power_state": {
+ "type": "string"
+ }
+ }
+ },
+ "api.VM": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "power_state": {
+ "type": "string"
+ },
+ "vm": {
+ "type": "string"
+ }
+ }
+ },
+ "api.VMInfo": {
+ "type": "object",
+ "properties": {
+ "cpu_cores": {
+ "type": "integer"
+ },
+ "name": {
+ "type": "string"
+ },
+ "provisioned_ram": {
+ "type": "integer"
+ },
+ "provisioned_storage": {
+ "type": "integer"
+ },
+ "used_storage": {
+ "type": "integer"
+ }
+ }
+ },
+ "api.VMTag": {
+ "type": "object",
+ "properties": {
+ "category": {
+ "description": "Category holds the tag category",
+ "type": "string"
+ },
+ "value": {
+ "description": "Value holds the value of the tag",
+ "type": "string"
+ }
+ }
+ },
+ "endpoints.Datastores": {
+ "type": "object",
+ "properties": {
+ "datastores": {
+ "$ref": "#/definitions/endpoints.DatastoresResult"
+ }
+ }
+ },
+ "endpoints.DatastoresResult": {
+ "type": "object",
+ "properties": {
+ "count": {
+ "type": "integer"
+ },
+ "datastores": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/api.Datastore"
+ }
+ }
+ }
+ },
+ "endpoints.FQDN": {
+ "type": "object",
+ "properties": {
+ "fqdn": {
+ "type": "string"
+ }
+ }
+ },
+ "endpoints.Hosts": {
+ "type": "object",
+ "properties": {
+ "hosts": {
+ "$ref": "#/definitions/endpoints.HostsResult"
+ }
+ }
+ },
+ "endpoints.HostsResult": {
+ "type": "object",
+ "properties": {
+ "count": {
+ "type": "integer"
+ },
+ "hosts": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/api.Host"
+ }
+ }
+ }
+ },
+ "endpoints.Status": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string"
+ }
+ }
+ },
+ "endpoints.Tags": {
+ "type": "object",
+ "properties": {
+ "tags": {
+ "$ref": "#/definitions/endpoints.TagsResult"
+ }
+ }
+ },
+ "endpoints.TagsResult": {
+ "type": "object",
+ "properties": {
+ "count": {
+ "type": "integer"
+ },
+ "tags": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/api.VMTag"
+ }
+ }
+ }
+ },
+ "endpoints.VMS": {
+ "type": "object",
+ "properties": {
+ "vms": {
+ "$ref": "#/definitions/endpoints.VMSResult"
+ }
+ }
+ },
+ "endpoints.VMSResult": {
+ "type": "object",
+ "properties": {
+ "count": {
+ "type": "integer"
+ },
+ "vms": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/api.VM"
+ }
+ }
+ }
+ }
+ },
+ "securityDefinitions": {
+ "BasicAuth": {
+ "type": "basic"
+ }
+ }
+}`
+
+// SwaggerInfo holds exported Swagger Info so clients can modify it
+var SwaggerInfo = &swag.Spec{
+ Version: "0.1.0",
+ Host: "",
+ BasePath: "",
+ Schemes: []string{},
+ Title: "vmware-rest-proxy",
+ Description: "",
+ InfoInstanceName: "swagger",
+ SwaggerTemplate: docTemplate,
+ LeftDelim: "{{",
+ RightDelim: "}}",
+}
+
+func init() {
+ swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
+}
diff --git a/cmd/docs/swagger.json b/cmd/docs/swagger.json
new file mode 100644
index 0000000..a660f52
--- /dev/null
+++ b/cmd/docs/swagger.json
@@ -0,0 +1,439 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "title": "vmware-rest-proxy",
+ "contact": {
+ "name": "DO!DevOps",
+ "url": "http://dodevops.io",
+ "email": "info@dodevops.io"
+ },
+ "version": "0.1.0"
+ },
+ "paths": {
+ "/datastores": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "description": "Fetches a list of registered datastores in the vCenter",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "datastore"
+ ],
+ "summary": "Retrieve a list of datastores",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/endpoints.Datastores"
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Authorization is required"
+ }
+ }
+ }
+ },
+ "/hosts": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "description": "Fetches a list of registered ESXi hosts in the vCenter",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "host"
+ ],
+ "summary": "Retrieve a list of ESXi hosts",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/endpoints.Hosts"
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Authorization is required"
+ }
+ }
+ }
+ },
+ "/status": {
+ "get": {
+ "description": "Just responses with a 200 to signal that the service is running",
+ "produces": [
+ "application/json"
+ ],
+ "summary": "Checks whether the service is running",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/endpoints.Status"
+ }
+ }
+ }
+ }
+ },
+ "/vms": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "description": "Fetches a list of vms from the vCenter",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "vm"
+ ],
+ "summary": "Retrieve a list of all vms",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/endpoints.VMS"
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Authorization is required"
+ }
+ }
+ }
+ },
+ "/vms/{id}/fqdn": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "description": "Try to find out the fqdn of the given VM using the guest tools",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "vm"
+ ],
+ "summary": "Get fqdn of VM",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "ID of VM",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/endpoints.FQDN"
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Authorization is required"
+ }
+ }
+ }
+ },
+ "/vms/{id}/info": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "description": "Find out some information about a VM and return them",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "vm"
+ ],
+ "summary": "Get informational data about a VM",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "ID of VM",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/api.VMInfo"
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Authorization is required"
+ }
+ }
+ }
+ },
+ "/vms/{id}/tags": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "description": "Retrieve tags and their categories for a vm",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "vm"
+ ],
+ "summary": "Retrieve tags",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "ID of VM",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/endpoints.Tags"
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Authorization is required"
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "api.Datastore": {
+ "type": "object",
+ "properties": {
+ "capacity": {
+ "type": "integer"
+ },
+ "datastore": {
+ "type": "string"
+ },
+ "free_space": {
+ "type": "integer"
+ },
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ }
+ }
+ },
+ "api.Host": {
+ "type": "object",
+ "properties": {
+ "connection_state": {
+ "type": "string"
+ },
+ "host": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "power_state": {
+ "type": "string"
+ }
+ }
+ },
+ "api.VM": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "power_state": {
+ "type": "string"
+ },
+ "vm": {
+ "type": "string"
+ }
+ }
+ },
+ "api.VMInfo": {
+ "type": "object",
+ "properties": {
+ "cpu_cores": {
+ "type": "integer"
+ },
+ "name": {
+ "type": "string"
+ },
+ "provisioned_ram": {
+ "type": "integer"
+ },
+ "provisioned_storage": {
+ "type": "integer"
+ },
+ "used_storage": {
+ "type": "integer"
+ }
+ }
+ },
+ "api.VMTag": {
+ "type": "object",
+ "properties": {
+ "category": {
+ "description": "Category holds the tag category",
+ "type": "string"
+ },
+ "value": {
+ "description": "Value holds the value of the tag",
+ "type": "string"
+ }
+ }
+ },
+ "endpoints.Datastores": {
+ "type": "object",
+ "properties": {
+ "datastores": {
+ "$ref": "#/definitions/endpoints.DatastoresResult"
+ }
+ }
+ },
+ "endpoints.DatastoresResult": {
+ "type": "object",
+ "properties": {
+ "count": {
+ "type": "integer"
+ },
+ "datastores": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/api.Datastore"
+ }
+ }
+ }
+ },
+ "endpoints.FQDN": {
+ "type": "object",
+ "properties": {
+ "fqdn": {
+ "type": "string"
+ }
+ }
+ },
+ "endpoints.Hosts": {
+ "type": "object",
+ "properties": {
+ "hosts": {
+ "$ref": "#/definitions/endpoints.HostsResult"
+ }
+ }
+ },
+ "endpoints.HostsResult": {
+ "type": "object",
+ "properties": {
+ "count": {
+ "type": "integer"
+ },
+ "hosts": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/api.Host"
+ }
+ }
+ }
+ },
+ "endpoints.Status": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string"
+ }
+ }
+ },
+ "endpoints.Tags": {
+ "type": "object",
+ "properties": {
+ "tags": {
+ "$ref": "#/definitions/endpoints.TagsResult"
+ }
+ }
+ },
+ "endpoints.TagsResult": {
+ "type": "object",
+ "properties": {
+ "count": {
+ "type": "integer"
+ },
+ "tags": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/api.VMTag"
+ }
+ }
+ }
+ },
+ "endpoints.VMS": {
+ "type": "object",
+ "properties": {
+ "vms": {
+ "$ref": "#/definitions/endpoints.VMSResult"
+ }
+ }
+ },
+ "endpoints.VMSResult": {
+ "type": "object",
+ "properties": {
+ "count": {
+ "type": "integer"
+ },
+ "vms": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/api.VM"
+ }
+ }
+ }
+ }
+ },
+ "securityDefinitions": {
+ "BasicAuth": {
+ "type": "basic"
+ }
+ }
+}
\ No newline at end of file
diff --git a/cmd/docs/swagger.yaml b/cmd/docs/swagger.yaml
new file mode 100644
index 0000000..23ac39e
--- /dev/null
+++ b/cmd/docs/swagger.yaml
@@ -0,0 +1,277 @@
+definitions:
+ api.Datastore:
+ properties:
+ capacity:
+ type: integer
+ datastore:
+ type: string
+ free_space:
+ type: integer
+ name:
+ type: string
+ type:
+ type: string
+ type: object
+ api.Host:
+ properties:
+ connection_state:
+ type: string
+ host:
+ type: string
+ name:
+ type: string
+ power_state:
+ type: string
+ type: object
+ api.VM:
+ properties:
+ name:
+ type: string
+ power_state:
+ type: string
+ vm:
+ type: string
+ type: object
+ api.VMInfo:
+ properties:
+ cpu_cores:
+ type: integer
+ name:
+ type: string
+ provisioned_ram:
+ type: integer
+ provisioned_storage:
+ type: integer
+ used_storage:
+ type: integer
+ type: object
+ api.VMTag:
+ properties:
+ category:
+ description: Category holds the tag category
+ type: string
+ value:
+ description: Value holds the value of the tag
+ type: string
+ type: object
+ endpoints.Datastores:
+ properties:
+ datastores:
+ $ref: '#/definitions/endpoints.DatastoresResult'
+ type: object
+ endpoints.DatastoresResult:
+ properties:
+ count:
+ type: integer
+ datastores:
+ items:
+ $ref: '#/definitions/api.Datastore'
+ type: array
+ type: object
+ endpoints.FQDN:
+ properties:
+ fqdn:
+ type: string
+ type: object
+ endpoints.Hosts:
+ properties:
+ hosts:
+ $ref: '#/definitions/endpoints.HostsResult'
+ type: object
+ endpoints.HostsResult:
+ properties:
+ count:
+ type: integer
+ hosts:
+ items:
+ $ref: '#/definitions/api.Host'
+ type: array
+ type: object
+ endpoints.Status:
+ properties:
+ status:
+ type: string
+ type: object
+ endpoints.Tags:
+ properties:
+ tags:
+ $ref: '#/definitions/endpoints.TagsResult'
+ type: object
+ endpoints.TagsResult:
+ properties:
+ count:
+ type: integer
+ tags:
+ items:
+ $ref: '#/definitions/api.VMTag'
+ type: array
+ type: object
+ endpoints.VMS:
+ properties:
+ vms:
+ $ref: '#/definitions/endpoints.VMSResult'
+ type: object
+ endpoints.VMSResult:
+ properties:
+ count:
+ type: integer
+ vms:
+ items:
+ $ref: '#/definitions/api.VM'
+ type: array
+ type: object
+info:
+ contact:
+ email: info@dodevops.io
+ name: DO!DevOps
+ url: http://dodevops.io
+ title: vmware-rest-proxy
+ version: 0.1.0
+paths:
+ /datastores:
+ get:
+ description: Fetches a list of registered datastores in the vCenter
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/endpoints.Datastores'
+ "400":
+ description: Invalid request
+ "401":
+ description: Authorization is required
+ security:
+ - BasicAuth: []
+ summary: Retrieve a list of datastores
+ tags:
+ - datastore
+ /hosts:
+ get:
+ description: Fetches a list of registered ESXi hosts in the vCenter
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/endpoints.Hosts'
+ "400":
+ description: Invalid request
+ "401":
+ description: Authorization is required
+ security:
+ - BasicAuth: []
+ summary: Retrieve a list of ESXi hosts
+ tags:
+ - host
+ /status:
+ get:
+ description: Just responses with a 200 to signal that the service is running
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/endpoints.Status'
+ summary: Checks whether the service is running
+ /vms:
+ get:
+ description: Fetches a list of vms from the vCenter
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/endpoints.VMS'
+ "400":
+ description: Invalid request
+ "401":
+ description: Authorization is required
+ security:
+ - BasicAuth: []
+ summary: Retrieve a list of all vms
+ tags:
+ - vm
+ /vms/{id}/fqdn:
+ get:
+ description: Try to find out the fqdn of the given VM using the guest tools
+ parameters:
+ - description: ID of VM
+ in: path
+ name: id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/endpoints.FQDN'
+ "400":
+ description: Invalid request
+ "401":
+ description: Authorization is required
+ security:
+ - BasicAuth: []
+ summary: Get fqdn of VM
+ tags:
+ - vm
+ /vms/{id}/info:
+ get:
+ description: Find out some information about a VM and return them
+ parameters:
+ - description: ID of VM
+ in: path
+ name: id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/api.VMInfo'
+ "400":
+ description: Invalid request
+ "401":
+ description: Authorization is required
+ security:
+ - BasicAuth: []
+ summary: Get informational data about a VM
+ tags:
+ - vm
+ /vms/{id}/tags:
+ get:
+ description: Retrieve tags and their categories for a vm
+ parameters:
+ - description: ID of VM
+ in: path
+ name: id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/endpoints.Tags'
+ "400":
+ description: Invalid request
+ "401":
+ description: Authorization is required
+ security:
+ - BasicAuth: []
+ summary: Retrieve tags
+ tags:
+ - vm
+securityDefinitions:
+ BasicAuth:
+ type: basic
+swagger: "2.0"
diff --git a/cmd/serve.go b/cmd/serve.go
index 10f509b..e731f77 100644
--- a/cmd/serve.go
+++ b/cmd/serve.go
@@ -2,17 +2,29 @@ package main
import (
"crypto/tls"
+ "fmt"
"github.com/gin-gonic/gin"
"github.com/go-resty/resty/v2"
"github.com/sirupsen/logrus"
+ swaggerFiles "github.com/swaggo/files"
+ ginSwagger "github.com/swaggo/gin-swagger"
"log"
+ "net/http"
+ "net/url"
"os"
+ "vmware-rest-proxy/cmd/docs"
api2 "vmware-rest-proxy/internal/api"
"vmware-rest-proxy/internal/endpoints"
)
// REST server that proxies request through to a vCenter web service making it easier to request certain details.
-
+// @title vmware-rest-proxy
+// @version 0.1.0
+// @contact.name DO!DevOps
+// @contact.url http://dodevops.io
+// @contact.email info@dodevops.io
+//
+// @securityDefinitions.basic BasicAuth
func main() {
r := resty.New()
@@ -53,6 +65,16 @@ func main() {
r.SetProxy(p)
}
+ externalBaseUrl, _ := url.Parse("http://localhost:8080")
+ if p, found := os.LookupEnv("EXTERNAL_BASE_URL"); found && p != "" {
+ logrus.Debug("Setting external base URL")
+ if b, err := url.Parse(p); err != nil {
+ log.Fatalf("Can not parse external base url %s: %s", p, err)
+ } else {
+ externalBaseUrl = b
+ }
+ }
+
logrus.Debug("Starting server")
gin.SetMode(gin.ReleaseMode)
@@ -62,8 +84,21 @@ func main() {
log.Fatalf("Error disabling trusted proxies: %s", err)
}
api := api2.DefaultVSphereProxyApi{Resty: r}
- for _, endpoint := range []endpoints.Endpoint{&endpoints.VMSEndpoint{API: api}, &endpoints.StatusEndpoint{}} {
+ for _, endpoint := range []endpoints.Endpoint{&endpoints.VMSEndpoint{API: api}, &endpoints.HostsEndpoint{API: api}, &endpoints.StatusEndpoint{}, &endpoints.DataStoreEndpoint{API: api}} {
endpoint.Register(s)
}
+ docs.SwaggerInfo.Title = "vmware-rest-proxy"
+ docs.SwaggerInfo.Description = fmt.Sprintf("This is the API of the vmware-rest-proxy pointing at %s", r.BaseURL)
+ docs.SwaggerInfo.Version = "1.0"
+ docs.SwaggerInfo.BasePath = "/"
+ docs.SwaggerInfo.Host = externalBaseUrl.Host
+ docs.SwaggerInfo.Schemes = []string{externalBaseUrl.Scheme}
+ s.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
+ s.GET("/", func(context *gin.Context) {
+ context.Redirect(http.StatusMovedPermanently, "/swagger/index.html")
+ })
+ s.GET("/swagger", func(context *gin.Context) {
+ context.Redirect(http.StatusMovedPermanently, "/swagger/index.html")
+ })
_ = s.Run(bindAddress)
}
diff --git a/go.mod b/go.mod
index 9f41dd4..f6932ab 100644
--- a/go.mod
+++ b/go.mod
@@ -11,29 +11,44 @@ require (
)
require (
- github.com/bytedance/sonic v1.9.1 // indirect
- github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
- github.com/gabriel-vasile/mimetype v1.4.2 // indirect
+ github.com/KyleBanks/depth v1.2.1 // indirect
+ github.com/PuerkitoBio/purell v1.2.1 // indirect
+ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
+ github.com/bytedance/sonic v1.10.2 // indirect
+ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
+ github.com/chenzhuoyu/iasm v0.9.1 // indirect
+ github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
+ github.com/go-openapi/jsonpointer v0.20.2 // indirect
+ github.com/go-openapi/jsonreference v0.20.4 // indirect
+ github.com/go-openapi/spec v0.20.13 // indirect
+ github.com/go-openapi/swag v0.22.6 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
- github.com/go-playground/validator/v10 v10.14.0 // indirect
+ github.com/go-playground/validator/v10 v10.16.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
- github.com/klauspost/cpuid/v2 v2.2.4 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
- github.com/pelletier/go-toml/v2 v2.0.8 // indirect
+ github.com/pelletier/go-toml/v2 v2.1.1 // indirect
+ github.com/swaggo/files v1.0.1 // indirect
+ github.com/swaggo/gin-swagger v1.6.0 // indirect
+ github.com/swaggo/swag v1.16.2 // indirect
github.com/thoas/go-funk v0.9.3 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
- github.com/ugorji/go/codec v1.2.11 // indirect
- golang.org/x/arch v0.3.0 // indirect
- golang.org/x/crypto v0.14.0 // indirect
- golang.org/x/net v0.17.0 // indirect
- golang.org/x/sys v0.13.0 // indirect
- golang.org/x/text v0.13.0 // indirect
- google.golang.org/protobuf v1.30.0 // indirect
+ github.com/ugorji/go/codec v1.2.12 // indirect
+ golang.org/x/arch v0.6.0 // indirect
+ golang.org/x/crypto v0.17.0 // indirect
+ golang.org/x/net v0.19.0 // indirect
+ golang.org/x/sys v0.15.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
+ golang.org/x/tools v0.16.1 // indirect
+ google.golang.org/protobuf v1.32.0 // indirect
+ gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index 827740f..a7ceb18 100644
--- a/go.sum
+++ b/go.sum
@@ -1,9 +1,23 @@
+github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
+github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
+github.com/PuerkitoBio/purell v1.2.1 h1:QsZ4TjvwiMpat6gBCBxEQI0rcS9ehtkKtSpiUnd9N28=
+github.com/PuerkitoBio/purell v1.2.1/go.mod h1:ZwHcC/82TOaovDi//J/804umJFFmbOHPngi8iYYv/Eo=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
+github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
+github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
+github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
+github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
+github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
+github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
+github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
+github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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=
@@ -11,10 +25,20 @@ github.com/dodevops/golang-handlerinspector v0.1.0 h1:iPSaw9izmNSvoVGUn3btGbpjXz
github.com/dodevops/golang-handlerinspector v0.1.0/go.mod h1:0oVA3heviGeSZQ1eqt/yjcouhP3B95g/2l732lK48r4=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
+github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
+github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
+github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
+github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
+github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU=
+github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4=
+github.com/go-openapi/spec v0.20.13 h1:XJDIN+dLH6vqXgafnl5SUIMnzaChQ6QTo0/UPMbkIaE=
+github.com/go-openapi/spec v0.20.13/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw=
+github.com/go-openapi/swag v0.22.6 h1:dnqg1XfHXL9aBxSbktBqFR5CxVyVI+7fYWhAf1JOeTw=
+github.com/go-openapi/swag v0.22.6/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@@ -23,6 +47,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
+github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE=
+github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-resty/resty/v2 v2.10.0 h1:Qla4W/+TMmv0fOeeRqzEpXPLfTUnR5HZ1+lGs+CkiCo=
github.com/go-resty/resty/v2 v2.10.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
@@ -31,15 +57,25 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
+github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
+github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -47,6 +83,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
+github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
+github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
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/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
@@ -63,29 +101,45 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
+github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
+github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
+github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo=
+github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04=
+github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E=
github.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw=
github.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
+github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc=
+golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
+golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
+golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -101,6 +155,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -113,22 +169,31 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
+golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
+google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
diff --git a/internal/endpoints/datastores.go b/internal/endpoints/datastores.go
index 2c43531..a8bb803 100644
--- a/internal/endpoints/datastores.go
+++ b/internal/endpoints/datastores.go
@@ -14,6 +14,24 @@ func (d DataStoreEndpoint) Register(engine *gin.Engine) {
engine.GET("/datastores", d.getDatastores)
}
+type DatastoresResult struct {
+ Count int `json:"count"`
+ Datastores []api.Datastore `json:"datastores"`
+}
+
+type Datastores struct {
+ Datastores DatastoresResult `json:"datastores"`
+}
+
+// @Summary Retrieve a list of datastores
+// @Description Fetches a list of registered datastores in the vCenter
+// @Tags datastore
+// @Produce json
+// @Security BasicAuth
+// @Success 200 {object} Datastores
+// @Failure 401 "Authorization is required"
+// @Failure 400 "Invalid request"
+// @Router /datastores [get]
func (d DataStoreEndpoint) getDatastores(context *gin.Context) {
if r, ok := HandleRequest(context); ok {
if datastores, err := d.API.GetDatastores(r.Username, r.Password); err != nil {
@@ -21,10 +39,10 @@ func (d DataStoreEndpoint) getDatastores(context *gin.Context) {
"error": fmt.Sprintf("Error getting datastores: %s", err),
})
} else {
- context.JSON(200, gin.H{
- "datastores": gin.H{
- "count": len(datastores),
- "datastores": datastores,
+ context.JSON(200, Datastores{
+ Datastores: DatastoresResult{
+ Count: len(datastores),
+ Datastores: datastores,
},
})
}
diff --git a/internal/endpoints/endpoint.go b/internal/endpoints/endpoint.go
index c5dd334..238fe18 100644
--- a/internal/endpoints/endpoint.go
+++ b/internal/endpoints/endpoint.go
@@ -24,10 +24,8 @@ type RequestData struct {
Password string
}
-/*
-HandleRequest manages incoming requests and extracts authorization data and optionally fails them if no authorization
-is present.
-*/
+// HandleRequest manages incoming requests and extracts authorization data and optionally fails them if no authorization
+// is present.
func HandleRequest(context *gin.Context) (RequestData, bool) {
if u, p, err := getAuthData(context.GetHeader("Authorization")); err != nil {
var missingAuthenticationHeaderError internal.MissingAuthorizationHeaderError
@@ -36,7 +34,7 @@ func HandleRequest(context *gin.Context) (RequestData, bool) {
"error": "Missing authentication header",
})
} else {
- context.AbortWithStatusJSON(403, gin.H{
+ context.AbortWithStatusJSON(400, gin.H{
"error": fmt.Sprintf("Error getting Authorization header: %s", err),
})
}
diff --git a/internal/endpoints/hosts.go b/internal/endpoints/hosts.go
index 59a5e52..6248220 100644
--- a/internal/endpoints/hosts.go
+++ b/internal/endpoints/hosts.go
@@ -14,6 +14,24 @@ func (H HostsEndpoint) Register(engine *gin.Engine) {
engine.GET("/hosts", H.getHosts)
}
+type HostsResult struct {
+ Count int `json:"count"`
+ Hosts []api.Host `json:"hosts"`
+}
+
+type Hosts struct {
+ Hosts HostsResult `json:"hosts"`
+}
+
+// @Summary Retrieve a list of ESXi hosts
+// @Description Fetches a list of registered ESXi hosts in the vCenter
+// @Tags host
+// @Produce json
+// @Security BasicAuth
+// @Success 200 {object} Hosts
+// @Failure 401 "Authorization is required"
+// @Failure 400 "Invalid request"
+// @Router /hosts [get]
func (H HostsEndpoint) getHosts(context *gin.Context) {
if r, ok := HandleRequest(context); ok {
if hosts, err := H.API.GetHosts(r.Username, r.Password); err != nil {
@@ -22,10 +40,10 @@ func (H HostsEndpoint) getHosts(context *gin.Context) {
})
} else {
context.JSON(200, gin.H{
- "hosts": gin.H{
- "count": len(hosts),
- "hosts": hosts,
- },
+ "hosts": Hosts{Hosts: HostsResult{
+ Count: len(hosts),
+ Hosts: hosts,
+ }},
})
}
}
diff --git a/internal/endpoints/status.go b/internal/endpoints/status.go
index 0bef567..4ad8c3f 100644
--- a/internal/endpoints/status.go
+++ b/internal/endpoints/status.go
@@ -9,10 +9,18 @@ type StatusEndpoint struct{}
var _ Endpoint = &StatusEndpoint{}
+type Status struct {
+ Status string `json:"status"`
+}
+
+// Register registers the status endpoint
+// @Summary Checks whether the service is running
+// @Description Just responses with a 200 to signal that the service is running
+// @Produce json
+// @Success 200 {object} Status
+// @Router /status [get]
func (StatusEndpoint) Register(engine *gin.Engine) {
engine.GET("/status", func(context *gin.Context) {
- context.JSON(200, gin.H{
- "status": "running",
- })
+ context.JSON(200, Status{Status: "running"})
})
}
diff --git a/internal/endpoints/vms.go b/internal/endpoints/vms.go
index 31f094d..708a274 100644
--- a/internal/endpoints/vms.go
+++ b/internal/endpoints/vms.go
@@ -25,7 +25,23 @@ func (V *VMSEndpoint) Register(engine *gin.Engine) {
engine.GET("/vms/:vm/info", V.getVMInfo)
}
-// getVMS exposes all VMS of the vCenter at /VMS
+type VMSResult struct {
+ Count int `json:"count"`
+ VMS []api.VM `json:"vms"`
+}
+type VMS struct {
+ VMS VMSResult `json:"vms"`
+}
+
+// @Summary Retrieve a list of all vms
+// @Description Fetches a list of vms from the vCenter
+// @Tags vm
+// @Produce json
+// @Security BasicAuth
+// @Success 200 {object} VMS
+// @Failure 401 "Authorization is required"
+// @Failure 400 "Invalid request"
+// @Router /vms [get]
func (V *VMSEndpoint) getVMS(context *gin.Context) {
if r, ok := HandleRequest(context); ok {
if vms, err := V.API.GetVMs(r.Username, r.Password); err != nil {
@@ -43,7 +59,25 @@ func (V *VMSEndpoint) getVMS(context *gin.Context) {
}
}
-// getVMTags exposes a list of tags associated with a vm at /VMS/:vm/tags
+type TagsResult struct {
+ Count int `json:"count"`
+ Tags []api.VMTag `json:"tags"`
+}
+
+type Tags struct {
+ Tags TagsResult `json:"tags"`
+}
+
+// @Summary Retrieve tags
+// @Description Retrieve tags and their categories for a vm
+// @Param id path string true "ID of VM"
+// @Tags vm
+// @Produce json
+// @Security BasicAuth
+// @Success 200 {object} Tags
+// @Failure 401 "Authorization is required"
+// @Failure 400 "Invalid request"
+// @Router /vms/{id}/tags [get]
func (V *VMSEndpoint) getVMTags(context *gin.Context) {
if r, ok := HandleRequest(context); ok {
var vm VMBinding
@@ -68,6 +102,20 @@ func (V *VMSEndpoint) getVMTags(context *gin.Context) {
}
}
+type FQDN struct {
+ FQDN string `json:"fqdn"`
+}
+
+// @Summary Get fqdn of VM
+// @Description Try to find out the fqdn of the given VM using the guest tools
+// @Param id path string true "ID of VM"
+// @Tags vm
+// @Produce json
+// @Security BasicAuth
+// @Success 200 {object} FQDN
+// @Failure 401 "Authorization is required"
+// @Failure 400 "Invalid request"
+// @Router /vms/{id}/fqdn [get]
func (V *VMSEndpoint) getFQDN(context *gin.Context) {
if r, ok := HandleRequest(context); ok {
var vm VMBinding
@@ -89,6 +137,16 @@ func (V *VMSEndpoint) getFQDN(context *gin.Context) {
}
}
+// @Summary Get informational data about a VM
+// @Description Find out some information about a VM and return them
+// @Param id path string true "ID of VM"
+// @Tags vm
+// @Produce json
+// @Security BasicAuth
+// @Success 200 {object} api.VMInfo
+// @Failure 401 "Authorization is required"
+// @Failure 400 "Invalid request"
+// @Router /vms/{id}/info [get]
func (V *VMSEndpoint) getVMInfo(context *gin.Context) {
if r, ok := HandleRequest(context); ok {
var vm VMBinding