From 2655eaefc01726ffbb747db855a994b7babc4cb2 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Fri, 12 May 2023 11:57:34 -0400 Subject: [PATCH] roughed in environment sparklines backend (#327) --- controller/accountDetail.go | 55 +++++++ controller/controller.go | 1 + controller/sparkData.go | 87 +++++++--- .../metadata/get_account_detail_parameters.go | 128 +++++++++++++++ .../metadata/get_account_detail_responses.go | 153 ++++++++++++++++++ rest_client_zrok/metadata/metadata_client.go | 41 +++++ rest_model_zrok/environment.go | 56 ++++++- rest_server_zrok/embedded_spec.go | 56 ++++++- .../operations/metadata/get_account_detail.go | 71 ++++++++ .../metadata/get_account_detail_parameters.go | 46 ++++++ .../metadata/get_account_detail_responses.go | 87 ++++++++++ .../metadata/get_account_detail_urlbuilder.go | 87 ++++++++++ rest_server_zrok/operations/zrok_api.go | 12 ++ specs/zrok.yml | 45 ++++-- ui/src/api/metadata.js | 16 ++ ui/src/api/types.js | 18 +-- 16 files changed, 908 insertions(+), 51 deletions(-) create mode 100644 controller/accountDetail.go create mode 100644 rest_client_zrok/metadata/get_account_detail_parameters.go create mode 100644 rest_client_zrok/metadata/get_account_detail_responses.go create mode 100644 rest_server_zrok/operations/metadata/get_account_detail.go create mode 100644 rest_server_zrok/operations/metadata/get_account_detail_parameters.go create mode 100644 rest_server_zrok/operations/metadata/get_account_detail_responses.go create mode 100644 rest_server_zrok/operations/metadata/get_account_detail_urlbuilder.go diff --git a/controller/accountDetail.go b/controller/accountDetail.go new file mode 100644 index 00000000..6bf4194b --- /dev/null +++ b/controller/accountDetail.go @@ -0,0 +1,55 @@ +package controller + +import ( + "github.com/go-openapi/runtime/middleware" + "github.com/openziti/zrok/rest_model_zrok" + "github.com/openziti/zrok/rest_server_zrok/operations/metadata" + "github.com/sirupsen/logrus" +) + +type accountDetailHandler struct{} + +func newAccountDetailHandler() *accountDetailHandler { + return &accountDetailHandler{} +} + +func (h *accountDetailHandler) Handle(params metadata.GetAccountDetailParams, principal *rest_model_zrok.Principal) middleware.Responder { + trx, err := str.Begin() + if err != nil { + logrus.Errorf("error stasrting transaction for '%v': %v", principal.Email, err) + return metadata.NewGetAccountDetailInternalServerError() + } + defer func() { _ = trx.Rollback() }() + envs, err := str.FindEnvironmentsForAccount(int(principal.ID), trx) + if err != nil { + logrus.Errorf("error retrieving environments for '%v': %v", principal.Email, err) + return metadata.NewGetAccountDetailInternalServerError() + } + sparkRx := make(map[int][]int64) + sparkTx := make(map[int][]int64) + if cfg.Metrics != nil && cfg.Metrics.Influx != nil { + sparkRx, sparkTx, err = sparkDataForEnvironments(envs) + if err != nil { + logrus.Errorf("error querying spark data for environments for '%v': %v", principal.Email, err) + } + } else { + logrus.Debug("skipping spark data for environments; no influx configuration") + } + var payload []*rest_model_zrok.Environment + for _, env := range envs { + var sparkData []*rest_model_zrok.SparkDataSample + for i := 0; i < len(sparkRx[env.Id]) && i < len(sparkTx[env.Id]); i++ { + sparkData = append(sparkData, &rest_model_zrok.SparkDataSample{Rx: float64(sparkRx[env.Id][i]), Tx: float64(sparkTx[env.Id][i])}) + } + payload = append(payload, &rest_model_zrok.Environment{ + Activity: sparkData, + Address: env.Address, + CreatedAt: env.CreatedAt.UnixMilli(), + Description: env.Description, + Host: env.Host, + UpdatedAt: env.UpdatedAt.UnixMilli(), + ZID: env.ZId, + }) + } + return metadata.NewGetAccountDetailOK().WithPayload(payload) +} diff --git a/controller/controller.go b/controller/controller.go index 706bf16f..18f189b7 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -46,6 +46,7 @@ func Run(inCfg *config.Config) error { api.AdminUpdateFrontendHandler = newUpdateFrontendHandler() api.EnvironmentEnableHandler = newEnableHandler() api.EnvironmentDisableHandler = newDisableHandler() + api.MetadataGetAccountDetailHandler = newAccountDetailHandler() api.MetadataConfigurationHandler = newConfigurationHandler(cfg) if cfg.Metrics != nil && cfg.Metrics.Influx != nil { api.MetadataGetAccountMetricsHandler = newGetAccountMetricsHandler(cfg.Metrics.Influx) diff --git a/controller/sparkData.go b/controller/sparkData.go index c68107e9..d8156c8d 100644 --- a/controller/sparkData.go +++ b/controller/sparkData.go @@ -6,13 +6,79 @@ import ( "github.com/openziti/zrok/controller/store" ) +func sparkDataForEnvironments(envs []*store.Environment) (rx, tx map[int][]int64, err error) { + rx = make(map[int][]int64) + tx = make(map[int][]int64) + if len(envs) > 0 { + qapi := idb.QueryAPI(cfg.Metrics.Influx.Org) + + envFilter := "|> filter(fn: (r) =>" + for i, env := range envs { + if i > 0 { + envFilter += " or" + } + envFilter += fmt.Sprintf(" r[\"envId\"] == \"%d\"", env.Id) + } + envFilter += ")" + query := fmt.Sprintf("from(bucket: \"%v\")\n", cfg.Metrics.Influx.Bucket) + + "|> range(start: -5m)\n" + + "|> filter(fn: (r) => r[\"_measurement\"] == \"xfer\")\n" + + "|> filter(fn: (r) => r[\"_field\"] == \"rx\" or r[\"_field\"] == \"tx\")\n" + + "|> filter(fn: (r) => r[\"namespace\"] == \"backend\")\n" + + envFilter + + "|> aggregateWindow(every: 10s, fn: sum, createEmpty: true)\n" + + result, err := qapi.Query(context.Background(), query) + if err != nil { + return nil, nil, err + } + + for result.Next() { + envId := result.Record().ValueByKey("envId").(int64) + switch result.Record().Field() { + case "rx": + rxV := int64(0) + if v, ok := result.Record().Value().(int64); ok { + rxV = v + } + rxData := append(rx[int(envId)], rxV) + rx[int(envId)] = rxData + + case "tx": + txV := int64(0) + if v, ok := result.Record().Value().(int64); ok { + txV = v + } + txData := append(tx[int(envId)], txV) + tx[int(envId)] = txData + } + } + } + return rx, tx, nil +} + func sparkDataForShares(shrs []*store.Share) (rx, tx map[string][]int64, err error) { rx = make(map[string][]int64) tx = make(map[string][]int64) if len(shrs) > 0 { qapi := idb.QueryAPI(cfg.Metrics.Influx.Org) - query := sparkFluxQuery(shrs, cfg.Metrics.Influx.Bucket) + shrFilter := "|> filter(fn: (r) =>" + for i, shr := range shrs { + if i > 0 { + shrFilter += " or" + } + shrFilter += fmt.Sprintf(" r[\"share\"] == \"%v\"", shr.Token) + } + shrFilter += ")" + query := fmt.Sprintf("from(bucket: \"%v\")\n", cfg.Metrics.Influx.Bucket) + + "|> range(start: -5m)\n" + + "|> filter(fn: (r) => r[\"_measurement\"] == \"xfer\")\n" + + "|> filter(fn: (r) => r[\"_field\"] == \"rx\" or r[\"_field\"] == \"tx\")\n" + + "|> filter(fn: (r) => r[\"namespace\"] == \"backend\")\n" + + shrFilter + + "|> aggregateWindow(every: 10s, fn: sum, createEmpty: true)\n" + result, err := qapi.Query(context.Background(), query) if err != nil { return nil, nil, err @@ -41,22 +107,3 @@ func sparkDataForShares(shrs []*store.Share) (rx, tx map[string][]int64, err err } return rx, tx, nil } - -func sparkFluxQuery(shrs []*store.Share, bucket string) string { - shrFilter := "|> filter(fn: (r) =>" - for i, shr := range shrs { - if i > 0 { - shrFilter += " or" - } - shrFilter += fmt.Sprintf(" r[\"share\"] == \"%v\"", shr.Token) - } - shrFilter += ")" - query := fmt.Sprintf("from(bucket: \"%v\")\n", bucket) + - "|> range(start: -5m)\n" + - "|> filter(fn: (r) => r[\"_measurement\"] == \"xfer\")\n" + - "|> filter(fn: (r) => r[\"_field\"] == \"rx\" or r[\"_field\"] == \"tx\")\n" + - "|> filter(fn: (r) => r[\"namespace\"] == \"backend\")" + - shrFilter + - "|> aggregateWindow(every: 10s, fn: sum, createEmpty: true)\n" - return query -} diff --git a/rest_client_zrok/metadata/get_account_detail_parameters.go b/rest_client_zrok/metadata/get_account_detail_parameters.go new file mode 100644 index 00000000..290957e7 --- /dev/null +++ b/rest_client_zrok/metadata/get_account_detail_parameters.go @@ -0,0 +1,128 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package metadata + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "net/http" + "time" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + cr "github.com/go-openapi/runtime/client" + "github.com/go-openapi/strfmt" +) + +// NewGetAccountDetailParams creates a new GetAccountDetailParams object, +// with the default timeout for this client. +// +// Default values are not hydrated, since defaults are normally applied by the API server side. +// +// To enforce default values in parameter, use SetDefaults or WithDefaults. +func NewGetAccountDetailParams() *GetAccountDetailParams { + return &GetAccountDetailParams{ + timeout: cr.DefaultTimeout, + } +} + +// NewGetAccountDetailParamsWithTimeout creates a new GetAccountDetailParams object +// with the ability to set a timeout on a request. +func NewGetAccountDetailParamsWithTimeout(timeout time.Duration) *GetAccountDetailParams { + return &GetAccountDetailParams{ + timeout: timeout, + } +} + +// NewGetAccountDetailParamsWithContext creates a new GetAccountDetailParams object +// with the ability to set a context for a request. +func NewGetAccountDetailParamsWithContext(ctx context.Context) *GetAccountDetailParams { + return &GetAccountDetailParams{ + Context: ctx, + } +} + +// NewGetAccountDetailParamsWithHTTPClient creates a new GetAccountDetailParams object +// with the ability to set a custom HTTPClient for a request. +func NewGetAccountDetailParamsWithHTTPClient(client *http.Client) *GetAccountDetailParams { + return &GetAccountDetailParams{ + HTTPClient: client, + } +} + +/* +GetAccountDetailParams contains all the parameters to send to the API endpoint + + for the get account detail operation. + + Typically these are written to a http.Request. +*/ +type GetAccountDetailParams struct { + timeout time.Duration + Context context.Context + HTTPClient *http.Client +} + +// WithDefaults hydrates default values in the get account detail params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *GetAccountDetailParams) WithDefaults() *GetAccountDetailParams { + o.SetDefaults() + return o +} + +// SetDefaults hydrates default values in the get account detail params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *GetAccountDetailParams) SetDefaults() { + // no default values defined for this parameter +} + +// WithTimeout adds the timeout to the get account detail params +func (o *GetAccountDetailParams) WithTimeout(timeout time.Duration) *GetAccountDetailParams { + o.SetTimeout(timeout) + return o +} + +// SetTimeout adds the timeout to the get account detail params +func (o *GetAccountDetailParams) SetTimeout(timeout time.Duration) { + o.timeout = timeout +} + +// WithContext adds the context to the get account detail params +func (o *GetAccountDetailParams) WithContext(ctx context.Context) *GetAccountDetailParams { + o.SetContext(ctx) + return o +} + +// SetContext adds the context to the get account detail params +func (o *GetAccountDetailParams) SetContext(ctx context.Context) { + o.Context = ctx +} + +// WithHTTPClient adds the HTTPClient to the get account detail params +func (o *GetAccountDetailParams) WithHTTPClient(client *http.Client) *GetAccountDetailParams { + o.SetHTTPClient(client) + return o +} + +// SetHTTPClient adds the HTTPClient to the get account detail params +func (o *GetAccountDetailParams) SetHTTPClient(client *http.Client) { + o.HTTPClient = client +} + +// WriteToRequest writes these params to a swagger request +func (o *GetAccountDetailParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { + + if err := r.SetTimeout(o.timeout); err != nil { + return err + } + var res []error + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/rest_client_zrok/metadata/get_account_detail_responses.go b/rest_client_zrok/metadata/get_account_detail_responses.go new file mode 100644 index 00000000..2d51df0d --- /dev/null +++ b/rest_client_zrok/metadata/get_account_detail_responses.go @@ -0,0 +1,153 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package metadata + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "fmt" + "io" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" + + "github.com/openziti/zrok/rest_model_zrok" +) + +// GetAccountDetailReader is a Reader for the GetAccountDetail structure. +type GetAccountDetailReader struct { + formats strfmt.Registry +} + +// ReadResponse reads a server response into the received o. +func (o *GetAccountDetailReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + switch response.Code() { + case 200: + result := NewGetAccountDetailOK() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return result, nil + case 500: + result := NewGetAccountDetailInternalServerError() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result + default: + return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) + } +} + +// NewGetAccountDetailOK creates a GetAccountDetailOK with default headers values +func NewGetAccountDetailOK() *GetAccountDetailOK { + return &GetAccountDetailOK{} +} + +/* +GetAccountDetailOK describes a response with status code 200, with default header values. + +ok +*/ +type GetAccountDetailOK struct { + Payload rest_model_zrok.Environments +} + +// IsSuccess returns true when this get account detail o k response has a 2xx status code +func (o *GetAccountDetailOK) IsSuccess() bool { + return true +} + +// IsRedirect returns true when this get account detail o k response has a 3xx status code +func (o *GetAccountDetailOK) IsRedirect() bool { + return false +} + +// IsClientError returns true when this get account detail o k response has a 4xx status code +func (o *GetAccountDetailOK) IsClientError() bool { + return false +} + +// IsServerError returns true when this get account detail o k response has a 5xx status code +func (o *GetAccountDetailOK) IsServerError() bool { + return false +} + +// IsCode returns true when this get account detail o k response a status code equal to that given +func (o *GetAccountDetailOK) IsCode(code int) bool { + return code == 200 +} + +func (o *GetAccountDetailOK) Error() string { + return fmt.Sprintf("[GET /detail/account][%d] getAccountDetailOK %+v", 200, o.Payload) +} + +func (o *GetAccountDetailOK) String() string { + return fmt.Sprintf("[GET /detail/account][%d] getAccountDetailOK %+v", 200, o.Payload) +} + +func (o *GetAccountDetailOK) GetPayload() rest_model_zrok.Environments { + return o.Payload +} + +func (o *GetAccountDetailOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + // response payload + if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +// NewGetAccountDetailInternalServerError creates a GetAccountDetailInternalServerError with default headers values +func NewGetAccountDetailInternalServerError() *GetAccountDetailInternalServerError { + return &GetAccountDetailInternalServerError{} +} + +/* +GetAccountDetailInternalServerError describes a response with status code 500, with default header values. + +internal server error +*/ +type GetAccountDetailInternalServerError struct { +} + +// IsSuccess returns true when this get account detail internal server error response has a 2xx status code +func (o *GetAccountDetailInternalServerError) IsSuccess() bool { + return false +} + +// IsRedirect returns true when this get account detail internal server error response has a 3xx status code +func (o *GetAccountDetailInternalServerError) IsRedirect() bool { + return false +} + +// IsClientError returns true when this get account detail internal server error response has a 4xx status code +func (o *GetAccountDetailInternalServerError) IsClientError() bool { + return false +} + +// IsServerError returns true when this get account detail internal server error response has a 5xx status code +func (o *GetAccountDetailInternalServerError) IsServerError() bool { + return true +} + +// IsCode returns true when this get account detail internal server error response a status code equal to that given +func (o *GetAccountDetailInternalServerError) IsCode(code int) bool { + return code == 500 +} + +func (o *GetAccountDetailInternalServerError) Error() string { + return fmt.Sprintf("[GET /detail/account][%d] getAccountDetailInternalServerError ", 500) +} + +func (o *GetAccountDetailInternalServerError) String() string { + return fmt.Sprintf("[GET /detail/account][%d] getAccountDetailInternalServerError ", 500) +} + +func (o *GetAccountDetailInternalServerError) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + return nil +} diff --git a/rest_client_zrok/metadata/metadata_client.go b/rest_client_zrok/metadata/metadata_client.go index 11e3a1ca..764216b3 100644 --- a/rest_client_zrok/metadata/metadata_client.go +++ b/rest_client_zrok/metadata/metadata_client.go @@ -32,6 +32,8 @@ type ClientOption func(*runtime.ClientOperation) type ClientService interface { Configuration(params *ConfigurationParams, opts ...ClientOption) (*ConfigurationOK, error) + GetAccountDetail(params *GetAccountDetailParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*GetAccountDetailOK, error) + GetAccountMetrics(params *GetAccountMetricsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*GetAccountMetricsOK, error) GetEnvironmentDetail(params *GetEnvironmentDetailParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*GetEnvironmentDetailOK, error) @@ -87,6 +89,45 @@ func (a *Client) Configuration(params *ConfigurationParams, opts ...ClientOption panic(msg) } +/* +GetAccountDetail get account detail API +*/ +func (a *Client) GetAccountDetail(params *GetAccountDetailParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*GetAccountDetailOK, error) { + // TODO: Validate the params before sending + if params == nil { + params = NewGetAccountDetailParams() + } + op := &runtime.ClientOperation{ + ID: "getAccountDetail", + Method: "GET", + PathPattern: "/detail/account", + ProducesMediaTypes: []string{"application/zrok.v1+json"}, + ConsumesMediaTypes: []string{"application/zrok.v1+json"}, + Schemes: []string{"http"}, + Params: params, + Reader: &GetAccountDetailReader{formats: a.formats}, + AuthInfo: authInfo, + Context: params.Context, + Client: params.HTTPClient, + } + for _, opt := range opts { + opt(op) + } + + result, err := a.transport.Submit(op) + if err != nil { + return nil, err + } + success, ok := result.(*GetAccountDetailOK) + if ok { + return success, nil + } + // unexpected success response + // safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue + msg := fmt.Sprintf("unexpected success response for getAccountDetail: API contract not enforced by server. Client expected to get an error, but got: %T", result) + panic(msg) +} + /* GetAccountMetrics get account metrics API */ diff --git a/rest_model_zrok/environment.go b/rest_model_zrok/environment.go index a6041314..19a354de 100644 --- a/rest_model_zrok/environment.go +++ b/rest_model_zrok/environment.go @@ -8,6 +8,7 @@ package rest_model_zrok import ( "context" + "github.com/go-openapi/errors" "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" ) @@ -17,8 +18,8 @@ import ( // swagger:model environment type Environment struct { - // active - Active bool `json:"active,omitempty"` + // activity + Activity SparkData `json:"activity,omitempty"` // address Address string `json:"address,omitempty"` @@ -41,11 +42,60 @@ type Environment struct { // Validate validates this environment func (m *Environment) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateActivity(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } return nil } -// ContextValidate validates this environment based on context it is used +func (m *Environment) validateActivity(formats strfmt.Registry) error { + if swag.IsZero(m.Activity) { // not required + return nil + } + + if err := m.Activity.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("activity") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("activity") + } + return err + } + + return nil +} + +// ContextValidate validate this environment based on the context it is used func (m *Environment) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateActivity(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *Environment) contextValidateActivity(ctx context.Context, formats strfmt.Registry) error { + + if err := m.Activity.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("activity") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("activity") + } + return err + } + return nil } diff --git a/rest_server_zrok/embedded_spec.go b/rest_server_zrok/embedded_spec.go index d41988ff..03a22b60 100644 --- a/rest_server_zrok/embedded_spec.go +++ b/rest_server_zrok/embedded_spec.go @@ -90,6 +90,30 @@ func init() { } } }, + "/detail/account": { + "get": { + "security": [ + { + "key": [] + } + ], + "tags": [ + "metadata" + ], + "operationId": "getAccountDetail", + "responses": { + "200": { + "description": "ok", + "schema": { + "$ref": "#/definitions/environments" + } + }, + "500": { + "description": "internal server error" + } + } + } + }, "/detail/environment/{envZId}": { "get": { "security": [ @@ -1065,8 +1089,8 @@ func init() { "environment": { "type": "object", "properties": { - "active": { - "type": "boolean" + "activity": { + "$ref": "#/definitions/sparkData" }, "address": { "type": "string" @@ -1537,6 +1561,30 @@ func init() { } } }, + "/detail/account": { + "get": { + "security": [ + { + "key": [] + } + ], + "tags": [ + "metadata" + ], + "operationId": "getAccountDetail", + "responses": { + "200": { + "description": "ok", + "schema": { + "$ref": "#/definitions/environments" + } + }, + "500": { + "description": "internal server error" + } + } + } + }, "/detail/environment/{envZId}": { "get": { "security": [ @@ -2512,8 +2560,8 @@ func init() { "environment": { "type": "object", "properties": { - "active": { - "type": "boolean" + "activity": { + "$ref": "#/definitions/sparkData" }, "address": { "type": "string" diff --git a/rest_server_zrok/operations/metadata/get_account_detail.go b/rest_server_zrok/operations/metadata/get_account_detail.go new file mode 100644 index 00000000..3df45d07 --- /dev/null +++ b/rest_server_zrok/operations/metadata/get_account_detail.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package metadata + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" + + "github.com/openziti/zrok/rest_model_zrok" +) + +// GetAccountDetailHandlerFunc turns a function with the right signature into a get account detail handler +type GetAccountDetailHandlerFunc func(GetAccountDetailParams, *rest_model_zrok.Principal) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetAccountDetailHandlerFunc) Handle(params GetAccountDetailParams, principal *rest_model_zrok.Principal) middleware.Responder { + return fn(params, principal) +} + +// GetAccountDetailHandler interface for that can handle valid get account detail params +type GetAccountDetailHandler interface { + Handle(GetAccountDetailParams, *rest_model_zrok.Principal) middleware.Responder +} + +// NewGetAccountDetail creates a new http.Handler for the get account detail operation +func NewGetAccountDetail(ctx *middleware.Context, handler GetAccountDetailHandler) *GetAccountDetail { + return &GetAccountDetail{Context: ctx, Handler: handler} +} + +/* + GetAccountDetail swagger:route GET /detail/account metadata getAccountDetail + +GetAccountDetail get account detail API +*/ +type GetAccountDetail struct { + Context *middleware.Context + Handler GetAccountDetailHandler +} + +func (o *GetAccountDetail) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetAccountDetailParams() + uprinc, aCtx, err := o.Context.Authorize(r, route) + if err != nil { + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + if aCtx != nil { + *r = *aCtx + } + var principal *rest_model_zrok.Principal + if uprinc != nil { + principal = uprinc.(*rest_model_zrok.Principal) // this is really a rest_model_zrok.Principal, I promise + } + + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params, principal) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/rest_server_zrok/operations/metadata/get_account_detail_parameters.go b/rest_server_zrok/operations/metadata/get_account_detail_parameters.go new file mode 100644 index 00000000..2702d68e --- /dev/null +++ b/rest_server_zrok/operations/metadata/get_account_detail_parameters.go @@ -0,0 +1,46 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package metadata + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" +) + +// NewGetAccountDetailParams creates a new GetAccountDetailParams object +// +// There are no default values defined in the spec. +func NewGetAccountDetailParams() GetAccountDetailParams { + + return GetAccountDetailParams{} +} + +// GetAccountDetailParams contains all the bound params for the get account detail operation +// typically these are obtained from a http.Request +// +// swagger:parameters getAccountDetail +type GetAccountDetailParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetAccountDetailParams() beforehand. +func (o *GetAccountDetailParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/rest_server_zrok/operations/metadata/get_account_detail_responses.go b/rest_server_zrok/operations/metadata/get_account_detail_responses.go new file mode 100644 index 00000000..78b271c3 --- /dev/null +++ b/rest_server_zrok/operations/metadata/get_account_detail_responses.go @@ -0,0 +1,87 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package metadata + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/openziti/zrok/rest_model_zrok" +) + +// GetAccountDetailOKCode is the HTTP code returned for type GetAccountDetailOK +const GetAccountDetailOKCode int = 200 + +/* +GetAccountDetailOK ok + +swagger:response getAccountDetailOK +*/ +type GetAccountDetailOK struct { + + /* + In: Body + */ + Payload rest_model_zrok.Environments `json:"body,omitempty"` +} + +// NewGetAccountDetailOK creates GetAccountDetailOK with default headers values +func NewGetAccountDetailOK() *GetAccountDetailOK { + + return &GetAccountDetailOK{} +} + +// WithPayload adds the payload to the get account detail o k response +func (o *GetAccountDetailOK) WithPayload(payload rest_model_zrok.Environments) *GetAccountDetailOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get account detail o k response +func (o *GetAccountDetailOK) SetPayload(payload rest_model_zrok.Environments) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetAccountDetailOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if payload == nil { + // return empty array + payload = rest_model_zrok.Environments{} + } + + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetAccountDetailInternalServerErrorCode is the HTTP code returned for type GetAccountDetailInternalServerError +const GetAccountDetailInternalServerErrorCode int = 500 + +/* +GetAccountDetailInternalServerError internal server error + +swagger:response getAccountDetailInternalServerError +*/ +type GetAccountDetailInternalServerError struct { +} + +// NewGetAccountDetailInternalServerError creates GetAccountDetailInternalServerError with default headers values +func NewGetAccountDetailInternalServerError() *GetAccountDetailInternalServerError { + + return &GetAccountDetailInternalServerError{} +} + +// WriteResponse to the client +func (o *GetAccountDetailInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(500) +} diff --git a/rest_server_zrok/operations/metadata/get_account_detail_urlbuilder.go b/rest_server_zrok/operations/metadata/get_account_detail_urlbuilder.go new file mode 100644 index 00000000..b7eda126 --- /dev/null +++ b/rest_server_zrok/operations/metadata/get_account_detail_urlbuilder.go @@ -0,0 +1,87 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package metadata + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" +) + +// GetAccountDetailURL generates an URL for the get account detail operation +type GetAccountDetailURL struct { + _basePath string +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetAccountDetailURL) WithBasePath(bp string) *GetAccountDetailURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetAccountDetailURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetAccountDetailURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/detail/account" + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/api/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetAccountDetailURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetAccountDetailURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetAccountDetailURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetAccountDetailURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetAccountDetailURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetAccountDetailURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/rest_server_zrok/operations/zrok_api.go b/rest_server_zrok/operations/zrok_api.go index 61b9bad1..ed5c7721 100644 --- a/rest_server_zrok/operations/zrok_api.go +++ b/rest_server_zrok/operations/zrok_api.go @@ -70,6 +70,9 @@ func NewZrokAPI(spec *loads.Document) *ZrokAPI { EnvironmentEnableHandler: environment.EnableHandlerFunc(func(params environment.EnableParams, principal *rest_model_zrok.Principal) middleware.Responder { return middleware.NotImplemented("operation environment.Enable has not yet been implemented") }), + MetadataGetAccountDetailHandler: metadata.GetAccountDetailHandlerFunc(func(params metadata.GetAccountDetailParams, principal *rest_model_zrok.Principal) middleware.Responder { + return middleware.NotImplemented("operation metadata.GetAccountDetail has not yet been implemented") + }), MetadataGetAccountMetricsHandler: metadata.GetAccountMetricsHandlerFunc(func(params metadata.GetAccountMetricsParams, principal *rest_model_zrok.Principal) middleware.Responder { return middleware.NotImplemented("operation metadata.GetAccountMetrics has not yet been implemented") }), @@ -194,6 +197,8 @@ type ZrokAPI struct { EnvironmentDisableHandler environment.DisableHandler // EnvironmentEnableHandler sets the operation handler for the enable operation EnvironmentEnableHandler environment.EnableHandler + // MetadataGetAccountDetailHandler sets the operation handler for the get account detail operation + MetadataGetAccountDetailHandler metadata.GetAccountDetailHandler // MetadataGetAccountMetricsHandler sets the operation handler for the get account metrics operation MetadataGetAccountMetricsHandler metadata.GetAccountMetricsHandler // MetadataGetEnvironmentDetailHandler sets the operation handler for the get environment detail operation @@ -336,6 +341,9 @@ func (o *ZrokAPI) Validate() error { if o.EnvironmentEnableHandler == nil { unregistered = append(unregistered, "environment.EnableHandler") } + if o.MetadataGetAccountDetailHandler == nil { + unregistered = append(unregistered, "metadata.GetAccountDetailHandler") + } if o.MetadataGetAccountMetricsHandler == nil { unregistered = append(unregistered, "metadata.GetAccountMetricsHandler") } @@ -526,6 +534,10 @@ func (o *ZrokAPI) initHandlerCache() { if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } + o.handlers["GET"]["/detail/account"] = metadata.NewGetAccountDetail(o.context, o.MetadataGetAccountDetailHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } o.handlers["GET"]["/metrics/account"] = metadata.NewGetAccountMetrics(o.context, o.MetadataGetAccountMetricsHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) diff --git a/specs/zrok.yml b/specs/zrok.yml index 39fe9033..38897e48 100644 --- a/specs/zrok.yml +++ b/specs/zrok.yml @@ -329,6 +329,21 @@ paths: schema: $ref: "#/definitions/configuration" + /detail/account: + get: + tags: + - metadata + security: + - key: [] + operationId: getAccountDetail + responses: + 200: + description: ok + schema: + $ref: "#/definitions/environments" + 500: + description: internal server error + /detail/environment/{envZId}: get: tags: @@ -689,8 +704,8 @@ definitions: type: string zId: type: string - active: - type: boolean + activity: + $ref: "#/definitions/sparkData" createdAt: type: integer updatedAt: @@ -856,19 +871,6 @@ definitions: items: $ref: "#/definitions/share" - sparkData: - type: array - items: - $ref: "#/definitions/sparkDataSample" - - sparkDataSample: - type: object - properties: - rx: - type: number - tx: - type: number - shareRequest: type: object properties: @@ -905,6 +907,19 @@ definitions: shrToken: type: string + sparkData: + type: array + items: + $ref: "#/definitions/sparkDataSample" + + sparkDataSample: + type: object + properties: + rx: + type: number + tx: + type: number + unaccessRequest: type: object properties: diff --git a/ui/src/api/metadata.js b/ui/src/api/metadata.js index 7b8af17a..1b50438f 100644 --- a/ui/src/api/metadata.js +++ b/ui/src/api/metadata.js @@ -8,6 +8,12 @@ export function configuration() { return gateway.request(configurationOperation) } +/** + */ +export function getAccountDetail() { + return gateway.request(getAccountDetailOperation) +} + /** * @param {string} envZId * @return {Promise} ok @@ -104,6 +110,16 @@ const configurationOperation = { method: 'get' } +const getAccountDetailOperation = { + path: '/detail/account', + method: 'get', + security: [ + { + id: 'key' + } + ] +} + const getEnvironmentDetailOperation = { path: '/detail/environment/{envZId}', method: 'get', diff --git a/ui/src/api/types.js b/ui/src/api/types.js index 09093d0e..4d5a07cb 100644 --- a/ui/src/api/types.js +++ b/ui/src/api/types.js @@ -87,7 +87,7 @@ * @property {string} host * @property {string} address * @property {string} zId - * @property {boolean} active + * @property {module:types.sparkData} activity * @property {number} createdAt * @property {number} updatedAt */ @@ -205,14 +205,6 @@ * @property {number} updatedAt */ -/** - * @typedef sparkDataSample - * @memberof module:types - * - * @property {number} rx - * @property {number} tx - */ - /** * @typedef shareRequest * @memberof module:types @@ -235,6 +227,14 @@ * @property {string} shrToken */ +/** + * @typedef sparkDataSample + * @memberof module:types + * + * @property {number} rx + * @property {number} tx + */ + /** * @typedef unaccessRequest * @memberof module:types