diff --git a/api/inventory/v1/json/client/nodes_service/add_node_responses.go b/api/inventory/v1/json/client/nodes_service/add_node_responses.go index 9b1e2539870..12383d2e292 100644 --- a/api/inventory/v1/json/client/nodes_service/add_node_responses.go +++ b/api/inventory/v1/json/client/nodes_service/add_node_responses.go @@ -201,6 +201,9 @@ type AddNodeBody struct { // remote azure RemoteAzure *AddNodeParamsBodyRemoteAzure `json:"remote_azure,omitempty"` + // remote elasticache + RemoteElasticache *AddNodeParamsBodyRemoteElasticache `json:"remote_elasticache,omitempty"` + // remote rds RemoteRDS *AddNodeParamsBodyRemoteRDS `json:"remote_rds,omitempty"` } @@ -225,6 +228,10 @@ func (o *AddNodeBody) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := o.validateRemoteElasticache(formats); err != nil { + res = append(res, err) + } + if err := o.validateRemoteRDS(formats); err != nil { res = append(res, err) } @@ -327,6 +334,29 @@ func (o *AddNodeBody) validateRemoteAzure(formats strfmt.Registry) error { return nil } +func (o *AddNodeBody) validateRemoteElasticache(formats strfmt.Registry) error { + if swag.IsZero(o.RemoteElasticache) { // not required + return nil + } + + if o.RemoteElasticache != nil { + if err := o.RemoteElasticache.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("body" + "." + "remote_elasticache") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("body" + "." + "remote_elasticache") + } + + return err + } + } + + return nil +} + func (o *AddNodeBody) validateRemoteRDS(formats strfmt.Registry) error { if swag.IsZero(o.RemoteRDS) { // not required return nil @@ -370,6 +400,10 @@ func (o *AddNodeBody) ContextValidate(ctx context.Context, formats strfmt.Regist res = append(res, err) } + if err := o.contextValidateRemoteElasticache(ctx, formats); err != nil { + res = append(res, err) + } + if err := o.contextValidateRemoteRDS(ctx, formats); err != nil { res = append(res, err) } @@ -476,6 +510,30 @@ func (o *AddNodeBody) contextValidateRemoteAzure(ctx context.Context, formats st return nil } +func (o *AddNodeBody) contextValidateRemoteElasticache(ctx context.Context, formats strfmt.Registry) error { + if o.RemoteElasticache != nil { + + if swag.IsZero(o.RemoteElasticache) { // not required + return nil + } + + if err := o.RemoteElasticache.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("body" + "." + "remote_elasticache") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("body" + "." + "remote_elasticache") + } + + return err + } + } + + return nil +} + func (o *AddNodeBody) contextValidateRemoteRDS(ctx context.Context, formats strfmt.Registry) error { if o.RemoteRDS != nil { @@ -763,6 +821,9 @@ type AddNodeOKBody struct { // remote azure database RemoteAzureDatabase *AddNodeOKBodyRemoteAzureDatabase `json:"remote_azure_database,omitempty"` + // remote elasticache + RemoteElasticache *AddNodeOKBodyRemoteElasticache `json:"remote_elasticache,omitempty"` + // remote rds RemoteRDS *AddNodeOKBodyRemoteRDS `json:"remote_rds,omitempty"` } @@ -787,6 +848,10 @@ func (o *AddNodeOKBody) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := o.validateRemoteElasticache(formats); err != nil { + res = append(res, err) + } + if err := o.validateRemoteRDS(formats); err != nil { res = append(res, err) } @@ -889,6 +954,29 @@ func (o *AddNodeOKBody) validateRemoteAzureDatabase(formats strfmt.Registry) err return nil } +func (o *AddNodeOKBody) validateRemoteElasticache(formats strfmt.Registry) error { + if swag.IsZero(o.RemoteElasticache) { // not required + return nil + } + + if o.RemoteElasticache != nil { + if err := o.RemoteElasticache.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addNodeOk" + "." + "remote_elasticache") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addNodeOk" + "." + "remote_elasticache") + } + + return err + } + } + + return nil +} + func (o *AddNodeOKBody) validateRemoteRDS(formats strfmt.Registry) error { if swag.IsZero(o.RemoteRDS) { // not required return nil @@ -932,6 +1020,10 @@ func (o *AddNodeOKBody) ContextValidate(ctx context.Context, formats strfmt.Regi res = append(res, err) } + if err := o.contextValidateRemoteElasticache(ctx, formats); err != nil { + res = append(res, err) + } + if err := o.contextValidateRemoteRDS(ctx, formats); err != nil { res = append(res, err) } @@ -1038,6 +1130,30 @@ func (o *AddNodeOKBody) contextValidateRemoteAzureDatabase(ctx context.Context, return nil } +func (o *AddNodeOKBody) contextValidateRemoteElasticache(ctx context.Context, formats strfmt.Registry) error { + if o.RemoteElasticache != nil { + + if swag.IsZero(o.RemoteElasticache) { // not required + return nil + } + + if err := o.RemoteElasticache.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addNodeOk" + "." + "remote_elasticache") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addNodeOk" + "." + "remote_elasticache") + } + + return err + } + } + + return nil +} + func (o *AddNodeOKBody) contextValidateRemoteRDS(ctx context.Context, formats strfmt.Registry) error { if o.RemoteRDS != nil { @@ -1321,6 +1437,64 @@ func (o *AddNodeOKBodyRemoteAzureDatabase) UnmarshalBinary(b []byte) error { return nil } +/* +AddNodeOKBodyRemoteElasticache RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes. +swagger:model AddNodeOKBodyRemoteElasticache +*/ +type AddNodeOKBodyRemoteElasticache struct { + // Unique randomly generated instance identifier. + NodeID string `json:"node_id,omitempty"` + + // Unique across all Nodes user-defined name. + NodeName string `json:"node_name,omitempty"` + + // ElastiCache primary endpoint address. + Address string `json:"address,omitempty"` + + // Node model (cache node type). + NodeModel string `json:"node_model,omitempty"` + + // Node region. + Region string `json:"region,omitempty"` + + // Node availability zone. + Az string `json:"az,omitempty"` + + // Custom user-assigned labels. + CustomLabels map[string]string `json:"custom_labels,omitempty"` + + // AWS instance ID (replication group ID). + InstanceID string `json:"instance_id,omitempty"` +} + +// Validate validates this add node OK body remote elasticache +func (o *AddNodeOKBodyRemoteElasticache) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this add node OK body remote elasticache based on context it is used +func (o *AddNodeOKBodyRemoteElasticache) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *AddNodeOKBodyRemoteElasticache) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *AddNodeOKBodyRemoteElasticache) UnmarshalBinary(b []byte) error { + var res AddNodeOKBodyRemoteElasticache + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + /* AddNodeOKBodyRemoteRDS RemoteRDSNode represents remote RDS Node. Agents can't run on Remote RDS Nodes. swagger:model AddNodeOKBodyRemoteRDS @@ -1602,6 +1776,61 @@ func (o *AddNodeParamsBodyRemoteAzure) UnmarshalBinary(b []byte) error { return nil } +/* +AddNodeParamsBodyRemoteElasticache add node params body remote elasticache +swagger:model AddNodeParamsBodyRemoteElasticache +*/ +type AddNodeParamsBodyRemoteElasticache struct { + // Unique across all Nodes user-defined name. + NodeName string `json:"node_name,omitempty"` + + // ElastiCache primary endpoint address. + Address string `json:"address,omitempty"` + + // Node model (cache node type). + NodeModel string `json:"node_model,omitempty"` + + // Node region. + Region string `json:"region,omitempty"` + + // Node availability zone. + Az string `json:"az,omitempty"` + + // Custom user-assigned labels. + CustomLabels map[string]string `json:"custom_labels,omitempty"` + + // AWS instance ID (replication group ID). + InstanceID string `json:"instance_id,omitempty"` +} + +// Validate validates this add node params body remote elasticache +func (o *AddNodeParamsBodyRemoteElasticache) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this add node params body remote elasticache based on context it is used +func (o *AddNodeParamsBodyRemoteElasticache) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *AddNodeParamsBodyRemoteElasticache) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *AddNodeParamsBodyRemoteElasticache) UnmarshalBinary(b []byte) error { + var res AddNodeParamsBodyRemoteElasticache + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + /* AddNodeParamsBodyRemoteRDS add node params body remote RDS swagger:model AddNodeParamsBodyRemoteRDS diff --git a/api/inventory/v1/json/client/nodes_service/get_node_responses.go b/api/inventory/v1/json/client/nodes_service/get_node_responses.go index ec4913b0da3..fb0e07aa6e9 100644 --- a/api/inventory/v1/json/client/nodes_service/get_node_responses.go +++ b/api/inventory/v1/json/client/nodes_service/get_node_responses.go @@ -429,6 +429,9 @@ type GetNodeOKBody struct { // remote azure database RemoteAzureDatabase *GetNodeOKBodyRemoteAzureDatabase `json:"remote_azure_database,omitempty"` + // remote elasticache + RemoteElasticache *GetNodeOKBodyRemoteElasticache `json:"remote_elasticache,omitempty"` + // remote rds RemoteRDS *GetNodeOKBodyRemoteRDS `json:"remote_rds,omitempty"` } @@ -453,6 +456,10 @@ func (o *GetNodeOKBody) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := o.validateRemoteElasticache(formats); err != nil { + res = append(res, err) + } + if err := o.validateRemoteRDS(formats); err != nil { res = append(res, err) } @@ -555,6 +562,29 @@ func (o *GetNodeOKBody) validateRemoteAzureDatabase(formats strfmt.Registry) err return nil } +func (o *GetNodeOKBody) validateRemoteElasticache(formats strfmt.Registry) error { + if swag.IsZero(o.RemoteElasticache) { // not required + return nil + } + + if o.RemoteElasticache != nil { + if err := o.RemoteElasticache.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("getNodeOk" + "." + "remote_elasticache") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("getNodeOk" + "." + "remote_elasticache") + } + + return err + } + } + + return nil +} + func (o *GetNodeOKBody) validateRemoteRDS(formats strfmt.Registry) error { if swag.IsZero(o.RemoteRDS) { // not required return nil @@ -598,6 +628,10 @@ func (o *GetNodeOKBody) ContextValidate(ctx context.Context, formats strfmt.Regi res = append(res, err) } + if err := o.contextValidateRemoteElasticache(ctx, formats); err != nil { + res = append(res, err) + } + if err := o.contextValidateRemoteRDS(ctx, formats); err != nil { res = append(res, err) } @@ -704,6 +738,30 @@ func (o *GetNodeOKBody) contextValidateRemoteAzureDatabase(ctx context.Context, return nil } +func (o *GetNodeOKBody) contextValidateRemoteElasticache(ctx context.Context, formats strfmt.Registry) error { + if o.RemoteElasticache != nil { + + if swag.IsZero(o.RemoteElasticache) { // not required + return nil + } + + if err := o.RemoteElasticache.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("getNodeOk" + "." + "remote_elasticache") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("getNodeOk" + "." + "remote_elasticache") + } + + return err + } + } + + return nil +} + func (o *GetNodeOKBody) contextValidateRemoteRDS(ctx context.Context, formats strfmt.Registry) error { if o.RemoteRDS != nil { @@ -987,6 +1045,64 @@ func (o *GetNodeOKBodyRemoteAzureDatabase) UnmarshalBinary(b []byte) error { return nil } +/* +GetNodeOKBodyRemoteElasticache RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes. +swagger:model GetNodeOKBodyRemoteElasticache +*/ +type GetNodeOKBodyRemoteElasticache struct { + // Unique randomly generated instance identifier. + NodeID string `json:"node_id,omitempty"` + + // Unique across all Nodes user-defined name. + NodeName string `json:"node_name,omitempty"` + + // ElastiCache primary endpoint address. + Address string `json:"address,omitempty"` + + // Node model (cache node type). + NodeModel string `json:"node_model,omitempty"` + + // Node region. + Region string `json:"region,omitempty"` + + // Node availability zone. + Az string `json:"az,omitempty"` + + // Custom user-assigned labels. + CustomLabels map[string]string `json:"custom_labels,omitempty"` + + // AWS instance ID (replication group ID). + InstanceID string `json:"instance_id,omitempty"` +} + +// Validate validates this get node OK body remote elasticache +func (o *GetNodeOKBodyRemoteElasticache) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this get node OK body remote elasticache based on context it is used +func (o *GetNodeOKBodyRemoteElasticache) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *GetNodeOKBodyRemoteElasticache) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *GetNodeOKBodyRemoteElasticache) UnmarshalBinary(b []byte) error { + var res GetNodeOKBodyRemoteElasticache + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + /* GetNodeOKBodyRemoteRDS RemoteRDSNode represents remote RDS Node. Agents can't run on Remote RDS Nodes. swagger:model GetNodeOKBodyRemoteRDS diff --git a/api/inventory/v1/json/client/nodes_service/list_nodes_responses.go b/api/inventory/v1/json/client/nodes_service/list_nodes_responses.go index ef036297fe7..ae2cd75c1e4 100644 --- a/api/inventory/v1/json/client/nodes_service/list_nodes_responses.go +++ b/api/inventory/v1/json/client/nodes_service/list_nodes_responses.go @@ -431,6 +431,9 @@ type ListNodesOKBody struct { // remote azure database RemoteAzureDatabase []*ListNodesOKBodyRemoteAzureDatabaseItems0 `json:"remote_azure_database"` + + // remote elasticache + RemoteElasticache []*ListNodesOKBodyRemoteElasticacheItems0 `json:"remote_elasticache"` } // Validate validates this list nodes OK body @@ -457,6 +460,10 @@ func (o *ListNodesOKBody) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := o.validateRemoteElasticache(formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -613,6 +620,36 @@ func (o *ListNodesOKBody) validateRemoteAzureDatabase(formats strfmt.Registry) e return nil } +func (o *ListNodesOKBody) validateRemoteElasticache(formats strfmt.Registry) error { + if swag.IsZero(o.RemoteElasticache) { // not required + return nil + } + + for i := 0; i < len(o.RemoteElasticache); i++ { + if swag.IsZero(o.RemoteElasticache[i]) { // not required + continue + } + + if o.RemoteElasticache[i] != nil { + if err := o.RemoteElasticache[i].Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("listNodesOk" + "." + "remote_elasticache" + "." + strconv.Itoa(i)) + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("listNodesOk" + "." + "remote_elasticache" + "." + strconv.Itoa(i)) + } + + return err + } + } + + } + + return nil +} + // ContextValidate validate this list nodes OK body based on the context it is used func (o *ListNodesOKBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { var res []error @@ -637,6 +674,10 @@ func (o *ListNodesOKBody) ContextValidate(ctx context.Context, formats strfmt.Re res = append(res, err) } + if err := o.contextValidateRemoteElasticache(ctx, formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -773,6 +814,32 @@ func (o *ListNodesOKBody) contextValidateRemoteAzureDatabase(ctx context.Context return nil } +func (o *ListNodesOKBody) contextValidateRemoteElasticache(ctx context.Context, formats strfmt.Registry) error { + for i := 0; i < len(o.RemoteElasticache); i++ { + if o.RemoteElasticache[i] != nil { + + if swag.IsZero(o.RemoteElasticache[i]) { // not required + return nil + } + + if err := o.RemoteElasticache[i].ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("listNodesOk" + "." + "remote_elasticache" + "." + strconv.Itoa(i)) + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("listNodesOk" + "." + "remote_elasticache" + "." + strconv.Itoa(i)) + } + + return err + } + } + } + + return nil +} + // MarshalBinary interface implementation func (o *ListNodesOKBody) MarshalBinary() ([]byte, error) { if o == nil { @@ -977,6 +1044,64 @@ func (o *ListNodesOKBodyRemoteAzureDatabaseItems0) UnmarshalBinary(b []byte) err return nil } +/* +ListNodesOKBodyRemoteElasticacheItems0 RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes. +swagger:model ListNodesOKBodyRemoteElasticacheItems0 +*/ +type ListNodesOKBodyRemoteElasticacheItems0 struct { + // Unique randomly generated instance identifier. + NodeID string `json:"node_id,omitempty"` + + // Unique across all Nodes user-defined name. + NodeName string `json:"node_name,omitempty"` + + // ElastiCache primary endpoint address. + Address string `json:"address,omitempty"` + + // Node model (cache node type). + NodeModel string `json:"node_model,omitempty"` + + // Node region. + Region string `json:"region,omitempty"` + + // Node availability zone. + Az string `json:"az,omitempty"` + + // Custom user-assigned labels. + CustomLabels map[string]string `json:"custom_labels,omitempty"` + + // AWS instance ID (replication group ID). + InstanceID string `json:"instance_id,omitempty"` +} + +// Validate validates this list nodes OK body remote elasticache items0 +func (o *ListNodesOKBodyRemoteElasticacheItems0) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this list nodes OK body remote elasticache items0 based on context it is used +func (o *ListNodesOKBodyRemoteElasticacheItems0) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *ListNodesOKBodyRemoteElasticacheItems0) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *ListNodesOKBodyRemoteElasticacheItems0) UnmarshalBinary(b []byte) error { + var res ListNodesOKBodyRemoteElasticacheItems0 + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + /* ListNodesOKBodyRemoteItems0 RemoteNode represents generic remote Node. It's a node where we don't run pmm-agents. Only external exporters can run on Remote Nodes. swagger:model ListNodesOKBodyRemoteItems0 diff --git a/api/inventory/v1/json/v1.json b/api/inventory/v1/json/v1.json index 1b0a2395e83..e088e0ea822 100644 --- a/api/inventory/v1/json/v1.json +++ b/api/inventory/v1/json/v1.json @@ -12188,7 +12188,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "type": "string", "default": "NODE_TYPE_UNSPECIFIED", @@ -12482,6 +12483,59 @@ } }, "x-order": 4 + }, + "remote_elasticache": { + "type": "array", + "items": { + "description": "RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes.", + "type": "object", + "properties": { + "node_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 1 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 3 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 4 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 5 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 6 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 7 + } + } + }, + "x-order": 5 } } } @@ -12753,6 +12807,50 @@ } }, "x-order": 4 + }, + "remote_elasticache": { + "type": "object", + "properties": { + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 0 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 1 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 2 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 3 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 4 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 5 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 6 + } + }, + "x-order": 5 } } } @@ -13028,6 +13126,56 @@ } }, "x-order": 4 + }, + "remote_elasticache": { + "description": "RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes.", + "type": "object", + "properties": { + "node_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 1 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 3 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 4 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 5 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 6 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 7 + } + }, + "x-order": 5 } } } @@ -13353,6 +13501,56 @@ } }, "x-order": 4 + }, + "remote_elasticache": { + "description": "RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes.", + "type": "object", + "properties": { + "node_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 1 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 3 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 4 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 5 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 6 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 7 + } + }, + "x-order": 5 } } } diff --git a/api/inventory/v1/nodes.go b/api/inventory/v1/nodes.go index 17876875dc0..3461f624bd9 100644 --- a/api/inventory/v1/nodes.go +++ b/api/inventory/v1/nodes.go @@ -29,3 +29,4 @@ func (*ContainerNode) sealedNode() {} func (*RemoteNode) sealedNode() {} func (*RemoteRDSNode) sealedNode() {} func (*RemoteAzureDatabaseNode) sealedNode() {} +func (*RemoteElastiCacheNode) sealedNode() {} diff --git a/api/inventory/v1/nodes.pb.go b/api/inventory/v1/nodes.pb.go index 447663477a9..db105d49b48 100644 --- a/api/inventory/v1/nodes.pb.go +++ b/api/inventory/v1/nodes.pb.go @@ -35,6 +35,7 @@ const ( NodeType_NODE_TYPE_REMOTE_NODE NodeType = 3 NodeType_NODE_TYPE_REMOTE_RDS_NODE NodeType = 4 NodeType_NODE_TYPE_REMOTE_AZURE_DATABASE_NODE NodeType = 5 + NodeType_NODE_TYPE_REMOTE_ELASTICACHE_NODE NodeType = 6 ) // Enum value maps for NodeType. @@ -46,6 +47,7 @@ var ( 3: "NODE_TYPE_REMOTE_NODE", 4: "NODE_TYPE_REMOTE_RDS_NODE", 5: "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + 6: "NODE_TYPE_REMOTE_ELASTICACHE_NODE", } NodeType_value = map[string]int32{ "NODE_TYPE_UNSPECIFIED": 0, @@ -54,6 +56,7 @@ var ( "NODE_TYPE_REMOTE_NODE": 3, "NODE_TYPE_REMOTE_RDS_NODE": 4, "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE": 5, + "NODE_TYPE_REMOTE_ELASTICACHE_NODE": 6, } ) @@ -656,6 +659,115 @@ func (x *RemoteAzureDatabaseNode) GetCustomLabels() map[string]string { return nil } +// RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes. +type RemoteElastiCacheNode struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Unique randomly generated instance identifier. + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + // Unique across all Nodes user-defined name. + NodeName string `protobuf:"bytes,2,opt,name=node_name,json=nodeName,proto3" json:"node_name,omitempty"` + // ElastiCache primary endpoint address. + Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"` + // Node model (cache node type). + NodeModel string `protobuf:"bytes,4,opt,name=node_model,json=nodeModel,proto3" json:"node_model,omitempty"` + // Node region. + Region string `protobuf:"bytes,5,opt,name=region,proto3" json:"region,omitempty"` + // Node availability zone. + Az string `protobuf:"bytes,6,opt,name=az,proto3" json:"az,omitempty"` + // Custom user-assigned labels. + CustomLabels map[string]string `protobuf:"bytes,7,rep,name=custom_labels,json=customLabels,proto3" json:"custom_labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // AWS instance ID (replication group ID). + InstanceId string `protobuf:"bytes,8,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RemoteElastiCacheNode) Reset() { + *x = RemoteElastiCacheNode{} + mi := &file_inventory_v1_nodes_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RemoteElastiCacheNode) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoteElastiCacheNode) ProtoMessage() {} + +func (x *RemoteElastiCacheNode) ProtoReflect() protoreflect.Message { + mi := &file_inventory_v1_nodes_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoteElastiCacheNode.ProtoReflect.Descriptor instead. +func (*RemoteElastiCacheNode) Descriptor() ([]byte, []int) { + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{5} +} + +func (x *RemoteElastiCacheNode) GetNodeId() string { + if x != nil { + return x.NodeId + } + return "" +} + +func (x *RemoteElastiCacheNode) GetNodeName() string { + if x != nil { + return x.NodeName + } + return "" +} + +func (x *RemoteElastiCacheNode) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *RemoteElastiCacheNode) GetNodeModel() string { + if x != nil { + return x.NodeModel + } + return "" +} + +func (x *RemoteElastiCacheNode) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *RemoteElastiCacheNode) GetAz() string { + if x != nil { + return x.Az + } + return "" +} + +func (x *RemoteElastiCacheNode) GetCustomLabels() map[string]string { + if x != nil { + return x.CustomLabels + } + return nil +} + +func (x *RemoteElastiCacheNode) GetInstanceId() string { + if x != nil { + return x.InstanceId + } + return "" +} + type ListNodesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Return only Nodes with matching Node type. @@ -666,7 +778,7 @@ type ListNodesRequest struct { func (x *ListNodesRequest) Reset() { *x = ListNodesRequest{} - mi := &file_inventory_v1_nodes_proto_msgTypes[5] + mi := &file_inventory_v1_nodes_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -678,7 +790,7 @@ func (x *ListNodesRequest) String() string { func (*ListNodesRequest) ProtoMessage() {} func (x *ListNodesRequest) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[5] + mi := &file_inventory_v1_nodes_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -691,7 +803,7 @@ func (x *ListNodesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListNodesRequest.ProtoReflect.Descriptor instead. func (*ListNodesRequest) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{5} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{6} } func (x *ListNodesRequest) GetNodeType() NodeType { @@ -708,13 +820,14 @@ type ListNodesResponse struct { Remote []*RemoteNode `protobuf:"bytes,3,rep,name=remote,proto3" json:"remote,omitempty"` RemoteRds []*RemoteRDSNode `protobuf:"bytes,4,rep,name=remote_rds,json=remoteRds,proto3" json:"remote_rds,omitempty"` RemoteAzureDatabase []*RemoteAzureDatabaseNode `protobuf:"bytes,5,rep,name=remote_azure_database,json=remoteAzureDatabase,proto3" json:"remote_azure_database,omitempty"` + RemoteElasticache []*RemoteElastiCacheNode `protobuf:"bytes,6,rep,name=remote_elasticache,json=remoteElasticache,proto3" json:"remote_elasticache,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *ListNodesResponse) Reset() { *x = ListNodesResponse{} - mi := &file_inventory_v1_nodes_proto_msgTypes[6] + mi := &file_inventory_v1_nodes_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -726,7 +839,7 @@ func (x *ListNodesResponse) String() string { func (*ListNodesResponse) ProtoMessage() {} func (x *ListNodesResponse) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[6] + mi := &file_inventory_v1_nodes_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -739,7 +852,7 @@ func (x *ListNodesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListNodesResponse.ProtoReflect.Descriptor instead. func (*ListNodesResponse) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{6} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{7} } func (x *ListNodesResponse) GetGeneric() []*GenericNode { @@ -777,6 +890,13 @@ func (x *ListNodesResponse) GetRemoteAzureDatabase() []*RemoteAzureDatabaseNode return nil } +func (x *ListNodesResponse) GetRemoteElasticache() []*RemoteElastiCacheNode { + if x != nil { + return x.RemoteElasticache + } + return nil +} + type GetNodeRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Unique randomly generated instance identifier. @@ -787,7 +907,7 @@ type GetNodeRequest struct { func (x *GetNodeRequest) Reset() { *x = GetNodeRequest{} - mi := &file_inventory_v1_nodes_proto_msgTypes[7] + mi := &file_inventory_v1_nodes_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -799,7 +919,7 @@ func (x *GetNodeRequest) String() string { func (*GetNodeRequest) ProtoMessage() {} func (x *GetNodeRequest) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[7] + mi := &file_inventory_v1_nodes_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -812,7 +932,7 @@ func (x *GetNodeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetNodeRequest.ProtoReflect.Descriptor instead. func (*GetNodeRequest) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{7} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{8} } func (x *GetNodeRequest) GetNodeId() string { @@ -831,6 +951,7 @@ type GetNodeResponse struct { // *GetNodeResponse_Remote // *GetNodeResponse_RemoteRds // *GetNodeResponse_RemoteAzureDatabase + // *GetNodeResponse_RemoteElasticache Node isGetNodeResponse_Node `protobuf_oneof:"node"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -838,7 +959,7 @@ type GetNodeResponse struct { func (x *GetNodeResponse) Reset() { *x = GetNodeResponse{} - mi := &file_inventory_v1_nodes_proto_msgTypes[8] + mi := &file_inventory_v1_nodes_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -850,7 +971,7 @@ func (x *GetNodeResponse) String() string { func (*GetNodeResponse) ProtoMessage() {} func (x *GetNodeResponse) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[8] + mi := &file_inventory_v1_nodes_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -863,7 +984,7 @@ func (x *GetNodeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetNodeResponse.ProtoReflect.Descriptor instead. func (*GetNodeResponse) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{8} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{9} } func (x *GetNodeResponse) GetNode() isGetNodeResponse_Node { @@ -918,6 +1039,15 @@ func (x *GetNodeResponse) GetRemoteAzureDatabase() *RemoteAzureDatabaseNode { return nil } +func (x *GetNodeResponse) GetRemoteElasticache() *RemoteElastiCacheNode { + if x != nil { + if x, ok := x.Node.(*GetNodeResponse_RemoteElasticache); ok { + return x.RemoteElasticache + } + } + return nil +} + type isGetNodeResponse_Node interface { isGetNodeResponse_Node() } @@ -942,6 +1072,10 @@ type GetNodeResponse_RemoteAzureDatabase struct { RemoteAzureDatabase *RemoteAzureDatabaseNode `protobuf:"bytes,5,opt,name=remote_azure_database,json=remoteAzureDatabase,proto3,oneof"` } +type GetNodeResponse_RemoteElasticache struct { + RemoteElasticache *RemoteElastiCacheNode `protobuf:"bytes,6,opt,name=remote_elasticache,json=remoteElasticache,proto3,oneof"` +} + func (*GetNodeResponse_Generic) isGetNodeResponse_Node() {} func (*GetNodeResponse_Container) isGetNodeResponse_Node() {} @@ -952,6 +1086,8 @@ func (*GetNodeResponse_RemoteRds) isGetNodeResponse_Node() {} func (*GetNodeResponse_RemoteAzureDatabase) isGetNodeResponse_Node() {} +func (*GetNodeResponse_RemoteElasticache) isGetNodeResponse_Node() {} + type AddNodeRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Types that are valid to be assigned to Node: @@ -961,6 +1097,7 @@ type AddNodeRequest struct { // *AddNodeRequest_Remote // *AddNodeRequest_RemoteRds // *AddNodeRequest_RemoteAzure + // *AddNodeRequest_RemoteElasticache Node isAddNodeRequest_Node `protobuf_oneof:"node"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -968,7 +1105,7 @@ type AddNodeRequest struct { func (x *AddNodeRequest) Reset() { *x = AddNodeRequest{} - mi := &file_inventory_v1_nodes_proto_msgTypes[9] + mi := &file_inventory_v1_nodes_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -980,7 +1117,7 @@ func (x *AddNodeRequest) String() string { func (*AddNodeRequest) ProtoMessage() {} func (x *AddNodeRequest) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[9] + mi := &file_inventory_v1_nodes_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -993,7 +1130,7 @@ func (x *AddNodeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AddNodeRequest.ProtoReflect.Descriptor instead. func (*AddNodeRequest) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{9} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{10} } func (x *AddNodeRequest) GetNode() isAddNodeRequest_Node { @@ -1048,6 +1185,15 @@ func (x *AddNodeRequest) GetRemoteAzure() *AddRemoteAzureNodeParams { return nil } +func (x *AddNodeRequest) GetRemoteElasticache() *AddRemoteElastiCacheNodeParams { + if x != nil { + if x, ok := x.Node.(*AddNodeRequest_RemoteElasticache); ok { + return x.RemoteElasticache + } + } + return nil +} + type isAddNodeRequest_Node interface { isAddNodeRequest_Node() } @@ -1072,6 +1218,10 @@ type AddNodeRequest_RemoteAzure struct { RemoteAzure *AddRemoteAzureNodeParams `protobuf:"bytes,5,opt,name=remote_azure,json=remoteAzure,proto3,oneof"` } +type AddNodeRequest_RemoteElasticache struct { + RemoteElasticache *AddRemoteElastiCacheNodeParams `protobuf:"bytes,6,opt,name=remote_elasticache,json=remoteElasticache,proto3,oneof"` +} + func (*AddNodeRequest_Generic) isAddNodeRequest_Node() {} func (*AddNodeRequest_Container) isAddNodeRequest_Node() {} @@ -1082,6 +1232,8 @@ func (*AddNodeRequest_RemoteRds) isAddNodeRequest_Node() {} func (*AddNodeRequest_RemoteAzure) isAddNodeRequest_Node() {} +func (*AddNodeRequest_RemoteElasticache) isAddNodeRequest_Node() {} + type AddNodeResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Types that are valid to be assigned to Node: @@ -1091,6 +1243,7 @@ type AddNodeResponse struct { // *AddNodeResponse_Remote // *AddNodeResponse_RemoteRds // *AddNodeResponse_RemoteAzureDatabase + // *AddNodeResponse_RemoteElasticache Node isAddNodeResponse_Node `protobuf_oneof:"node"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -1098,7 +1251,7 @@ type AddNodeResponse struct { func (x *AddNodeResponse) Reset() { *x = AddNodeResponse{} - mi := &file_inventory_v1_nodes_proto_msgTypes[10] + mi := &file_inventory_v1_nodes_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1110,7 +1263,7 @@ func (x *AddNodeResponse) String() string { func (*AddNodeResponse) ProtoMessage() {} func (x *AddNodeResponse) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[10] + mi := &file_inventory_v1_nodes_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1123,7 +1276,7 @@ func (x *AddNodeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AddNodeResponse.ProtoReflect.Descriptor instead. func (*AddNodeResponse) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{10} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{11} } func (x *AddNodeResponse) GetNode() isAddNodeResponse_Node { @@ -1178,6 +1331,15 @@ func (x *AddNodeResponse) GetRemoteAzureDatabase() *RemoteAzureDatabaseNode { return nil } +func (x *AddNodeResponse) GetRemoteElasticache() *RemoteElastiCacheNode { + if x != nil { + if x, ok := x.Node.(*AddNodeResponse_RemoteElasticache); ok { + return x.RemoteElasticache + } + } + return nil +} + type isAddNodeResponse_Node interface { isAddNodeResponse_Node() } @@ -1202,6 +1364,10 @@ type AddNodeResponse_RemoteAzureDatabase struct { RemoteAzureDatabase *RemoteAzureDatabaseNode `protobuf:"bytes,5,opt,name=remote_azure_database,json=remoteAzureDatabase,proto3,oneof"` } +type AddNodeResponse_RemoteElasticache struct { + RemoteElasticache *RemoteElastiCacheNode `protobuf:"bytes,6,opt,name=remote_elasticache,json=remoteElasticache,proto3,oneof"` +} + func (*AddNodeResponse_Generic) isAddNodeResponse_Node() {} func (*AddNodeResponse_Container) isAddNodeResponse_Node() {} @@ -1212,6 +1378,8 @@ func (*AddNodeResponse_RemoteRds) isAddNodeResponse_Node() {} func (*AddNodeResponse_RemoteAzureDatabase) isAddNodeResponse_Node() {} +func (*AddNodeResponse_RemoteElasticache) isAddNodeResponse_Node() {} + type AddGenericNodeParams struct { state protoimpl.MessageState `protogen:"open.v1"` // Unique across all Nodes user-defined name. @@ -1236,7 +1404,7 @@ type AddGenericNodeParams struct { func (x *AddGenericNodeParams) Reset() { *x = AddGenericNodeParams{} - mi := &file_inventory_v1_nodes_proto_msgTypes[11] + mi := &file_inventory_v1_nodes_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1248,7 +1416,7 @@ func (x *AddGenericNodeParams) String() string { func (*AddGenericNodeParams) ProtoMessage() {} func (x *AddGenericNodeParams) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[11] + mi := &file_inventory_v1_nodes_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1261,7 +1429,7 @@ func (x *AddGenericNodeParams) ProtoReflect() protoreflect.Message { // Deprecated: Use AddGenericNodeParams.ProtoReflect.Descriptor instead. func (*AddGenericNodeParams) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{11} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{12} } func (x *AddGenericNodeParams) GetNodeName() string { @@ -1346,7 +1514,7 @@ type AddContainerNodeParams struct { func (x *AddContainerNodeParams) Reset() { *x = AddContainerNodeParams{} - mi := &file_inventory_v1_nodes_proto_msgTypes[12] + mi := &file_inventory_v1_nodes_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1358,7 +1526,7 @@ func (x *AddContainerNodeParams) String() string { func (*AddContainerNodeParams) ProtoMessage() {} func (x *AddContainerNodeParams) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[12] + mi := &file_inventory_v1_nodes_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1371,7 +1539,7 @@ func (x *AddContainerNodeParams) ProtoReflect() protoreflect.Message { // Deprecated: Use AddContainerNodeParams.ProtoReflect.Descriptor instead. func (*AddContainerNodeParams) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{12} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{13} } func (x *AddContainerNodeParams) GetNodeName() string { @@ -1457,7 +1625,7 @@ type AddRemoteNodeParams struct { func (x *AddRemoteNodeParams) Reset() { *x = AddRemoteNodeParams{} - mi := &file_inventory_v1_nodes_proto_msgTypes[13] + mi := &file_inventory_v1_nodes_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1469,7 +1637,7 @@ func (x *AddRemoteNodeParams) String() string { func (*AddRemoteNodeParams) ProtoMessage() {} func (x *AddRemoteNodeParams) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[13] + mi := &file_inventory_v1_nodes_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1482,7 +1650,7 @@ func (x *AddRemoteNodeParams) ProtoReflect() protoreflect.Message { // Deprecated: Use AddRemoteNodeParams.ProtoReflect.Descriptor instead. func (*AddRemoteNodeParams) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{13} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{14} } func (x *AddRemoteNodeParams) GetNodeName() string { @@ -1547,7 +1715,7 @@ type AddRemoteRDSNodeParams struct { func (x *AddRemoteRDSNodeParams) Reset() { *x = AddRemoteRDSNodeParams{} - mi := &file_inventory_v1_nodes_proto_msgTypes[14] + mi := &file_inventory_v1_nodes_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1559,7 +1727,7 @@ func (x *AddRemoteRDSNodeParams) String() string { func (*AddRemoteRDSNodeParams) ProtoMessage() {} func (x *AddRemoteRDSNodeParams) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[14] + mi := &file_inventory_v1_nodes_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1572,7 +1740,7 @@ func (x *AddRemoteRDSNodeParams) ProtoReflect() protoreflect.Message { // Deprecated: Use AddRemoteRDSNodeParams.ProtoReflect.Descriptor instead. func (*AddRemoteRDSNodeParams) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{14} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{15} } func (x *AddRemoteRDSNodeParams) GetNodeName() string { @@ -1637,7 +1805,7 @@ type AddRemoteAzureNodeParams struct { func (x *AddRemoteAzureNodeParams) Reset() { *x = AddRemoteAzureNodeParams{} - mi := &file_inventory_v1_nodes_proto_msgTypes[15] + mi := &file_inventory_v1_nodes_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1649,7 +1817,7 @@ func (x *AddRemoteAzureNodeParams) String() string { func (*AddRemoteAzureNodeParams) ProtoMessage() {} func (x *AddRemoteAzureNodeParams) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[15] + mi := &file_inventory_v1_nodes_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1662,7 +1830,7 @@ func (x *AddRemoteAzureNodeParams) ProtoReflect() protoreflect.Message { // Deprecated: Use AddRemoteAzureNodeParams.ProtoReflect.Descriptor instead. func (*AddRemoteAzureNodeParams) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{15} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{16} } func (x *AddRemoteAzureNodeParams) GetNodeName() string { @@ -1707,6 +1875,105 @@ func (x *AddRemoteAzureNodeParams) GetCustomLabels() map[string]string { return nil } +type AddRemoteElastiCacheNodeParams struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Unique across all Nodes user-defined name. + NodeName string `protobuf:"bytes,1,opt,name=node_name,json=nodeName,proto3" json:"node_name,omitempty"` + // ElastiCache primary endpoint address. + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + // Node model (cache node type). + NodeModel string `protobuf:"bytes,3,opt,name=node_model,json=nodeModel,proto3" json:"node_model,omitempty"` + // Node region. + Region string `protobuf:"bytes,4,opt,name=region,proto3" json:"region,omitempty"` + // Node availability zone. + Az string `protobuf:"bytes,5,opt,name=az,proto3" json:"az,omitempty"` + // Custom user-assigned labels. + CustomLabels map[string]string `protobuf:"bytes,6,rep,name=custom_labels,json=customLabels,proto3" json:"custom_labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // AWS instance ID (replication group ID). + InstanceId string `protobuf:"bytes,7,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddRemoteElastiCacheNodeParams) Reset() { + *x = AddRemoteElastiCacheNodeParams{} + mi := &file_inventory_v1_nodes_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddRemoteElastiCacheNodeParams) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddRemoteElastiCacheNodeParams) ProtoMessage() {} + +func (x *AddRemoteElastiCacheNodeParams) ProtoReflect() protoreflect.Message { + mi := &file_inventory_v1_nodes_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddRemoteElastiCacheNodeParams.ProtoReflect.Descriptor instead. +func (*AddRemoteElastiCacheNodeParams) Descriptor() ([]byte, []int) { + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{17} +} + +func (x *AddRemoteElastiCacheNodeParams) GetNodeName() string { + if x != nil { + return x.NodeName + } + return "" +} + +func (x *AddRemoteElastiCacheNodeParams) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *AddRemoteElastiCacheNodeParams) GetNodeModel() string { + if x != nil { + return x.NodeModel + } + return "" +} + +func (x *AddRemoteElastiCacheNodeParams) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *AddRemoteElastiCacheNodeParams) GetAz() string { + if x != nil { + return x.Az + } + return "" +} + +func (x *AddRemoteElastiCacheNodeParams) GetCustomLabels() map[string]string { + if x != nil { + return x.CustomLabels + } + return nil +} + +func (x *AddRemoteElastiCacheNodeParams) GetInstanceId() string { + if x != nil { + return x.InstanceId + } + return "" +} + type RemoveNodeRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Unique randomly generated instance identifier. @@ -1719,7 +1986,7 @@ type RemoveNodeRequest struct { func (x *RemoveNodeRequest) Reset() { *x = RemoveNodeRequest{} - mi := &file_inventory_v1_nodes_proto_msgTypes[16] + mi := &file_inventory_v1_nodes_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1731,7 +1998,7 @@ func (x *RemoveNodeRequest) String() string { func (*RemoveNodeRequest) ProtoMessage() {} func (x *RemoveNodeRequest) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[16] + mi := &file_inventory_v1_nodes_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1744,7 +2011,7 @@ func (x *RemoveNodeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveNodeRequest.ProtoReflect.Descriptor instead. func (*RemoveNodeRequest) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{16} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{18} } func (x *RemoveNodeRequest) GetNodeId() string { @@ -1769,7 +2036,7 @@ type RemoveNodeResponse struct { func (x *RemoveNodeResponse) Reset() { *x = RemoveNodeResponse{} - mi := &file_inventory_v1_nodes_proto_msgTypes[17] + mi := &file_inventory_v1_nodes_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1781,7 +2048,7 @@ func (x *RemoveNodeResponse) String() string { func (*RemoveNodeResponse) ProtoMessage() {} func (x *RemoveNodeResponse) ProtoReflect() protoreflect.Message { - mi := &file_inventory_v1_nodes_proto_msgTypes[17] + mi := &file_inventory_v1_nodes_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1794,7 +2061,7 @@ func (x *RemoveNodeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveNodeResponse.ProtoReflect.Descriptor instead. func (*RemoveNodeResponse) Descriptor() ([]byte, []int) { - return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{17} + return file_inventory_v1_nodes_proto_rawDescGZIP(), []int{19} } var File_inventory_v1_nodes_proto protoreflect.FileDescriptor @@ -1875,41 +2142,59 @@ const file_inventory_v1_nodes_proto_rawDesc = "" + "\rcustom_labels\x18\a \x03(\v27.inventory.v1.RemoteAzureDatabaseNode.CustomLabelsEntryR\fcustomLabels\x1a?\n" + "\x11CustomLabelsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xec\x02\n" + + "\x15RemoteElastiCacheNode\x12\x17\n" + + "\anode_id\x18\x01 \x01(\tR\x06nodeId\x12\x1b\n" + + "\tnode_name\x18\x02 \x01(\tR\bnodeName\x12\x18\n" + + "\aaddress\x18\x03 \x01(\tR\aaddress\x12\x1d\n" + + "\n" + + "node_model\x18\x04 \x01(\tR\tnodeModel\x12\x16\n" + + "\x06region\x18\x05 \x01(\tR\x06region\x12\x0e\n" + + "\x02az\x18\x06 \x01(\tR\x02az\x12Z\n" + + "\rcustom_labels\x18\a \x03(\v25.inventory.v1.RemoteElastiCacheNode.CustomLabelsEntryR\fcustomLabels\x12\x1f\n" + + "\vinstance_id\x18\b \x01(\tR\n" + + "instanceId\x1a?\n" + + "\x11CustomLabelsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"G\n" + "\x10ListNodesRequest\x123\n" + - "\tnode_type\x18\x01 \x01(\x0e2\x16.inventory.v1.NodeTypeR\bnodeType\"\xcc\x02\n" + + "\tnode_type\x18\x01 \x01(\x0e2\x16.inventory.v1.NodeTypeR\bnodeType\"\xa0\x03\n" + "\x11ListNodesResponse\x123\n" + "\ageneric\x18\x01 \x03(\v2\x19.inventory.v1.GenericNodeR\ageneric\x129\n" + "\tcontainer\x18\x02 \x03(\v2\x1b.inventory.v1.ContainerNodeR\tcontainer\x120\n" + "\x06remote\x18\x03 \x03(\v2\x18.inventory.v1.RemoteNodeR\x06remote\x12:\n" + "\n" + "remote_rds\x18\x04 \x03(\v2\x1b.inventory.v1.RemoteRDSNodeR\tremoteRds\x12Y\n" + - "\x15remote_azure_database\x18\x05 \x03(\v2%.inventory.v1.RemoteAzureDatabaseNodeR\x13remoteAzureDatabase\"2\n" + + "\x15remote_azure_database\x18\x05 \x03(\v2%.inventory.v1.RemoteAzureDatabaseNodeR\x13remoteAzureDatabase\x12R\n" + + "\x12remote_elasticache\x18\x06 \x03(\v2#.inventory.v1.RemoteElastiCacheNodeR\x11remoteElasticache\"2\n" + "\x0eGetNodeRequest\x12 \n" + - "\anode_id\x18\x01 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\x06nodeId\"\xdc\x02\n" + + "\anode_id\x18\x01 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\x06nodeId\"\xb2\x03\n" + "\x0fGetNodeResponse\x125\n" + "\ageneric\x18\x01 \x01(\v2\x19.inventory.v1.GenericNodeH\x00R\ageneric\x12;\n" + "\tcontainer\x18\x02 \x01(\v2\x1b.inventory.v1.ContainerNodeH\x00R\tcontainer\x122\n" + "\x06remote\x18\x03 \x01(\v2\x18.inventory.v1.RemoteNodeH\x00R\x06remote\x12<\n" + "\n" + "remote_rds\x18\x04 \x01(\v2\x1b.inventory.v1.RemoteRDSNodeH\x00R\tremoteRds\x12[\n" + - "\x15remote_azure_database\x18\x05 \x01(\v2%.inventory.v1.RemoteAzureDatabaseNodeH\x00R\x13remoteAzureDatabaseB\x06\n" + - "\x04node\"\xef\x02\n" + + "\x15remote_azure_database\x18\x05 \x01(\v2%.inventory.v1.RemoteAzureDatabaseNodeH\x00R\x13remoteAzureDatabase\x12T\n" + + "\x12remote_elasticache\x18\x06 \x01(\v2#.inventory.v1.RemoteElastiCacheNodeH\x00R\x11remoteElasticacheB\x06\n" + + "\x04node\"\xce\x03\n" + "\x0eAddNodeRequest\x12>\n" + "\ageneric\x18\x01 \x01(\v2\".inventory.v1.AddGenericNodeParamsH\x00R\ageneric\x12D\n" + "\tcontainer\x18\x02 \x01(\v2$.inventory.v1.AddContainerNodeParamsH\x00R\tcontainer\x12;\n" + "\x06remote\x18\x03 \x01(\v2!.inventory.v1.AddRemoteNodeParamsH\x00R\x06remote\x12E\n" + "\n" + "remote_rds\x18\x04 \x01(\v2$.inventory.v1.AddRemoteRDSNodeParamsH\x00R\tremoteRds\x12K\n" + - "\fremote_azure\x18\x05 \x01(\v2&.inventory.v1.AddRemoteAzureNodeParamsH\x00R\vremoteAzureB\x06\n" + - "\x04node\"\xdc\x02\n" + + "\fremote_azure\x18\x05 \x01(\v2&.inventory.v1.AddRemoteAzureNodeParamsH\x00R\vremoteAzure\x12]\n" + + "\x12remote_elasticache\x18\x06 \x01(\v2,.inventory.v1.AddRemoteElastiCacheNodeParamsH\x00R\x11remoteElasticacheB\x06\n" + + "\x04node\"\xb2\x03\n" + "\x0fAddNodeResponse\x125\n" + "\ageneric\x18\x01 \x01(\v2\x19.inventory.v1.GenericNodeH\x00R\ageneric\x12;\n" + "\tcontainer\x18\x02 \x01(\v2\x1b.inventory.v1.ContainerNodeH\x00R\tcontainer\x122\n" + "\x06remote\x18\x03 \x01(\v2\x18.inventory.v1.RemoteNodeH\x00R\x06remote\x12<\n" + "\n" + "remote_rds\x18\x04 \x01(\v2\x1b.inventory.v1.RemoteRDSNodeH\x00R\tremoteRds\x12[\n" + - "\x15remote_azure_database\x18\x05 \x01(\v2%.inventory.v1.RemoteAzureDatabaseNodeH\x00R\x13remoteAzureDatabaseB\x06\n" + + "\x15remote_azure_database\x18\x05 \x01(\v2%.inventory.v1.RemoteAzureDatabaseNodeH\x00R\x13remoteAzureDatabase\x12T\n" + + "\x12remote_elasticache\x18\x06 \x01(\v2#.inventory.v1.RemoteElastiCacheNodeH\x00R\x11remoteElasticacheB\x06\n" + "\x04node\"\xf9\x02\n" + "\x14AddGenericNodeParams\x12$\n" + "\tnode_name\x18\x01 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\bnodeName\x12!\n" + @@ -1972,18 +2257,32 @@ const file_inventory_v1_nodes_proto_rawDesc = "" + "\rcustom_labels\x18\x06 \x03(\v28.inventory.v1.AddRemoteAzureNodeParams.CustomLabelsEntryR\fcustomLabels\x1a?\n" + "\x11CustomLabelsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\x80\x03\n" + + "\x1eAddRemoteElastiCacheNodeParams\x12$\n" + + "\tnode_name\x18\x01 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\bnodeName\x12!\n" + + "\aaddress\x18\x02 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\aaddress\x12\x1d\n" + + "\n" + + "node_model\x18\x03 \x01(\tR\tnodeModel\x12\x1f\n" + + "\x06region\x18\x04 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\x06region\x12\x0e\n" + + "\x02az\x18\x05 \x01(\tR\x02az\x12c\n" + + "\rcustom_labels\x18\x06 \x03(\v2>.inventory.v1.AddRemoteElastiCacheNodeParams.CustomLabelsEntryR\fcustomLabels\x12\x1f\n" + + "\vinstance_id\x18\a \x01(\tR\n" + + "instanceId\x1a?\n" + + "\x11CustomLabelsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"K\n" + "\x11RemoveNodeRequest\x12 \n" + "\anode_id\x18\x01 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\x06nodeId\x12\x14\n" + "\x05force\x18\x02 \x01(\bR\x05force\"\x14\n" + - "\x12RemoveNodeResponse*\xc3\x01\n" + + "\x12RemoveNodeResponse*\xea\x01\n" + "\bNodeType\x12\x19\n" + "\x15NODE_TYPE_UNSPECIFIED\x10\x00\x12\x1a\n" + "\x16NODE_TYPE_GENERIC_NODE\x10\x01\x12\x1c\n" + "\x18NODE_TYPE_CONTAINER_NODE\x10\x02\x12\x19\n" + "\x15NODE_TYPE_REMOTE_NODE\x10\x03\x12\x1d\n" + "\x19NODE_TYPE_REMOTE_RDS_NODE\x10\x04\x12(\n" + - "$NODE_TYPE_REMOTE_AZURE_DATABASE_NODE\x10\x052\xe6\x04\n" + + "$NODE_TYPE_REMOTE_AZURE_DATABASE_NODE\x10\x05\x12%\n" + + "!NODE_TYPE_REMOTE_ELASTICACHE_NODE\x10\x062\xe6\x04\n" + "\fNodesService\x12\x96\x01\n" + "\tListNodes\x12\x1e.inventory.v1.ListNodesRequest\x1a\x1f.inventory.v1.ListNodesResponse\"H\x92A*\x12\n" + "List Nodes\x1a\x1cReturns a list of all Nodes.\x82\xd3\xe4\x93\x02\x15\x12\x13/v1/inventory/nodes\x12\x9a\x01\n" + @@ -2010,85 +2309,95 @@ func file_inventory_v1_nodes_proto_rawDescGZIP() []byte { var ( file_inventory_v1_nodes_proto_enumTypes = make([]protoimpl.EnumInfo, 1) - file_inventory_v1_nodes_proto_msgTypes = make([]protoimpl.MessageInfo, 28) + file_inventory_v1_nodes_proto_msgTypes = make([]protoimpl.MessageInfo, 32) file_inventory_v1_nodes_proto_goTypes = []any{ - NodeType(0), // 0: inventory.v1.NodeType - (*GenericNode)(nil), // 1: inventory.v1.GenericNode - (*ContainerNode)(nil), // 2: inventory.v1.ContainerNode - (*RemoteNode)(nil), // 3: inventory.v1.RemoteNode - (*RemoteRDSNode)(nil), // 4: inventory.v1.RemoteRDSNode - (*RemoteAzureDatabaseNode)(nil), // 5: inventory.v1.RemoteAzureDatabaseNode - (*ListNodesRequest)(nil), // 6: inventory.v1.ListNodesRequest - (*ListNodesResponse)(nil), // 7: inventory.v1.ListNodesResponse - (*GetNodeRequest)(nil), // 8: inventory.v1.GetNodeRequest - (*GetNodeResponse)(nil), // 9: inventory.v1.GetNodeResponse - (*AddNodeRequest)(nil), // 10: inventory.v1.AddNodeRequest - (*AddNodeResponse)(nil), // 11: inventory.v1.AddNodeResponse - (*AddGenericNodeParams)(nil), // 12: inventory.v1.AddGenericNodeParams - (*AddContainerNodeParams)(nil), // 13: inventory.v1.AddContainerNodeParams - (*AddRemoteNodeParams)(nil), // 14: inventory.v1.AddRemoteNodeParams - (*AddRemoteRDSNodeParams)(nil), // 15: inventory.v1.AddRemoteRDSNodeParams - (*AddRemoteAzureNodeParams)(nil), // 16: inventory.v1.AddRemoteAzureNodeParams - (*RemoveNodeRequest)(nil), // 17: inventory.v1.RemoveNodeRequest - (*RemoveNodeResponse)(nil), // 18: inventory.v1.RemoveNodeResponse - nil, // 19: inventory.v1.GenericNode.CustomLabelsEntry - nil, // 20: inventory.v1.ContainerNode.CustomLabelsEntry - nil, // 21: inventory.v1.RemoteNode.CustomLabelsEntry - nil, // 22: inventory.v1.RemoteRDSNode.CustomLabelsEntry - nil, // 23: inventory.v1.RemoteAzureDatabaseNode.CustomLabelsEntry - nil, // 24: inventory.v1.AddGenericNodeParams.CustomLabelsEntry - nil, // 25: inventory.v1.AddContainerNodeParams.CustomLabelsEntry - nil, // 26: inventory.v1.AddRemoteNodeParams.CustomLabelsEntry - nil, // 27: inventory.v1.AddRemoteRDSNodeParams.CustomLabelsEntry - nil, // 28: inventory.v1.AddRemoteAzureNodeParams.CustomLabelsEntry + NodeType(0), // 0: inventory.v1.NodeType + (*GenericNode)(nil), // 1: inventory.v1.GenericNode + (*ContainerNode)(nil), // 2: inventory.v1.ContainerNode + (*RemoteNode)(nil), // 3: inventory.v1.RemoteNode + (*RemoteRDSNode)(nil), // 4: inventory.v1.RemoteRDSNode + (*RemoteAzureDatabaseNode)(nil), // 5: inventory.v1.RemoteAzureDatabaseNode + (*RemoteElastiCacheNode)(nil), // 6: inventory.v1.RemoteElastiCacheNode + (*ListNodesRequest)(nil), // 7: inventory.v1.ListNodesRequest + (*ListNodesResponse)(nil), // 8: inventory.v1.ListNodesResponse + (*GetNodeRequest)(nil), // 9: inventory.v1.GetNodeRequest + (*GetNodeResponse)(nil), // 10: inventory.v1.GetNodeResponse + (*AddNodeRequest)(nil), // 11: inventory.v1.AddNodeRequest + (*AddNodeResponse)(nil), // 12: inventory.v1.AddNodeResponse + (*AddGenericNodeParams)(nil), // 13: inventory.v1.AddGenericNodeParams + (*AddContainerNodeParams)(nil), // 14: inventory.v1.AddContainerNodeParams + (*AddRemoteNodeParams)(nil), // 15: inventory.v1.AddRemoteNodeParams + (*AddRemoteRDSNodeParams)(nil), // 16: inventory.v1.AddRemoteRDSNodeParams + (*AddRemoteAzureNodeParams)(nil), // 17: inventory.v1.AddRemoteAzureNodeParams + (*AddRemoteElastiCacheNodeParams)(nil), // 18: inventory.v1.AddRemoteElastiCacheNodeParams + (*RemoveNodeRequest)(nil), // 19: inventory.v1.RemoveNodeRequest + (*RemoveNodeResponse)(nil), // 20: inventory.v1.RemoveNodeResponse + nil, // 21: inventory.v1.GenericNode.CustomLabelsEntry + nil, // 22: inventory.v1.ContainerNode.CustomLabelsEntry + nil, // 23: inventory.v1.RemoteNode.CustomLabelsEntry + nil, // 24: inventory.v1.RemoteRDSNode.CustomLabelsEntry + nil, // 25: inventory.v1.RemoteAzureDatabaseNode.CustomLabelsEntry + nil, // 26: inventory.v1.RemoteElastiCacheNode.CustomLabelsEntry + nil, // 27: inventory.v1.AddGenericNodeParams.CustomLabelsEntry + nil, // 28: inventory.v1.AddContainerNodeParams.CustomLabelsEntry + nil, // 29: inventory.v1.AddRemoteNodeParams.CustomLabelsEntry + nil, // 30: inventory.v1.AddRemoteRDSNodeParams.CustomLabelsEntry + nil, // 31: inventory.v1.AddRemoteAzureNodeParams.CustomLabelsEntry + nil, // 32: inventory.v1.AddRemoteElastiCacheNodeParams.CustomLabelsEntry } ) var file_inventory_v1_nodes_proto_depIdxs = []int32{ - 19, // 0: inventory.v1.GenericNode.custom_labels:type_name -> inventory.v1.GenericNode.CustomLabelsEntry - 20, // 1: inventory.v1.ContainerNode.custom_labels:type_name -> inventory.v1.ContainerNode.CustomLabelsEntry - 21, // 2: inventory.v1.RemoteNode.custom_labels:type_name -> inventory.v1.RemoteNode.CustomLabelsEntry - 22, // 3: inventory.v1.RemoteRDSNode.custom_labels:type_name -> inventory.v1.RemoteRDSNode.CustomLabelsEntry - 23, // 4: inventory.v1.RemoteAzureDatabaseNode.custom_labels:type_name -> inventory.v1.RemoteAzureDatabaseNode.CustomLabelsEntry - 0, // 5: inventory.v1.ListNodesRequest.node_type:type_name -> inventory.v1.NodeType - 1, // 6: inventory.v1.ListNodesResponse.generic:type_name -> inventory.v1.GenericNode - 2, // 7: inventory.v1.ListNodesResponse.container:type_name -> inventory.v1.ContainerNode - 3, // 8: inventory.v1.ListNodesResponse.remote:type_name -> inventory.v1.RemoteNode - 4, // 9: inventory.v1.ListNodesResponse.remote_rds:type_name -> inventory.v1.RemoteRDSNode - 5, // 10: inventory.v1.ListNodesResponse.remote_azure_database:type_name -> inventory.v1.RemoteAzureDatabaseNode - 1, // 11: inventory.v1.GetNodeResponse.generic:type_name -> inventory.v1.GenericNode - 2, // 12: inventory.v1.GetNodeResponse.container:type_name -> inventory.v1.ContainerNode - 3, // 13: inventory.v1.GetNodeResponse.remote:type_name -> inventory.v1.RemoteNode - 4, // 14: inventory.v1.GetNodeResponse.remote_rds:type_name -> inventory.v1.RemoteRDSNode - 5, // 15: inventory.v1.GetNodeResponse.remote_azure_database:type_name -> inventory.v1.RemoteAzureDatabaseNode - 12, // 16: inventory.v1.AddNodeRequest.generic:type_name -> inventory.v1.AddGenericNodeParams - 13, // 17: inventory.v1.AddNodeRequest.container:type_name -> inventory.v1.AddContainerNodeParams - 14, // 18: inventory.v1.AddNodeRequest.remote:type_name -> inventory.v1.AddRemoteNodeParams - 15, // 19: inventory.v1.AddNodeRequest.remote_rds:type_name -> inventory.v1.AddRemoteRDSNodeParams - 16, // 20: inventory.v1.AddNodeRequest.remote_azure:type_name -> inventory.v1.AddRemoteAzureNodeParams - 1, // 21: inventory.v1.AddNodeResponse.generic:type_name -> inventory.v1.GenericNode - 2, // 22: inventory.v1.AddNodeResponse.container:type_name -> inventory.v1.ContainerNode - 3, // 23: inventory.v1.AddNodeResponse.remote:type_name -> inventory.v1.RemoteNode - 4, // 24: inventory.v1.AddNodeResponse.remote_rds:type_name -> inventory.v1.RemoteRDSNode - 5, // 25: inventory.v1.AddNodeResponse.remote_azure_database:type_name -> inventory.v1.RemoteAzureDatabaseNode - 24, // 26: inventory.v1.AddGenericNodeParams.custom_labels:type_name -> inventory.v1.AddGenericNodeParams.CustomLabelsEntry - 25, // 27: inventory.v1.AddContainerNodeParams.custom_labels:type_name -> inventory.v1.AddContainerNodeParams.CustomLabelsEntry - 26, // 28: inventory.v1.AddRemoteNodeParams.custom_labels:type_name -> inventory.v1.AddRemoteNodeParams.CustomLabelsEntry - 27, // 29: inventory.v1.AddRemoteRDSNodeParams.custom_labels:type_name -> inventory.v1.AddRemoteRDSNodeParams.CustomLabelsEntry - 28, // 30: inventory.v1.AddRemoteAzureNodeParams.custom_labels:type_name -> inventory.v1.AddRemoteAzureNodeParams.CustomLabelsEntry - 6, // 31: inventory.v1.NodesService.ListNodes:input_type -> inventory.v1.ListNodesRequest - 8, // 32: inventory.v1.NodesService.GetNode:input_type -> inventory.v1.GetNodeRequest - 10, // 33: inventory.v1.NodesService.AddNode:input_type -> inventory.v1.AddNodeRequest - 17, // 34: inventory.v1.NodesService.RemoveNode:input_type -> inventory.v1.RemoveNodeRequest - 7, // 35: inventory.v1.NodesService.ListNodes:output_type -> inventory.v1.ListNodesResponse - 9, // 36: inventory.v1.NodesService.GetNode:output_type -> inventory.v1.GetNodeResponse - 11, // 37: inventory.v1.NodesService.AddNode:output_type -> inventory.v1.AddNodeResponse - 18, // 38: inventory.v1.NodesService.RemoveNode:output_type -> inventory.v1.RemoveNodeResponse - 35, // [35:39] is the sub-list for method output_type - 31, // [31:35] is the sub-list for method input_type - 31, // [31:31] is the sub-list for extension type_name - 31, // [31:31] is the sub-list for extension extendee - 0, // [0:31] is the sub-list for field type_name + 21, // 0: inventory.v1.GenericNode.custom_labels:type_name -> inventory.v1.GenericNode.CustomLabelsEntry + 22, // 1: inventory.v1.ContainerNode.custom_labels:type_name -> inventory.v1.ContainerNode.CustomLabelsEntry + 23, // 2: inventory.v1.RemoteNode.custom_labels:type_name -> inventory.v1.RemoteNode.CustomLabelsEntry + 24, // 3: inventory.v1.RemoteRDSNode.custom_labels:type_name -> inventory.v1.RemoteRDSNode.CustomLabelsEntry + 25, // 4: inventory.v1.RemoteAzureDatabaseNode.custom_labels:type_name -> inventory.v1.RemoteAzureDatabaseNode.CustomLabelsEntry + 26, // 5: inventory.v1.RemoteElastiCacheNode.custom_labels:type_name -> inventory.v1.RemoteElastiCacheNode.CustomLabelsEntry + 0, // 6: inventory.v1.ListNodesRequest.node_type:type_name -> inventory.v1.NodeType + 1, // 7: inventory.v1.ListNodesResponse.generic:type_name -> inventory.v1.GenericNode + 2, // 8: inventory.v1.ListNodesResponse.container:type_name -> inventory.v1.ContainerNode + 3, // 9: inventory.v1.ListNodesResponse.remote:type_name -> inventory.v1.RemoteNode + 4, // 10: inventory.v1.ListNodesResponse.remote_rds:type_name -> inventory.v1.RemoteRDSNode + 5, // 11: inventory.v1.ListNodesResponse.remote_azure_database:type_name -> inventory.v1.RemoteAzureDatabaseNode + 6, // 12: inventory.v1.ListNodesResponse.remote_elasticache:type_name -> inventory.v1.RemoteElastiCacheNode + 1, // 13: inventory.v1.GetNodeResponse.generic:type_name -> inventory.v1.GenericNode + 2, // 14: inventory.v1.GetNodeResponse.container:type_name -> inventory.v1.ContainerNode + 3, // 15: inventory.v1.GetNodeResponse.remote:type_name -> inventory.v1.RemoteNode + 4, // 16: inventory.v1.GetNodeResponse.remote_rds:type_name -> inventory.v1.RemoteRDSNode + 5, // 17: inventory.v1.GetNodeResponse.remote_azure_database:type_name -> inventory.v1.RemoteAzureDatabaseNode + 6, // 18: inventory.v1.GetNodeResponse.remote_elasticache:type_name -> inventory.v1.RemoteElastiCacheNode + 13, // 19: inventory.v1.AddNodeRequest.generic:type_name -> inventory.v1.AddGenericNodeParams + 14, // 20: inventory.v1.AddNodeRequest.container:type_name -> inventory.v1.AddContainerNodeParams + 15, // 21: inventory.v1.AddNodeRequest.remote:type_name -> inventory.v1.AddRemoteNodeParams + 16, // 22: inventory.v1.AddNodeRequest.remote_rds:type_name -> inventory.v1.AddRemoteRDSNodeParams + 17, // 23: inventory.v1.AddNodeRequest.remote_azure:type_name -> inventory.v1.AddRemoteAzureNodeParams + 18, // 24: inventory.v1.AddNodeRequest.remote_elasticache:type_name -> inventory.v1.AddRemoteElastiCacheNodeParams + 1, // 25: inventory.v1.AddNodeResponse.generic:type_name -> inventory.v1.GenericNode + 2, // 26: inventory.v1.AddNodeResponse.container:type_name -> inventory.v1.ContainerNode + 3, // 27: inventory.v1.AddNodeResponse.remote:type_name -> inventory.v1.RemoteNode + 4, // 28: inventory.v1.AddNodeResponse.remote_rds:type_name -> inventory.v1.RemoteRDSNode + 5, // 29: inventory.v1.AddNodeResponse.remote_azure_database:type_name -> inventory.v1.RemoteAzureDatabaseNode + 6, // 30: inventory.v1.AddNodeResponse.remote_elasticache:type_name -> inventory.v1.RemoteElastiCacheNode + 27, // 31: inventory.v1.AddGenericNodeParams.custom_labels:type_name -> inventory.v1.AddGenericNodeParams.CustomLabelsEntry + 28, // 32: inventory.v1.AddContainerNodeParams.custom_labels:type_name -> inventory.v1.AddContainerNodeParams.CustomLabelsEntry + 29, // 33: inventory.v1.AddRemoteNodeParams.custom_labels:type_name -> inventory.v1.AddRemoteNodeParams.CustomLabelsEntry + 30, // 34: inventory.v1.AddRemoteRDSNodeParams.custom_labels:type_name -> inventory.v1.AddRemoteRDSNodeParams.CustomLabelsEntry + 31, // 35: inventory.v1.AddRemoteAzureNodeParams.custom_labels:type_name -> inventory.v1.AddRemoteAzureNodeParams.CustomLabelsEntry + 32, // 36: inventory.v1.AddRemoteElastiCacheNodeParams.custom_labels:type_name -> inventory.v1.AddRemoteElastiCacheNodeParams.CustomLabelsEntry + 7, // 37: inventory.v1.NodesService.ListNodes:input_type -> inventory.v1.ListNodesRequest + 9, // 38: inventory.v1.NodesService.GetNode:input_type -> inventory.v1.GetNodeRequest + 11, // 39: inventory.v1.NodesService.AddNode:input_type -> inventory.v1.AddNodeRequest + 19, // 40: inventory.v1.NodesService.RemoveNode:input_type -> inventory.v1.RemoveNodeRequest + 8, // 41: inventory.v1.NodesService.ListNodes:output_type -> inventory.v1.ListNodesResponse + 10, // 42: inventory.v1.NodesService.GetNode:output_type -> inventory.v1.GetNodeResponse + 12, // 43: inventory.v1.NodesService.AddNode:output_type -> inventory.v1.AddNodeResponse + 20, // 44: inventory.v1.NodesService.RemoveNode:output_type -> inventory.v1.RemoveNodeResponse + 41, // [41:45] is the sub-list for method output_type + 37, // [37:41] is the sub-list for method input_type + 37, // [37:37] is the sub-list for extension type_name + 37, // [37:37] is the sub-list for extension extendee + 0, // [0:37] is the sub-list for field type_name } func init() { file_inventory_v1_nodes_proto_init() } @@ -2096,26 +2405,29 @@ func file_inventory_v1_nodes_proto_init() { if File_inventory_v1_nodes_proto != nil { return } - file_inventory_v1_nodes_proto_msgTypes[8].OneofWrappers = []any{ + file_inventory_v1_nodes_proto_msgTypes[9].OneofWrappers = []any{ (*GetNodeResponse_Generic)(nil), (*GetNodeResponse_Container)(nil), (*GetNodeResponse_Remote)(nil), (*GetNodeResponse_RemoteRds)(nil), (*GetNodeResponse_RemoteAzureDatabase)(nil), + (*GetNodeResponse_RemoteElasticache)(nil), } - file_inventory_v1_nodes_proto_msgTypes[9].OneofWrappers = []any{ + file_inventory_v1_nodes_proto_msgTypes[10].OneofWrappers = []any{ (*AddNodeRequest_Generic)(nil), (*AddNodeRequest_Container)(nil), (*AddNodeRequest_Remote)(nil), (*AddNodeRequest_RemoteRds)(nil), (*AddNodeRequest_RemoteAzure)(nil), + (*AddNodeRequest_RemoteElasticache)(nil), } - file_inventory_v1_nodes_proto_msgTypes[10].OneofWrappers = []any{ + file_inventory_v1_nodes_proto_msgTypes[11].OneofWrappers = []any{ (*AddNodeResponse_Generic)(nil), (*AddNodeResponse_Container)(nil), (*AddNodeResponse_Remote)(nil), (*AddNodeResponse_RemoteRds)(nil), (*AddNodeResponse_RemoteAzureDatabase)(nil), + (*AddNodeResponse_RemoteElasticache)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -2123,7 +2435,7 @@ func file_inventory_v1_nodes_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_inventory_v1_nodes_proto_rawDesc), len(file_inventory_v1_nodes_proto_rawDesc)), NumEnums: 1, - NumMessages: 28, + NumMessages: 32, NumExtensions: 0, NumServices: 1, }, diff --git a/api/inventory/v1/nodes.pb.validate.go b/api/inventory/v1/nodes.pb.validate.go index 99d6893a535..e5af4b6592c 100644 --- a/api/inventory/v1/nodes.pb.validate.go +++ b/api/inventory/v1/nodes.pb.validate.go @@ -626,6 +626,125 @@ var _ interface { ErrorName() string } = RemoteAzureDatabaseNodeValidationError{} +// Validate checks the field values on RemoteElastiCacheNode with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *RemoteElastiCacheNode) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on RemoteElastiCacheNode with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// RemoteElastiCacheNodeMultiError, or nil if none found. +func (m *RemoteElastiCacheNode) ValidateAll() error { + return m.validate(true) +} + +func (m *RemoteElastiCacheNode) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for NodeId + + // no validation rules for NodeName + + // no validation rules for Address + + // no validation rules for NodeModel + + // no validation rules for Region + + // no validation rules for Az + + // no validation rules for CustomLabels + + // no validation rules for InstanceId + + if len(errors) > 0 { + return RemoteElastiCacheNodeMultiError(errors) + } + + return nil +} + +// RemoteElastiCacheNodeMultiError is an error wrapping multiple validation +// errors returned by RemoteElastiCacheNode.ValidateAll() if the designated +// constraints aren't met. +type RemoteElastiCacheNodeMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m RemoteElastiCacheNodeMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m RemoteElastiCacheNodeMultiError) AllErrors() []error { return m } + +// RemoteElastiCacheNodeValidationError is the validation error returned by +// RemoteElastiCacheNode.Validate if the designated constraints aren't met. +type RemoteElastiCacheNodeValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e RemoteElastiCacheNodeValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e RemoteElastiCacheNodeValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e RemoteElastiCacheNodeValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e RemoteElastiCacheNodeValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e RemoteElastiCacheNodeValidationError) ErrorName() string { + return "RemoteElastiCacheNodeValidationError" +} + +// Error satisfies the builtin error interface +func (e RemoteElastiCacheNodeValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRemoteElastiCacheNode.%s: %s%s", + key, + e.field, + e.reason, + cause, + ) +} + +var _ error = RemoteElastiCacheNodeValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = RemoteElastiCacheNodeValidationError{} + // Validate checks the field values on ListNodesRequest with the rules defined // in the proto definition for this message. If any rules are violated, the // first error encountered is returned, or nil if there are no violations. @@ -921,6 +1040,40 @@ func (m *ListNodesResponse) validate(all bool) error { } + for idx, item := range m.GetRemoteElasticache() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ListNodesResponseValidationError{ + field: fmt.Sprintf("RemoteElasticache[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ListNodesResponseValidationError{ + field: fmt.Sprintf("RemoteElasticache[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListNodesResponseValidationError{ + field: fmt.Sprintf("RemoteElasticache[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + if len(errors) > 0 { return ListNodesResponseMultiError(errors) } @@ -1342,6 +1495,47 @@ func (m *GetNodeResponse) validate(all bool) error { } } + case *GetNodeResponse_RemoteElasticache: + if v == nil { + err := GetNodeResponseValidationError{ + field: "Node", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetRemoteElasticache()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetNodeResponseValidationError{ + field: "RemoteElasticache", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetNodeResponseValidationError{ + field: "RemoteElasticache", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRemoteElasticache()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetNodeResponseValidationError{ + field: "RemoteElasticache", + reason: "embedded message failed validation", + cause: err, + } + } + } + default: _ = v // ensures v is used } @@ -1653,6 +1847,47 @@ func (m *AddNodeRequest) validate(all bool) error { } } + case *AddNodeRequest_RemoteElasticache: + if v == nil { + err := AddNodeRequestValidationError{ + field: "Node", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetRemoteElasticache()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, AddNodeRequestValidationError{ + field: "RemoteElasticache", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, AddNodeRequestValidationError{ + field: "RemoteElasticache", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRemoteElasticache()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AddNodeRequestValidationError{ + field: "RemoteElasticache", + reason: "embedded message failed validation", + cause: err, + } + } + } + default: _ = v // ensures v is used } @@ -1964,6 +2199,47 @@ func (m *AddNodeResponse) validate(all bool) error { } } + case *AddNodeResponse_RemoteElasticache: + if v == nil { + err := AddNodeResponseValidationError{ + field: "Node", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetRemoteElasticache()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, AddNodeResponseValidationError{ + field: "RemoteElasticache", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, AddNodeResponseValidationError{ + field: "RemoteElasticache", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRemoteElasticache()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AddNodeResponseValidationError{ + field: "RemoteElasticache", + reason: "embedded message failed validation", + cause: err, + } + } + } + default: _ = v // ensures v is used } @@ -2740,6 +3016,151 @@ var _ interface { ErrorName() string } = AddRemoteAzureNodeParamsValidationError{} +// Validate checks the field values on AddRemoteElastiCacheNodeParams with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *AddRemoteElastiCacheNodeParams) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on AddRemoteElastiCacheNodeParams with +// the rules defined in the proto definition for this message. If any rules +// are violated, the result is a list of violation errors wrapped in +// AddRemoteElastiCacheNodeParamsMultiError, or nil if none found. +func (m *AddRemoteElastiCacheNodeParams) ValidateAll() error { + return m.validate(true) +} + +func (m *AddRemoteElastiCacheNodeParams) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if utf8.RuneCountInString(m.GetNodeName()) < 1 { + err := AddRemoteElastiCacheNodeParamsValidationError{ + field: "NodeName", + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } + + if utf8.RuneCountInString(m.GetAddress()) < 1 { + err := AddRemoteElastiCacheNodeParamsValidationError{ + field: "Address", + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } + + // no validation rules for NodeModel + + if utf8.RuneCountInString(m.GetRegion()) < 1 { + err := AddRemoteElastiCacheNodeParamsValidationError{ + field: "Region", + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } + + // no validation rules for Az + + // no validation rules for CustomLabels + + // no validation rules for InstanceId + + if len(errors) > 0 { + return AddRemoteElastiCacheNodeParamsMultiError(errors) + } + + return nil +} + +// AddRemoteElastiCacheNodeParamsMultiError is an error wrapping multiple +// validation errors returned by AddRemoteElastiCacheNodeParams.ValidateAll() +// if the designated constraints aren't met. +type AddRemoteElastiCacheNodeParamsMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m AddRemoteElastiCacheNodeParamsMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m AddRemoteElastiCacheNodeParamsMultiError) AllErrors() []error { return m } + +// AddRemoteElastiCacheNodeParamsValidationError is the validation error +// returned by AddRemoteElastiCacheNodeParams.Validate if the designated +// constraints aren't met. +type AddRemoteElastiCacheNodeParamsValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e AddRemoteElastiCacheNodeParamsValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e AddRemoteElastiCacheNodeParamsValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e AddRemoteElastiCacheNodeParamsValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e AddRemoteElastiCacheNodeParamsValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e AddRemoteElastiCacheNodeParamsValidationError) ErrorName() string { + return "AddRemoteElastiCacheNodeParamsValidationError" +} + +// Error satisfies the builtin error interface +func (e AddRemoteElastiCacheNodeParamsValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAddRemoteElastiCacheNodeParams.%s: %s%s", + key, + e.field, + e.reason, + cause, + ) +} + +var _ error = AddRemoteElastiCacheNodeParamsValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = AddRemoteElastiCacheNodeParamsValidationError{} + // Validate checks the field values on RemoveNodeRequest with the rules defined // in the proto definition for this message. If any rules are violated, the // first error encountered is returned, or nil if there are no violations. diff --git a/api/inventory/v1/nodes.proto b/api/inventory/v1/nodes.proto index 3cead66d61b..de3c5a71939 100644 --- a/api/inventory/v1/nodes.proto +++ b/api/inventory/v1/nodes.proto @@ -14,6 +14,7 @@ enum NodeType { NODE_TYPE_REMOTE_NODE = 3; NODE_TYPE_REMOTE_RDS_NODE = 4; NODE_TYPE_REMOTE_AZURE_DATABASE_NODE = 5; + NODE_TYPE_REMOTE_ELASTICACHE_NODE = 6; } // GenericNode represents a bare metal server or virtual machine. @@ -122,6 +123,26 @@ message RemoteAzureDatabaseNode { map custom_labels = 7; } +// RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes. +message RemoteElastiCacheNode { + // Unique randomly generated instance identifier. + string node_id = 1; + // Unique across all Nodes user-defined name. + string node_name = 2; + // ElastiCache primary endpoint address. + string address = 3; + // Node model (cache node type). + string node_model = 4; + // Node region. + string region = 5; + // Node availability zone. + string az = 6; + // Custom user-assigned labels. + map custom_labels = 7; + // AWS instance ID (replication group ID). + string instance_id = 8; +} + // List message ListNodesRequest { @@ -135,6 +156,7 @@ message ListNodesResponse { repeated RemoteNode remote = 3; repeated RemoteRDSNode remote_rds = 4; repeated RemoteAzureDatabaseNode remote_azure_database = 5; + repeated RemoteElastiCacheNode remote_elasticache = 6; } // Get @@ -151,6 +173,7 @@ message GetNodeResponse { RemoteNode remote = 3; RemoteRDSNode remote_rds = 4; RemoteAzureDatabaseNode remote_azure_database = 5; + RemoteElastiCacheNode remote_elasticache = 6; } } @@ -163,6 +186,7 @@ message AddNodeRequest { AddRemoteNodeParams remote = 3; AddRemoteRDSNodeParams remote_rds = 4; AddRemoteAzureNodeParams remote_azure = 5; + AddRemoteElastiCacheNodeParams remote_elasticache = 6; } } @@ -173,6 +197,7 @@ message AddNodeResponse { RemoteNode remote = 3; RemoteRDSNode remote_rds = 4; RemoteAzureDatabaseNode remote_azure_database = 5; + RemoteElastiCacheNode remote_elasticache = 6; } } @@ -271,6 +296,25 @@ message AddRemoteAzureNodeParams { map custom_labels = 6; } +// Add Remote ElastiCache + +message AddRemoteElastiCacheNodeParams { + // Unique across all Nodes user-defined name. + string node_name = 1 [(validate.rules).string.min_len = 1]; + // ElastiCache primary endpoint address. + string address = 2 [(validate.rules).string.min_len = 1]; + // Node model (cache node type). + string node_model = 3; + // Node region. + string region = 4 [(validate.rules).string.min_len = 1]; + // Node availability zone. + string az = 5; + // Custom user-assigned labels. + map custom_labels = 6; + // AWS instance ID (replication group ID). + string instance_id = 7; +} + // Remove message RemoveNodeRequest { diff --git a/api/inventory/v1/types/node_types.go b/api/inventory/v1/types/node_types.go index b9ff4ef07bf..c258e7a065d 100644 --- a/api/inventory/v1/types/node_types.go +++ b/api/inventory/v1/types/node_types.go @@ -24,6 +24,7 @@ const ( NodeTypeRemoteNode = "NODE_TYPE_REMOTE_NODE" NodeTypeRemoteRDSNode = "NODE_TYPE_REMOTE_RDS_NODE" NodeTypeRemoteAzureDatabaseNode = "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + NodeTypeRemoteElastiCacheNode = "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ) var nodeTypeNames = map[string]string{ @@ -33,6 +34,7 @@ var nodeTypeNames = map[string]string{ NodeTypeRemoteNode: "Remote", NodeTypeRemoteRDSNode: "Remote RDS", NodeTypeRemoteAzureDatabaseNode: "Remote Azure database", + NodeTypeRemoteElastiCacheNode: "Remote ElastiCache", } // NodeTypeName returns human friendly node type to be used in reports. diff --git a/api/management/v1/elasticache.pb.go b/api/management/v1/elasticache.pb.go new file mode 100644 index 00000000000..c6facd91559 --- /dev/null +++ b/api/management/v1/elasticache.pb.go @@ -0,0 +1,722 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: management/v1/elasticache.proto + +package managementv1 + +import ( + reflect "reflect" + sync "sync" + unsafe "unsafe" + + _ "github.com/envoyproxy/protoc-gen-validate/validate" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + + _ "github.com/percona/pmm/api/extensions/v1" + v1 "github.com/percona/pmm/api/inventory/v1" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// DiscoverElastiCacheEngine describes supported ElastiCache engines. +type DiscoverElastiCacheEngine int32 + +const ( + DiscoverElastiCacheEngine_DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED DiscoverElastiCacheEngine = 0 + DiscoverElastiCacheEngine_DISCOVER_ELASTI_CACHE_ENGINE_REDIS DiscoverElastiCacheEngine = 1 + DiscoverElastiCacheEngine_DISCOVER_ELASTI_CACHE_ENGINE_VALKEY DiscoverElastiCacheEngine = 2 +) + +// Enum value maps for DiscoverElastiCacheEngine. +var ( + DiscoverElastiCacheEngine_name = map[int32]string{ + 0: "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + 1: "DISCOVER_ELASTI_CACHE_ENGINE_REDIS", + 2: "DISCOVER_ELASTI_CACHE_ENGINE_VALKEY", + } + DiscoverElastiCacheEngine_value = map[string]int32{ + "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED": 0, + "DISCOVER_ELASTI_CACHE_ENGINE_REDIS": 1, + "DISCOVER_ELASTI_CACHE_ENGINE_VALKEY": 2, + } +) + +func (x DiscoverElastiCacheEngine) Enum() *DiscoverElastiCacheEngine { + p := new(DiscoverElastiCacheEngine) + *p = x + return p +} + +func (x DiscoverElastiCacheEngine) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DiscoverElastiCacheEngine) Descriptor() protoreflect.EnumDescriptor { + return file_management_v1_elasticache_proto_enumTypes[0].Descriptor() +} + +func (DiscoverElastiCacheEngine) Type() protoreflect.EnumType { + return &file_management_v1_elasticache_proto_enumTypes[0] +} + +func (x DiscoverElastiCacheEngine) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DiscoverElastiCacheEngine.Descriptor instead. +func (DiscoverElastiCacheEngine) EnumDescriptor() ([]byte, []int) { + return file_management_v1_elasticache_proto_rawDescGZIP(), []int{0} +} + +// DiscoverElastiCacheInstance models an ElastiCache replication group discovered by the API. +type DiscoverElastiCacheInstance struct { + state protoimpl.MessageState `protogen:"open.v1"` + // AWS region. + Region string `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` + // AWS availability zone. + Az string `protobuf:"bytes,2,opt,name=az,proto3" json:"az,omitempty"` + // Replication group identifier. + InstanceId string `protobuf:"bytes,3,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` + // Cache node type (e.g. cache.r7g.large). + NodeModel string `protobuf:"bytes,4,opt,name=node_model,json=nodeModel,proto3" json:"node_model,omitempty"` + // Primary endpoint address. + Address string `protobuf:"bytes,5,opt,name=address,proto3" json:"address,omitempty"` + // Primary endpoint port. + Port uint32 `protobuf:"varint,6,opt,name=port,proto3" json:"port,omitempty"` + // Engine type (redis or valkey). + Engine DiscoverElastiCacheEngine `protobuf:"varint,7,opt,name=engine,proto3,enum=management.v1.DiscoverElastiCacheEngine" json:"engine,omitempty"` + // Engine version. + EngineVersion string `protobuf:"bytes,8,opt,name=engine_version,json=engineVersion,proto3" json:"engine_version,omitempty"` + // Whether in-transit encryption is enabled. + TransitEncryptionEnabled bool `protobuf:"varint,9,opt,name=transit_encryption_enabled,json=transitEncryptionEnabled,proto3" json:"transit_encryption_enabled,omitempty"` + // Cluster name (replication group ID). + Cluster string `protobuf:"bytes,10,opt,name=cluster,proto3" json:"cluster,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DiscoverElastiCacheInstance) Reset() { + *x = DiscoverElastiCacheInstance{} + mi := &file_management_v1_elasticache_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DiscoverElastiCacheInstance) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DiscoverElastiCacheInstance) ProtoMessage() {} + +func (x *DiscoverElastiCacheInstance) ProtoReflect() protoreflect.Message { + mi := &file_management_v1_elasticache_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DiscoverElastiCacheInstance.ProtoReflect.Descriptor instead. +func (*DiscoverElastiCacheInstance) Descriptor() ([]byte, []int) { + return file_management_v1_elasticache_proto_rawDescGZIP(), []int{0} +} + +func (x *DiscoverElastiCacheInstance) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *DiscoverElastiCacheInstance) GetAz() string { + if x != nil { + return x.Az + } + return "" +} + +func (x *DiscoverElastiCacheInstance) GetInstanceId() string { + if x != nil { + return x.InstanceId + } + return "" +} + +func (x *DiscoverElastiCacheInstance) GetNodeModel() string { + if x != nil { + return x.NodeModel + } + return "" +} + +func (x *DiscoverElastiCacheInstance) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *DiscoverElastiCacheInstance) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + +func (x *DiscoverElastiCacheInstance) GetEngine() DiscoverElastiCacheEngine { + if x != nil { + return x.Engine + } + return DiscoverElastiCacheEngine_DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED +} + +func (x *DiscoverElastiCacheInstance) GetEngineVersion() string { + if x != nil { + return x.EngineVersion + } + return "" +} + +func (x *DiscoverElastiCacheInstance) GetTransitEncryptionEnabled() bool { + if x != nil { + return x.TransitEncryptionEnabled + } + return false +} + +func (x *DiscoverElastiCacheInstance) GetCluster() string { + if x != nil { + return x.Cluster + } + return "" +} + +type DiscoverElastiCacheRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // AWS Access key. Optional — if empty, the default credential chain is used. + AwsAccessKey string `protobuf:"bytes,1,opt,name=aws_access_key,json=awsAccessKey,proto3" json:"aws_access_key,omitempty"` + // AWS Secret key. Optional. + AwsSecretKey string `protobuf:"bytes,2,opt,name=aws_secret_key,json=awsSecretKey,proto3" json:"aws_secret_key,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DiscoverElastiCacheRequest) Reset() { + *x = DiscoverElastiCacheRequest{} + mi := &file_management_v1_elasticache_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DiscoverElastiCacheRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DiscoverElastiCacheRequest) ProtoMessage() {} + +func (x *DiscoverElastiCacheRequest) ProtoReflect() protoreflect.Message { + mi := &file_management_v1_elasticache_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DiscoverElastiCacheRequest.ProtoReflect.Descriptor instead. +func (*DiscoverElastiCacheRequest) Descriptor() ([]byte, []int) { + return file_management_v1_elasticache_proto_rawDescGZIP(), []int{1} +} + +func (x *DiscoverElastiCacheRequest) GetAwsAccessKey() string { + if x != nil { + return x.AwsAccessKey + } + return "" +} + +func (x *DiscoverElastiCacheRequest) GetAwsSecretKey() string { + if x != nil { + return x.AwsSecretKey + } + return "" +} + +type DiscoverElastiCacheResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + ElasticacheInstances []*DiscoverElastiCacheInstance `protobuf:"bytes,1,rep,name=elasticache_instances,json=elasticacheInstances,proto3" json:"elasticache_instances,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DiscoverElastiCacheResponse) Reset() { + *x = DiscoverElastiCacheResponse{} + mi := &file_management_v1_elasticache_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DiscoverElastiCacheResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DiscoverElastiCacheResponse) ProtoMessage() {} + +func (x *DiscoverElastiCacheResponse) ProtoReflect() protoreflect.Message { + mi := &file_management_v1_elasticache_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DiscoverElastiCacheResponse.ProtoReflect.Descriptor instead. +func (*DiscoverElastiCacheResponse) Descriptor() ([]byte, []int) { + return file_management_v1_elasticache_proto_rawDescGZIP(), []int{2} +} + +func (x *DiscoverElastiCacheResponse) GetElasticacheInstances() []*DiscoverElastiCacheInstance { + if x != nil { + return x.ElasticacheInstances + } + return nil +} + +type AddElastiCacheServiceParams struct { + state protoimpl.MessageState `protogen:"open.v1"` + // AWS region. + Region string `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` + // AWS availability zone. + Az string `protobuf:"bytes,2,opt,name=az,proto3" json:"az,omitempty"` + // Replication group identifier. + InstanceId string `protobuf:"bytes,3,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` + // Cache node type. + NodeModel string `protobuf:"bytes,4,opt,name=node_model,json=nodeModel,proto3" json:"node_model,omitempty"` + // Primary endpoint address. + Address string `protobuf:"bytes,5,opt,name=address,proto3" json:"address,omitempty"` + // Primary endpoint port. + Port uint32 `protobuf:"varint,6,opt,name=port,proto3" json:"port,omitempty"` + // Engine type. + Engine DiscoverElastiCacheEngine `protobuf:"varint,7,opt,name=engine,proto3,enum=management.v1.DiscoverElastiCacheEngine" json:"engine,omitempty"` + // PMM Agent ID. + PmmAgentId string `protobuf:"bytes,8,opt,name=pmm_agent_id,json=pmmAgentId,proto3" json:"pmm_agent_id,omitempty"` + // Unique across all Nodes user-defined name. Defaults to instance_id. + NodeName string `protobuf:"bytes,9,opt,name=node_name,json=nodeName,proto3" json:"node_name,omitempty"` + // Unique across all Services user-defined name. Defaults to instance_id. + ServiceName string `protobuf:"bytes,10,opt,name=service_name,json=serviceName,proto3" json:"service_name,omitempty"` + // Environment name. + Environment string `protobuf:"bytes,11,opt,name=environment,proto3" json:"environment,omitempty"` + // Cluster name. + Cluster string `protobuf:"bytes,12,opt,name=cluster,proto3" json:"cluster,omitempty"` + // Replication set name. + ReplicationSet string `protobuf:"bytes,13,opt,name=replication_set,json=replicationSet,proto3" json:"replication_set,omitempty"` + // Username for scraping metrics. + Username string `protobuf:"bytes,14,opt,name=username,proto3" json:"username,omitempty"` + // Password for scraping metrics. + Password string `protobuf:"bytes,15,opt,name=password,proto3" json:"password,omitempty"` + // Custom user-assigned labels for Node and Service. + CustomLabels map[string]string `protobuf:"bytes,16,rep,name=custom_labels,json=customLabels,proto3" json:"custom_labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Skip connection check. + SkipConnectionCheck bool `protobuf:"varint,17,opt,name=skip_connection_check,json=skipConnectionCheck,proto3" json:"skip_connection_check,omitempty"` + // Use TLS for database connections. + Tls bool `protobuf:"varint,18,opt,name=tls,proto3" json:"tls,omitempty"` + // Skip TLS certificate and hostname validation. + TlsSkipVerify bool `protobuf:"varint,19,opt,name=tls_skip_verify,json=tlsSkipVerify,proto3" json:"tls_skip_verify,omitempty"` + // Defines metrics flow model for this exporter. + MetricsMode MetricsMode `protobuf:"varint,20,opt,name=metrics_mode,json=metricsMode,proto3,enum=management.v1.MetricsMode" json:"metrics_mode,omitempty"` + // Custom password for exporter endpoint /metrics. + AgentPassword string `protobuf:"bytes,21,opt,name=agent_password,json=agentPassword,proto3" json:"agent_password,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddElastiCacheServiceParams) Reset() { + *x = AddElastiCacheServiceParams{} + mi := &file_management_v1_elasticache_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddElastiCacheServiceParams) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddElastiCacheServiceParams) ProtoMessage() {} + +func (x *AddElastiCacheServiceParams) ProtoReflect() protoreflect.Message { + mi := &file_management_v1_elasticache_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddElastiCacheServiceParams.ProtoReflect.Descriptor instead. +func (*AddElastiCacheServiceParams) Descriptor() ([]byte, []int) { + return file_management_v1_elasticache_proto_rawDescGZIP(), []int{3} +} + +func (x *AddElastiCacheServiceParams) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetAz() string { + if x != nil { + return x.Az + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetInstanceId() string { + if x != nil { + return x.InstanceId + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetNodeModel() string { + if x != nil { + return x.NodeModel + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + +func (x *AddElastiCacheServiceParams) GetEngine() DiscoverElastiCacheEngine { + if x != nil { + return x.Engine + } + return DiscoverElastiCacheEngine_DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED +} + +func (x *AddElastiCacheServiceParams) GetPmmAgentId() string { + if x != nil { + return x.PmmAgentId + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetNodeName() string { + if x != nil { + return x.NodeName + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetServiceName() string { + if x != nil { + return x.ServiceName + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetEnvironment() string { + if x != nil { + return x.Environment + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetCluster() string { + if x != nil { + return x.Cluster + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetReplicationSet() string { + if x != nil { + return x.ReplicationSet + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +func (x *AddElastiCacheServiceParams) GetCustomLabels() map[string]string { + if x != nil { + return x.CustomLabels + } + return nil +} + +func (x *AddElastiCacheServiceParams) GetSkipConnectionCheck() bool { + if x != nil { + return x.SkipConnectionCheck + } + return false +} + +func (x *AddElastiCacheServiceParams) GetTls() bool { + if x != nil { + return x.Tls + } + return false +} + +func (x *AddElastiCacheServiceParams) GetTlsSkipVerify() bool { + if x != nil { + return x.TlsSkipVerify + } + return false +} + +func (x *AddElastiCacheServiceParams) GetMetricsMode() MetricsMode { + if x != nil { + return x.MetricsMode + } + return MetricsMode_METRICS_MODE_UNSPECIFIED +} + +func (x *AddElastiCacheServiceParams) GetAgentPassword() string { + if x != nil { + return x.AgentPassword + } + return "" +} + +type ElastiCacheServiceResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + Node *v1.RemoteElastiCacheNode `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` + ValkeyService *v1.ValkeyService `protobuf:"bytes,2,opt,name=valkey_service,json=valkeyService,proto3" json:"valkey_service,omitempty"` + ValkeyExporter *v1.ValkeyExporter `protobuf:"bytes,3,opt,name=valkey_exporter,json=valkeyExporter,proto3" json:"valkey_exporter,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ElastiCacheServiceResult) Reset() { + *x = ElastiCacheServiceResult{} + mi := &file_management_v1_elasticache_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ElastiCacheServiceResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ElastiCacheServiceResult) ProtoMessage() {} + +func (x *ElastiCacheServiceResult) ProtoReflect() protoreflect.Message { + mi := &file_management_v1_elasticache_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ElastiCacheServiceResult.ProtoReflect.Descriptor instead. +func (*ElastiCacheServiceResult) Descriptor() ([]byte, []int) { + return file_management_v1_elasticache_proto_rawDescGZIP(), []int{4} +} + +func (x *ElastiCacheServiceResult) GetNode() *v1.RemoteElastiCacheNode { + if x != nil { + return x.Node + } + return nil +} + +func (x *ElastiCacheServiceResult) GetValkeyService() *v1.ValkeyService { + if x != nil { + return x.ValkeyService + } + return nil +} + +func (x *ElastiCacheServiceResult) GetValkeyExporter() *v1.ValkeyExporter { + if x != nil { + return x.ValkeyExporter + } + return nil +} + +var File_management_v1_elasticache_proto protoreflect.FileDescriptor + +const file_management_v1_elasticache_proto_rawDesc = "" + + "\n" + + "\x1fmanagement/v1/elasticache.proto\x12\rmanagement.v1\x1a\x1aextensions/v1/redact.proto\x1a\x19inventory/v1/agents.proto\x1a\x18inventory/v1/nodes.proto\x1a\x1binventory/v1/services.proto\x1a\x1bmanagement/v1/metrics.proto\x1a\x17validate/validate.proto\"\xf4\x02\n" + + "\x1bDiscoverElastiCacheInstance\x12\x16\n" + + "\x06region\x18\x01 \x01(\tR\x06region\x12\x0e\n" + + "\x02az\x18\x02 \x01(\tR\x02az\x12\x1f\n" + + "\vinstance_id\x18\x03 \x01(\tR\n" + + "instanceId\x12\x1d\n" + + "\n" + + "node_model\x18\x04 \x01(\tR\tnodeModel\x12\x18\n" + + "\aaddress\x18\x05 \x01(\tR\aaddress\x12\x12\n" + + "\x04port\x18\x06 \x01(\rR\x04port\x12@\n" + + "\x06engine\x18\a \x01(\x0e2(.management.v1.DiscoverElastiCacheEngineR\x06engine\x12%\n" + + "\x0eengine_version\x18\b \x01(\tR\rengineVersion\x12<\n" + + "\x1atransit_encryption_enabled\x18\t \x01(\bR\x18transitEncryptionEnabled\x12\x18\n" + + "\acluster\x18\n" + + " \x01(\tR\acluster\"t\n" + + "\x1aDiscoverElastiCacheRequest\x12*\n" + + "\x0eaws_access_key\x18\x01 \x01(\tB\x04\x88\xb5\x18\x01R\fawsAccessKey\x12*\n" + + "\x0eaws_secret_key\x18\x02 \x01(\tB\x04\x88\xb5\x18\x01R\fawsSecretKey\"~\n" + + "\x1bDiscoverElastiCacheResponse\x12_\n" + + "\x15elasticache_instances\x18\x01 \x03(\v2*.management.v1.DiscoverElastiCacheInstanceR\x14elasticacheInstances\"\x9c\a\n" + + "\x1bAddElastiCacheServiceParams\x12\x1f\n" + + "\x06region\x18\x01 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\x06region\x12\x0e\n" + + "\x02az\x18\x02 \x01(\tR\x02az\x12(\n" + + "\vinstance_id\x18\x03 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\n" + + "instanceId\x12\x1d\n" + + "\n" + + "node_model\x18\x04 \x01(\tR\tnodeModel\x12!\n" + + "\aaddress\x18\x05 \x01(\tB\a\xfaB\x04r\x02\x10\x01R\aaddress\x12\x1b\n" + + "\x04port\x18\x06 \x01(\rB\a\xfaB\x04*\x02 \x00R\x04port\x12@\n" + + "\x06engine\x18\a \x01(\x0e2(.management.v1.DiscoverElastiCacheEngineR\x06engine\x12 \n" + + "\fpmm_agent_id\x18\b \x01(\tR\n" + + "pmmAgentId\x12\x1b\n" + + "\tnode_name\x18\t \x01(\tR\bnodeName\x12!\n" + + "\fservice_name\x18\n" + + " \x01(\tR\vserviceName\x12 \n" + + "\venvironment\x18\v \x01(\tR\venvironment\x12\x18\n" + + "\acluster\x18\f \x01(\tR\acluster\x12'\n" + + "\x0freplication_set\x18\r \x01(\tR\x0ereplicationSet\x12\x1a\n" + + "\busername\x18\x0e \x01(\tR\busername\x12 \n" + + "\bpassword\x18\x0f \x01(\tB\x04\x88\xb5\x18\x01R\bpassword\x12a\n" + + "\rcustom_labels\x18\x10 \x03(\v2<.management.v1.AddElastiCacheServiceParams.CustomLabelsEntryR\fcustomLabels\x122\n" + + "\x15skip_connection_check\x18\x11 \x01(\bR\x13skipConnectionCheck\x12\x10\n" + + "\x03tls\x18\x12 \x01(\bR\x03tls\x12&\n" + + "\x0ftls_skip_verify\x18\x13 \x01(\bR\rtlsSkipVerify\x12=\n" + + "\fmetrics_mode\x18\x14 \x01(\x0e2\x1a.management.v1.MetricsModeR\vmetricsMode\x12+\n" + + "\x0eagent_password\x18\x15 \x01(\tB\x04\x88\xb5\x18\x01R\ragentPassword\x1a?\n" + + "\x11CustomLabelsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xde\x01\n" + + "\x18ElastiCacheServiceResult\x127\n" + + "\x04node\x18\x01 \x01(\v2#.inventory.v1.RemoteElastiCacheNodeR\x04node\x12B\n" + + "\x0evalkey_service\x18\x02 \x01(\v2\x1b.inventory.v1.ValkeyServiceR\rvalkeyService\x12E\n" + + "\x0fvalkey_exporter\x18\x03 \x01(\v2\x1c.inventory.v1.ValkeyExporterR\x0evalkeyExporter*\x9a\x01\n" + + "\x19DiscoverElastiCacheEngine\x12,\n" + + "(DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED\x10\x00\x12&\n" + + "\"DISCOVER_ELASTI_CACHE_ENGINE_REDIS\x10\x01\x12'\n" + + "#DISCOVER_ELASTI_CACHE_ENGINE_VALKEY\x10\x02B\xb1\x01\n" + + "\x11com.management.v1B\x10ElasticacheProtoP\x01Z5github.com/percona/pmm/api/management/v1;managementv1\xa2\x02\x03MXX\xaa\x02\rManagement.V1\xca\x02\rManagement\\V1\xe2\x02\x19Management\\V1\\GPBMetadata\xea\x02\x0eManagement::V1b\x06proto3" + +var ( + file_management_v1_elasticache_proto_rawDescOnce sync.Once + file_management_v1_elasticache_proto_rawDescData []byte +) + +func file_management_v1_elasticache_proto_rawDescGZIP() []byte { + file_management_v1_elasticache_proto_rawDescOnce.Do(func() { + file_management_v1_elasticache_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_management_v1_elasticache_proto_rawDesc), len(file_management_v1_elasticache_proto_rawDesc))) + }) + return file_management_v1_elasticache_proto_rawDescData +} + +var ( + file_management_v1_elasticache_proto_enumTypes = make([]protoimpl.EnumInfo, 1) + file_management_v1_elasticache_proto_msgTypes = make([]protoimpl.MessageInfo, 6) + file_management_v1_elasticache_proto_goTypes = []any{ + DiscoverElastiCacheEngine(0), // 0: management.v1.DiscoverElastiCacheEngine + (*DiscoverElastiCacheInstance)(nil), // 1: management.v1.DiscoverElastiCacheInstance + (*DiscoverElastiCacheRequest)(nil), // 2: management.v1.DiscoverElastiCacheRequest + (*DiscoverElastiCacheResponse)(nil), // 3: management.v1.DiscoverElastiCacheResponse + (*AddElastiCacheServiceParams)(nil), // 4: management.v1.AddElastiCacheServiceParams + (*ElastiCacheServiceResult)(nil), // 5: management.v1.ElastiCacheServiceResult + nil, // 6: management.v1.AddElastiCacheServiceParams.CustomLabelsEntry + MetricsMode(0), // 7: management.v1.MetricsMode + (*v1.RemoteElastiCacheNode)(nil), // 8: inventory.v1.RemoteElastiCacheNode + (*v1.ValkeyService)(nil), // 9: inventory.v1.ValkeyService + (*v1.ValkeyExporter)(nil), // 10: inventory.v1.ValkeyExporter + } +) + +var file_management_v1_elasticache_proto_depIdxs = []int32{ + 0, // 0: management.v1.DiscoverElastiCacheInstance.engine:type_name -> management.v1.DiscoverElastiCacheEngine + 1, // 1: management.v1.DiscoverElastiCacheResponse.elasticache_instances:type_name -> management.v1.DiscoverElastiCacheInstance + 0, // 2: management.v1.AddElastiCacheServiceParams.engine:type_name -> management.v1.DiscoverElastiCacheEngine + 6, // 3: management.v1.AddElastiCacheServiceParams.custom_labels:type_name -> management.v1.AddElastiCacheServiceParams.CustomLabelsEntry + 7, // 4: management.v1.AddElastiCacheServiceParams.metrics_mode:type_name -> management.v1.MetricsMode + 8, // 5: management.v1.ElastiCacheServiceResult.node:type_name -> inventory.v1.RemoteElastiCacheNode + 9, // 6: management.v1.ElastiCacheServiceResult.valkey_service:type_name -> inventory.v1.ValkeyService + 10, // 7: management.v1.ElastiCacheServiceResult.valkey_exporter:type_name -> inventory.v1.ValkeyExporter + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name +} + +func init() { file_management_v1_elasticache_proto_init() } +func file_management_v1_elasticache_proto_init() { + if File_management_v1_elasticache_proto != nil { + return + } + file_management_v1_metrics_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_management_v1_elasticache_proto_rawDesc), len(file_management_v1_elasticache_proto_rawDesc)), + NumEnums: 1, + NumMessages: 6, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_management_v1_elasticache_proto_goTypes, + DependencyIndexes: file_management_v1_elasticache_proto_depIdxs, + EnumInfos: file_management_v1_elasticache_proto_enumTypes, + MessageInfos: file_management_v1_elasticache_proto_msgTypes, + }.Build() + File_management_v1_elasticache_proto = out.File + file_management_v1_elasticache_proto_goTypes = nil + file_management_v1_elasticache_proto_depIdxs = nil +} diff --git a/api/management/v1/elasticache.pb.validate.go b/api/management/v1/elasticache.pb.validate.go new file mode 100644 index 00000000000..a6500392297 --- /dev/null +++ b/api/management/v1/elasticache.pb.validate.go @@ -0,0 +1,777 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: management/v1/elasticache.proto + +package managementv1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on DiscoverElastiCacheInstance with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *DiscoverElastiCacheInstance) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on DiscoverElastiCacheInstance with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// DiscoverElastiCacheInstanceMultiError, or nil if none found. +func (m *DiscoverElastiCacheInstance) ValidateAll() error { + return m.validate(true) +} + +func (m *DiscoverElastiCacheInstance) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Region + + // no validation rules for Az + + // no validation rules for InstanceId + + // no validation rules for NodeModel + + // no validation rules for Address + + // no validation rules for Port + + // no validation rules for Engine + + // no validation rules for EngineVersion + + // no validation rules for TransitEncryptionEnabled + + // no validation rules for Cluster + + if len(errors) > 0 { + return DiscoverElastiCacheInstanceMultiError(errors) + } + + return nil +} + +// DiscoverElastiCacheInstanceMultiError is an error wrapping multiple +// validation errors returned by DiscoverElastiCacheInstance.ValidateAll() if +// the designated constraints aren't met. +type DiscoverElastiCacheInstanceMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m DiscoverElastiCacheInstanceMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m DiscoverElastiCacheInstanceMultiError) AllErrors() []error { return m } + +// DiscoverElastiCacheInstanceValidationError is the validation error returned +// by DiscoverElastiCacheInstance.Validate if the designated constraints +// aren't met. +type DiscoverElastiCacheInstanceValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e DiscoverElastiCacheInstanceValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e DiscoverElastiCacheInstanceValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e DiscoverElastiCacheInstanceValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e DiscoverElastiCacheInstanceValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e DiscoverElastiCacheInstanceValidationError) ErrorName() string { + return "DiscoverElastiCacheInstanceValidationError" +} + +// Error satisfies the builtin error interface +func (e DiscoverElastiCacheInstanceValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDiscoverElastiCacheInstance.%s: %s%s", + key, + e.field, + e.reason, + cause, + ) +} + +var _ error = DiscoverElastiCacheInstanceValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = DiscoverElastiCacheInstanceValidationError{} + +// Validate checks the field values on DiscoverElastiCacheRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *DiscoverElastiCacheRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on DiscoverElastiCacheRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// DiscoverElastiCacheRequestMultiError, or nil if none found. +func (m *DiscoverElastiCacheRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *DiscoverElastiCacheRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for AwsAccessKey + + // no validation rules for AwsSecretKey + + if len(errors) > 0 { + return DiscoverElastiCacheRequestMultiError(errors) + } + + return nil +} + +// DiscoverElastiCacheRequestMultiError is an error wrapping multiple +// validation errors returned by DiscoverElastiCacheRequest.ValidateAll() if +// the designated constraints aren't met. +type DiscoverElastiCacheRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m DiscoverElastiCacheRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m DiscoverElastiCacheRequestMultiError) AllErrors() []error { return m } + +// DiscoverElastiCacheRequestValidationError is the validation error returned +// by DiscoverElastiCacheRequest.Validate if the designated constraints aren't met. +type DiscoverElastiCacheRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e DiscoverElastiCacheRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e DiscoverElastiCacheRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e DiscoverElastiCacheRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e DiscoverElastiCacheRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e DiscoverElastiCacheRequestValidationError) ErrorName() string { + return "DiscoverElastiCacheRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e DiscoverElastiCacheRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDiscoverElastiCacheRequest.%s: %s%s", + key, + e.field, + e.reason, + cause, + ) +} + +var _ error = DiscoverElastiCacheRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = DiscoverElastiCacheRequestValidationError{} + +// Validate checks the field values on DiscoverElastiCacheResponse with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *DiscoverElastiCacheResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on DiscoverElastiCacheResponse with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// DiscoverElastiCacheResponseMultiError, or nil if none found. +func (m *DiscoverElastiCacheResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *DiscoverElastiCacheResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetElasticacheInstances() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, DiscoverElastiCacheResponseValidationError{ + field: fmt.Sprintf("ElasticacheInstances[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, DiscoverElastiCacheResponseValidationError{ + field: fmt.Sprintf("ElasticacheInstances[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DiscoverElastiCacheResponseValidationError{ + field: fmt.Sprintf("ElasticacheInstances[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return DiscoverElastiCacheResponseMultiError(errors) + } + + return nil +} + +// DiscoverElastiCacheResponseMultiError is an error wrapping multiple +// validation errors returned by DiscoverElastiCacheResponse.ValidateAll() if +// the designated constraints aren't met. +type DiscoverElastiCacheResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m DiscoverElastiCacheResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m DiscoverElastiCacheResponseMultiError) AllErrors() []error { return m } + +// DiscoverElastiCacheResponseValidationError is the validation error returned +// by DiscoverElastiCacheResponse.Validate if the designated constraints +// aren't met. +type DiscoverElastiCacheResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e DiscoverElastiCacheResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e DiscoverElastiCacheResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e DiscoverElastiCacheResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e DiscoverElastiCacheResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e DiscoverElastiCacheResponseValidationError) ErrorName() string { + return "DiscoverElastiCacheResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e DiscoverElastiCacheResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDiscoverElastiCacheResponse.%s: %s%s", + key, + e.field, + e.reason, + cause, + ) +} + +var _ error = DiscoverElastiCacheResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = DiscoverElastiCacheResponseValidationError{} + +// Validate checks the field values on AddElastiCacheServiceParams with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *AddElastiCacheServiceParams) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on AddElastiCacheServiceParams with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// AddElastiCacheServiceParamsMultiError, or nil if none found. +func (m *AddElastiCacheServiceParams) ValidateAll() error { + return m.validate(true) +} + +func (m *AddElastiCacheServiceParams) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if utf8.RuneCountInString(m.GetRegion()) < 1 { + err := AddElastiCacheServiceParamsValidationError{ + field: "Region", + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } + + // no validation rules for Az + + if utf8.RuneCountInString(m.GetInstanceId()) < 1 { + err := AddElastiCacheServiceParamsValidationError{ + field: "InstanceId", + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } + + // no validation rules for NodeModel + + if utf8.RuneCountInString(m.GetAddress()) < 1 { + err := AddElastiCacheServiceParamsValidationError{ + field: "Address", + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } + + if m.GetPort() <= 0 { + err := AddElastiCacheServiceParamsValidationError{ + field: "Port", + reason: "value must be greater than 0", + } + if !all { + return err + } + errors = append(errors, err) + } + + // no validation rules for Engine + + // no validation rules for PmmAgentId + + // no validation rules for NodeName + + // no validation rules for ServiceName + + // no validation rules for Environment + + // no validation rules for Cluster + + // no validation rules for ReplicationSet + + // no validation rules for Username + + // no validation rules for Password + + // no validation rules for CustomLabels + + // no validation rules for SkipConnectionCheck + + // no validation rules for Tls + + // no validation rules for TlsSkipVerify + + // no validation rules for MetricsMode + + // no validation rules for AgentPassword + + if len(errors) > 0 { + return AddElastiCacheServiceParamsMultiError(errors) + } + + return nil +} + +// AddElastiCacheServiceParamsMultiError is an error wrapping multiple +// validation errors returned by AddElastiCacheServiceParams.ValidateAll() if +// the designated constraints aren't met. +type AddElastiCacheServiceParamsMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m AddElastiCacheServiceParamsMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m AddElastiCacheServiceParamsMultiError) AllErrors() []error { return m } + +// AddElastiCacheServiceParamsValidationError is the validation error returned +// by AddElastiCacheServiceParams.Validate if the designated constraints +// aren't met. +type AddElastiCacheServiceParamsValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e AddElastiCacheServiceParamsValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e AddElastiCacheServiceParamsValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e AddElastiCacheServiceParamsValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e AddElastiCacheServiceParamsValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e AddElastiCacheServiceParamsValidationError) ErrorName() string { + return "AddElastiCacheServiceParamsValidationError" +} + +// Error satisfies the builtin error interface +func (e AddElastiCacheServiceParamsValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAddElastiCacheServiceParams.%s: %s%s", + key, + e.field, + e.reason, + cause, + ) +} + +var _ error = AddElastiCacheServiceParamsValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = AddElastiCacheServiceParamsValidationError{} + +// Validate checks the field values on ElastiCacheServiceResult with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ElastiCacheServiceResult) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ElastiCacheServiceResult with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ElastiCacheServiceResultMultiError, or nil if none found. +func (m *ElastiCacheServiceResult) ValidateAll() error { + return m.validate(true) +} + +func (m *ElastiCacheServiceResult) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetNode()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ElastiCacheServiceResultValidationError{ + field: "Node", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ElastiCacheServiceResultValidationError{ + field: "Node", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetNode()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ElastiCacheServiceResultValidationError{ + field: "Node", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if all { + switch v := interface{}(m.GetValkeyService()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ElastiCacheServiceResultValidationError{ + field: "ValkeyService", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ElastiCacheServiceResultValidationError{ + field: "ValkeyService", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetValkeyService()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ElastiCacheServiceResultValidationError{ + field: "ValkeyService", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if all { + switch v := interface{}(m.GetValkeyExporter()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ElastiCacheServiceResultValidationError{ + field: "ValkeyExporter", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ElastiCacheServiceResultValidationError{ + field: "ValkeyExporter", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetValkeyExporter()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ElastiCacheServiceResultValidationError{ + field: "ValkeyExporter", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return ElastiCacheServiceResultMultiError(errors) + } + + return nil +} + +// ElastiCacheServiceResultMultiError is an error wrapping multiple validation +// errors returned by ElastiCacheServiceResult.ValidateAll() if the designated +// constraints aren't met. +type ElastiCacheServiceResultMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ElastiCacheServiceResultMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ElastiCacheServiceResultMultiError) AllErrors() []error { return m } + +// ElastiCacheServiceResultValidationError is the validation error returned by +// ElastiCacheServiceResult.Validate if the designated constraints aren't met. +type ElastiCacheServiceResultValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ElastiCacheServiceResultValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ElastiCacheServiceResultValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ElastiCacheServiceResultValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ElastiCacheServiceResultValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ElastiCacheServiceResultValidationError) ErrorName() string { + return "ElastiCacheServiceResultValidationError" +} + +// Error satisfies the builtin error interface +func (e ElastiCacheServiceResultValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sElastiCacheServiceResult.%s: %s%s", + key, + e.field, + e.reason, + cause, + ) +} + +var _ error = ElastiCacheServiceResultValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ElastiCacheServiceResultValidationError{} diff --git a/api/management/v1/elasticache.proto b/api/management/v1/elasticache.proto new file mode 100644 index 00000000000..0e36945eb9a --- /dev/null +++ b/api/management/v1/elasticache.proto @@ -0,0 +1,103 @@ +syntax = "proto3"; + +package management.v1; + +import "extensions/v1/redact.proto"; +import "inventory/v1/agents.proto"; +import "inventory/v1/nodes.proto"; +import "inventory/v1/services.proto"; +import "management/v1/metrics.proto"; +import "validate/validate.proto"; + +// DiscoverElastiCacheEngine describes supported ElastiCache engines. +enum DiscoverElastiCacheEngine { + DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED = 0; + DISCOVER_ELASTI_CACHE_ENGINE_REDIS = 1; + DISCOVER_ELASTI_CACHE_ENGINE_VALKEY = 2; +} + +// DiscoverElastiCacheInstance models an ElastiCache replication group discovered by the API. +message DiscoverElastiCacheInstance { + // AWS region. + string region = 1; + // AWS availability zone. + string az = 2; + // Replication group identifier. + string instance_id = 3; + // Cache node type (e.g. cache.r7g.large). + string node_model = 4; + // Primary endpoint address. + string address = 5; + // Primary endpoint port. + uint32 port = 6; + // Engine type (redis or valkey). + DiscoverElastiCacheEngine engine = 7; + // Engine version. + string engine_version = 8; + // Whether in-transit encryption is enabled. + bool transit_encryption_enabled = 9; + // Cluster name (replication group ID). + string cluster = 10; +} + +message DiscoverElastiCacheRequest { + // AWS Access key. Optional — if empty, the default credential chain is used. + string aws_access_key = 1 [(extensions.v1.sensitive) = REDACT_TYPE_FULL]; + // AWS Secret key. Optional. + string aws_secret_key = 2 [(extensions.v1.sensitive) = REDACT_TYPE_FULL]; +} + +message DiscoverElastiCacheResponse { + repeated DiscoverElastiCacheInstance elasticache_instances = 1; +} + +message AddElastiCacheServiceParams { + // AWS region. + string region = 1 [(validate.rules).string.min_len = 1]; + // AWS availability zone. + string az = 2; + // Replication group identifier. + string instance_id = 3 [(validate.rules).string.min_len = 1]; + // Cache node type. + string node_model = 4; + // Primary endpoint address. + string address = 5 [(validate.rules).string.min_len = 1]; + // Primary endpoint port. + uint32 port = 6 [(validate.rules).uint32.gt = 0]; + // Engine type. + DiscoverElastiCacheEngine engine = 7; + // PMM Agent ID. + string pmm_agent_id = 8; + // Unique across all Nodes user-defined name. Defaults to instance_id. + string node_name = 9; + // Unique across all Services user-defined name. Defaults to instance_id. + string service_name = 10; + // Environment name. + string environment = 11; + // Cluster name. + string cluster = 12; + // Replication set name. + string replication_set = 13; + // Username for scraping metrics. + string username = 14; + // Password for scraping metrics. + string password = 15 [(extensions.v1.sensitive) = REDACT_TYPE_FULL]; + // Custom user-assigned labels for Node and Service. + map custom_labels = 16; + // Skip connection check. + bool skip_connection_check = 17; + // Use TLS for database connections. + bool tls = 18; + // Skip TLS certificate and hostname validation. + bool tls_skip_verify = 19; + // Defines metrics flow model for this exporter. + MetricsMode metrics_mode = 20; + // Custom password for exporter endpoint /metrics. + string agent_password = 21 [(extensions.v1.sensitive) = REDACT_TYPE_FULL]; +} + +message ElastiCacheServiceResult { + inventory.v1.RemoteElastiCacheNode node = 1; + inventory.v1.ValkeyService valkey_service = 2; + inventory.v1.ValkeyExporter valkey_exporter = 3; +} diff --git a/api/management/v1/json/client/management_service/add_service_responses.go b/api/management/v1/json/client/management_service/add_service_responses.go index 357450d0c64..32a9c608b0e 100644 --- a/api/management/v1/json/client/management_service/add_service_responses.go +++ b/api/management/v1/json/client/management_service/add_service_responses.go @@ -190,6 +190,9 @@ AddServiceBody add service body swagger:model AddServiceBody */ type AddServiceBody struct { + // elasticache + Elasticache *AddServiceParamsBodyElasticache `json:"elasticache,omitempty"` + // external External *AddServiceParamsBodyExternal `json:"external,omitempty"` @@ -219,6 +222,10 @@ type AddServiceBody struct { func (o *AddServiceBody) Validate(formats strfmt.Registry) error { var res []error + if err := o.validateElasticache(formats); err != nil { + res = append(res, err) + } + if err := o.validateExternal(formats); err != nil { res = append(res, err) } @@ -257,6 +264,29 @@ func (o *AddServiceBody) Validate(formats strfmt.Registry) error { return nil } +func (o *AddServiceBody) validateElasticache(formats strfmt.Registry) error { + if swag.IsZero(o.Elasticache) { // not required + return nil + } + + if o.Elasticache != nil { + if err := o.Elasticache.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("body" + "." + "elasticache") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("body" + "." + "elasticache") + } + + return err + } + } + + return nil +} + func (o *AddServiceBody) validateExternal(formats strfmt.Registry) error { if swag.IsZero(o.External) { // not required return nil @@ -445,6 +475,10 @@ func (o *AddServiceBody) validateValkey(formats strfmt.Registry) error { func (o *AddServiceBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { var res []error + if err := o.contextValidateElasticache(ctx, formats); err != nil { + res = append(res, err) + } + if err := o.contextValidateExternal(ctx, formats); err != nil { res = append(res, err) } @@ -483,6 +517,30 @@ func (o *AddServiceBody) ContextValidate(ctx context.Context, formats strfmt.Reg return nil } +func (o *AddServiceBody) contextValidateElasticache(ctx context.Context, formats strfmt.Registry) error { + if o.Elasticache != nil { + + if swag.IsZero(o.Elasticache) { // not required + return nil + } + + if err := o.Elasticache.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("body" + "." + "elasticache") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("body" + "." + "elasticache") + } + + return err + } + } + + return nil +} + func (o *AddServiceBody) contextValidateExternal(ctx context.Context, formats strfmt.Registry) error { if o.External != nil { @@ -926,6 +984,9 @@ AddServiceOKBody add service OK body swagger:model AddServiceOKBody */ type AddServiceOKBody struct { + // elasticache + Elasticache *AddServiceOKBodyElasticache `json:"elasticache,omitempty"` + // external External *AddServiceOKBodyExternal `json:"external,omitempty"` @@ -955,6 +1016,10 @@ type AddServiceOKBody struct { func (o *AddServiceOKBody) Validate(formats strfmt.Registry) error { var res []error + if err := o.validateElasticache(formats); err != nil { + res = append(res, err) + } + if err := o.validateExternal(formats); err != nil { res = append(res, err) } @@ -993,6 +1058,29 @@ func (o *AddServiceOKBody) Validate(formats strfmt.Registry) error { return nil } +func (o *AddServiceOKBody) validateElasticache(formats strfmt.Registry) error { + if swag.IsZero(o.Elasticache) { // not required + return nil + } + + if o.Elasticache != nil { + if err := o.Elasticache.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addServiceOk" + "." + "elasticache") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addServiceOk" + "." + "elasticache") + } + + return err + } + } + + return nil +} + func (o *AddServiceOKBody) validateExternal(formats strfmt.Registry) error { if swag.IsZero(o.External) { // not required return nil @@ -1181,6 +1269,10 @@ func (o *AddServiceOKBody) validateValkey(formats strfmt.Registry) error { func (o *AddServiceOKBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { var res []error + if err := o.contextValidateElasticache(ctx, formats); err != nil { + res = append(res, err) + } + if err := o.contextValidateExternal(ctx, formats); err != nil { res = append(res, err) } @@ -1219,6 +1311,30 @@ func (o *AddServiceOKBody) ContextValidate(ctx context.Context, formats strfmt.R return nil } +func (o *AddServiceOKBody) contextValidateElasticache(ctx context.Context, formats strfmt.Registry) error { + if o.Elasticache != nil { + + if swag.IsZero(o.Elasticache) { // not required + return nil + } + + if err := o.Elasticache.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addServiceOk" + "." + "elasticache") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addServiceOk" + "." + "elasticache") + } + + return err + } + } + + return nil +} + func (o *AddServiceOKBody) contextValidateExternal(ctx context.Context, formats strfmt.Registry) error { if o.External != nil { @@ -1356,63 +1472,672 @@ func (o *AddServiceOKBody) contextValidateProxysql(ctx context.Context, formats return ce.ValidateName("addServiceOk" + "." + "proxysql") } - return err - } + return err + } + } + + return nil +} + +func (o *AddServiceOKBody) contextValidateRDS(ctx context.Context, formats strfmt.Registry) error { + if o.RDS != nil { + + if swag.IsZero(o.RDS) { // not required + return nil + } + + if err := o.RDS.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addServiceOk" + "." + "rds") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addServiceOk" + "." + "rds") + } + + return err + } + } + + return nil +} + +func (o *AddServiceOKBody) contextValidateValkey(ctx context.Context, formats strfmt.Registry) error { + if o.Valkey != nil { + + if swag.IsZero(o.Valkey) { // not required + return nil + } + + if err := o.Valkey.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addServiceOk" + "." + "valkey") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addServiceOk" + "." + "valkey") + } + + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (o *AddServiceOKBody) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *AddServiceOKBody) UnmarshalBinary(b []byte) error { + var res AddServiceOKBody + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +AddServiceOKBodyElasticache add service OK body elasticache +swagger:model AddServiceOKBodyElasticache +*/ +type AddServiceOKBodyElasticache struct { + // node + Node *AddServiceOKBodyElasticacheNode `json:"node,omitempty"` + + // valkey exporter + ValkeyExporter *AddServiceOKBodyElasticacheValkeyExporter `json:"valkey_exporter,omitempty"` + + // valkey service + ValkeyService *AddServiceOKBodyElasticacheValkeyService `json:"valkey_service,omitempty"` +} + +// Validate validates this add service OK body elasticache +func (o *AddServiceOKBodyElasticache) Validate(formats strfmt.Registry) error { + var res []error + + if err := o.validateNode(formats); err != nil { + res = append(res, err) + } + + if err := o.validateValkeyExporter(formats); err != nil { + res = append(res, err) + } + + if err := o.validateValkeyService(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *AddServiceOKBodyElasticache) validateNode(formats strfmt.Registry) error { + if swag.IsZero(o.Node) { // not required + return nil + } + + if o.Node != nil { + if err := o.Node.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addServiceOk" + "." + "elasticache" + "." + "node") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addServiceOk" + "." + "elasticache" + "." + "node") + } + + return err + } + } + + return nil +} + +func (o *AddServiceOKBodyElasticache) validateValkeyExporter(formats strfmt.Registry) error { + if swag.IsZero(o.ValkeyExporter) { // not required + return nil + } + + if o.ValkeyExporter != nil { + if err := o.ValkeyExporter.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addServiceOk" + "." + "elasticache" + "." + "valkey_exporter") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addServiceOk" + "." + "elasticache" + "." + "valkey_exporter") + } + + return err + } + } + + return nil +} + +func (o *AddServiceOKBodyElasticache) validateValkeyService(formats strfmt.Registry) error { + if swag.IsZero(o.ValkeyService) { // not required + return nil + } + + if o.ValkeyService != nil { + if err := o.ValkeyService.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addServiceOk" + "." + "elasticache" + "." + "valkey_service") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addServiceOk" + "." + "elasticache" + "." + "valkey_service") + } + + return err + } + } + + return nil +} + +// ContextValidate validate this add service OK body elasticache based on the context it is used +func (o *AddServiceOKBodyElasticache) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := o.contextValidateNode(ctx, formats); err != nil { + res = append(res, err) + } + + if err := o.contextValidateValkeyExporter(ctx, formats); err != nil { + res = append(res, err) + } + + if err := o.contextValidateValkeyService(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *AddServiceOKBodyElasticache) contextValidateNode(ctx context.Context, formats strfmt.Registry) error { + if o.Node != nil { + + if swag.IsZero(o.Node) { // not required + return nil + } + + if err := o.Node.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addServiceOk" + "." + "elasticache" + "." + "node") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addServiceOk" + "." + "elasticache" + "." + "node") + } + + return err + } + } + + return nil +} + +func (o *AddServiceOKBodyElasticache) contextValidateValkeyExporter(ctx context.Context, formats strfmt.Registry) error { + if o.ValkeyExporter != nil { + + if swag.IsZero(o.ValkeyExporter) { // not required + return nil + } + + if err := o.ValkeyExporter.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addServiceOk" + "." + "elasticache" + "." + "valkey_exporter") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addServiceOk" + "." + "elasticache" + "." + "valkey_exporter") + } + + return err + } + } + + return nil +} + +func (o *AddServiceOKBodyElasticache) contextValidateValkeyService(ctx context.Context, formats strfmt.Registry) error { + if o.ValkeyService != nil { + + if swag.IsZero(o.ValkeyService) { // not required + return nil + } + + if err := o.ValkeyService.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addServiceOk" + "." + "elasticache" + "." + "valkey_service") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addServiceOk" + "." + "elasticache" + "." + "valkey_service") + } + + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (o *AddServiceOKBodyElasticache) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *AddServiceOKBodyElasticache) UnmarshalBinary(b []byte) error { + var res AddServiceOKBodyElasticache + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +AddServiceOKBodyElasticacheNode RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes. +swagger:model AddServiceOKBodyElasticacheNode +*/ +type AddServiceOKBodyElasticacheNode struct { + // Unique randomly generated instance identifier. + NodeID string `json:"node_id,omitempty"` + + // Unique across all Nodes user-defined name. + NodeName string `json:"node_name,omitempty"` + + // ElastiCache primary endpoint address. + Address string `json:"address,omitempty"` + + // Node model (cache node type). + NodeModel string `json:"node_model,omitempty"` + + // Node region. + Region string `json:"region,omitempty"` + + // Node availability zone. + Az string `json:"az,omitempty"` + + // Custom user-assigned labels. + CustomLabels map[string]string `json:"custom_labels,omitempty"` + + // AWS instance ID (replication group ID). + InstanceID string `json:"instance_id,omitempty"` +} + +// Validate validates this add service OK body elasticache node +func (o *AddServiceOKBodyElasticacheNode) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this add service OK body elasticache node based on context it is used +func (o *AddServiceOKBodyElasticacheNode) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *AddServiceOKBodyElasticacheNode) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *AddServiceOKBodyElasticacheNode) UnmarshalBinary(b []byte) error { + var res AddServiceOKBodyElasticacheNode + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +AddServiceOKBodyElasticacheValkeyExporter ValkeyExporter runs on Generic or Container Node and exposes Valkey Service metrics. +swagger:model AddServiceOKBodyElasticacheValkeyExporter +*/ +type AddServiceOKBodyElasticacheValkeyExporter struct { + // Unique randomly generated instance identifier. + AgentID string `json:"agent_id,omitempty"` + + // The pmm-agent identifier which runs this instance. + PMMAgentID string `json:"pmm_agent_id,omitempty"` + + // Desired Agent status: enabled (false) or disabled (true). + Disabled bool `json:"disabled,omitempty"` + + // Service identifier. + ServiceID string `json:"service_id,omitempty"` + + // Valkey username for scraping metrics. + Username string `json:"username,omitempty"` + + // Use TLS for database connections. + TLS bool `json:"tls,omitempty"` + + // Skip TLS certificate and hostname verification. + TLSSkipVerify bool `json:"tls_skip_verify,omitempty"` + + // Custom user-assigned labels. + CustomLabels map[string]string `json:"custom_labels,omitempty"` + + // True if exporter uses push metrics mode. + PushMetricsEnabled bool `json:"push_metrics_enabled,omitempty"` + + // List of disabled collector names. + DisabledCollectors []string `json:"disabled_collectors"` + + // AgentStatus represents actual Agent status. + // + // - AGENT_STATUS_STARTING: Agent is starting. + // - AGENT_STATUS_INITIALIZATION_ERROR: Agent encountered error when starting. + // - AGENT_STATUS_RUNNING: Agent is running. + // - AGENT_STATUS_WAITING: Agent encountered error and will be restarted automatically soon. + // - AGENT_STATUS_STOPPING: Agent is stopping. + // - AGENT_STATUS_DONE: Agent has been stopped or disabled. + // - AGENT_STATUS_UNKNOWN: Agent is not connected, we don't know anything about it's state. + // Enum: ["AGENT_STATUS_UNSPECIFIED","AGENT_STATUS_STARTING","AGENT_STATUS_INITIALIZATION_ERROR","AGENT_STATUS_RUNNING","AGENT_STATUS_WAITING","AGENT_STATUS_STOPPING","AGENT_STATUS_DONE","AGENT_STATUS_UNKNOWN"] + Status *string `json:"status,omitempty"` + + // Listen port for scraping metrics. + ListenPort int64 `json:"listen_port,omitempty"` + + // Path to exec process. + ProcessExecPath string `json:"process_exec_path,omitempty"` + + // Optionally expose the exporter process on all public interfaces + ExposeExporter bool `json:"expose_exporter,omitempty"` + + // Connection timeout for exporter (if set). + ConnectionTimeout string `json:"connection_timeout,omitempty"` + + // metrics resolutions + MetricsResolutions *AddServiceOKBodyElasticacheValkeyExporterMetricsResolutions `json:"metrics_resolutions,omitempty"` +} + +// Validate validates this add service OK body elasticache valkey exporter +func (o *AddServiceOKBodyElasticacheValkeyExporter) Validate(formats strfmt.Registry) error { + var res []error + + if err := o.validateStatus(formats); err != nil { + res = append(res, err) + } + + if err := o.validateMetricsResolutions(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +var addServiceOkBodyElasticacheValkeyExporterTypeStatusPropEnum []any + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["AGENT_STATUS_UNSPECIFIED","AGENT_STATUS_STARTING","AGENT_STATUS_INITIALIZATION_ERROR","AGENT_STATUS_RUNNING","AGENT_STATUS_WAITING","AGENT_STATUS_STOPPING","AGENT_STATUS_DONE","AGENT_STATUS_UNKNOWN"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + addServiceOkBodyElasticacheValkeyExporterTypeStatusPropEnum = append(addServiceOkBodyElasticacheValkeyExporterTypeStatusPropEnum, v) + } +} + +const ( + + // AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSUNSPECIFIED captures enum value "AGENT_STATUS_UNSPECIFIED" + AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSUNSPECIFIED string = "AGENT_STATUS_UNSPECIFIED" + + // AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSSTARTING captures enum value "AGENT_STATUS_STARTING" + AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSSTARTING string = "AGENT_STATUS_STARTING" + + // AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSINITIALIZATIONERROR captures enum value "AGENT_STATUS_INITIALIZATION_ERROR" + AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSINITIALIZATIONERROR string = "AGENT_STATUS_INITIALIZATION_ERROR" + + // AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSRUNNING captures enum value "AGENT_STATUS_RUNNING" + AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSRUNNING string = "AGENT_STATUS_RUNNING" + + // AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSWAITING captures enum value "AGENT_STATUS_WAITING" + AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSWAITING string = "AGENT_STATUS_WAITING" + + // AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSSTOPPING captures enum value "AGENT_STATUS_STOPPING" + AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSSTOPPING string = "AGENT_STATUS_STOPPING" + + // AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSDONE captures enum value "AGENT_STATUS_DONE" + AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSDONE string = "AGENT_STATUS_DONE" + + // AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSUNKNOWN captures enum value "AGENT_STATUS_UNKNOWN" + AddServiceOKBodyElasticacheValkeyExporterStatusAGENTSTATUSUNKNOWN string = "AGENT_STATUS_UNKNOWN" +) + +// prop value enum +func (o *AddServiceOKBodyElasticacheValkeyExporter) validateStatusEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, addServiceOkBodyElasticacheValkeyExporterTypeStatusPropEnum, true); err != nil { + return err + } + return nil +} + +func (o *AddServiceOKBodyElasticacheValkeyExporter) validateStatus(formats strfmt.Registry) error { + if swag.IsZero(o.Status) { // not required + return nil + } + + // value enum + if err := o.validateStatusEnum("addServiceOk"+"."+"elasticache"+"."+"valkey_exporter"+"."+"status", "body", *o.Status); err != nil { + return err + } + + return nil +} + +func (o *AddServiceOKBodyElasticacheValkeyExporter) validateMetricsResolutions(formats strfmt.Registry) error { + if swag.IsZero(o.MetricsResolutions) { // not required + return nil + } + + if o.MetricsResolutions != nil { + if err := o.MetricsResolutions.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addServiceOk" + "." + "elasticache" + "." + "valkey_exporter" + "." + "metrics_resolutions") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addServiceOk" + "." + "elasticache" + "." + "valkey_exporter" + "." + "metrics_resolutions") + } + + return err + } + } + + return nil +} + +// ContextValidate validate this add service OK body elasticache valkey exporter based on the context it is used +func (o *AddServiceOKBodyElasticacheValkeyExporter) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := o.contextValidateMetricsResolutions(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *AddServiceOKBodyElasticacheValkeyExporter) contextValidateMetricsResolutions(ctx context.Context, formats strfmt.Registry) error { + if o.MetricsResolutions != nil { + + if swag.IsZero(o.MetricsResolutions) { // not required + return nil + } + + if err := o.MetricsResolutions.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("addServiceOk" + "." + "elasticache" + "." + "valkey_exporter" + "." + "metrics_resolutions") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("addServiceOk" + "." + "elasticache" + "." + "valkey_exporter" + "." + "metrics_resolutions") + } + + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (o *AddServiceOKBodyElasticacheValkeyExporter) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *AddServiceOKBodyElasticacheValkeyExporter) UnmarshalBinary(b []byte) error { + var res AddServiceOKBodyElasticacheValkeyExporter + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +AddServiceOKBodyElasticacheValkeyExporterMetricsResolutions MetricsResolutions represents Prometheus exporters metrics resolutions. +swagger:model AddServiceOKBodyElasticacheValkeyExporterMetricsResolutions +*/ +type AddServiceOKBodyElasticacheValkeyExporterMetricsResolutions struct { + // High resolution. In JSON should be represented as a string with number of seconds with `s` suffix. + Hr string `json:"hr,omitempty"` + + // Medium resolution. In JSON should be represented as a string with number of seconds with `s` suffix. + Mr string `json:"mr,omitempty"` + + // Low resolution. In JSON should be represented as a string with number of seconds with `s` suffix. + Lr string `json:"lr,omitempty"` +} + +// Validate validates this add service OK body elasticache valkey exporter metrics resolutions +func (o *AddServiceOKBodyElasticacheValkeyExporterMetricsResolutions) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this add service OK body elasticache valkey exporter metrics resolutions based on context it is used +func (o *AddServiceOKBodyElasticacheValkeyExporterMetricsResolutions) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *AddServiceOKBodyElasticacheValkeyExporterMetricsResolutions) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil } + return swag.WriteJSON(o) +} +// UnmarshalBinary interface implementation +func (o *AddServiceOKBodyElasticacheValkeyExporterMetricsResolutions) UnmarshalBinary(b []byte) error { + var res AddServiceOKBodyElasticacheValkeyExporterMetricsResolutions + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res return nil } -func (o *AddServiceOKBody) contextValidateRDS(ctx context.Context, formats strfmt.Registry) error { - if o.RDS != nil { +/* +AddServiceOKBodyElasticacheValkeyService ValkeyService represents a generic Valkey instance. +swagger:model AddServiceOKBodyElasticacheValkeyService +*/ +type AddServiceOKBodyElasticacheValkeyService struct { + // Unique randomly generated instance identifier. + ServiceID string `json:"service_id,omitempty"` - if swag.IsZero(o.RDS) { // not required - return nil - } + // Unique across all Services user-defined name. + ServiceName string `json:"service_name,omitempty"` - if err := o.RDS.ContextValidate(ctx, formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("addServiceOk" + "." + "rds") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("addServiceOk" + "." + "rds") - } + // Node identifier where this instance runs. + NodeID string `json:"node_id,omitempty"` - return err - } - } + // Access address (DNS name or IP). + // Address (and port) or socket is required. + Address string `json:"address,omitempty"` - return nil -} + // Access port. + // Port is required when the address present. + Port int64 `json:"port,omitempty"` -func (o *AddServiceOKBody) contextValidateValkey(ctx context.Context, formats strfmt.Registry) error { - if o.Valkey != nil { + // Access unix socket. + // Address (and port) or socket is required. + Socket string `json:"socket,omitempty"` - if swag.IsZero(o.Valkey) { // not required - return nil - } + // Environment name. + Environment string `json:"environment,omitempty"` - if err := o.Valkey.ContextValidate(ctx, formats); err != nil { - ve := new(errors.Validation) - if stderrors.As(err, &ve) { - return ve.ValidateName("addServiceOk" + "." + "valkey") - } - ce := new(errors.CompositeError) - if stderrors.As(err, &ce) { - return ce.ValidateName("addServiceOk" + "." + "valkey") - } + // Cluster name. + Cluster string `json:"cluster,omitempty"` - return err - } - } + // Replication set name. + ReplicationSet string `json:"replication_set,omitempty"` + + // Custom user-assigned labels. + CustomLabels map[string]string `json:"custom_labels,omitempty"` + + // Valkey version. + Version string `json:"version,omitempty"` +} + +// Validate validates this add service OK body elasticache valkey service +func (o *AddServiceOKBodyElasticacheValkeyService) Validate(formats strfmt.Registry) error { + return nil +} +// ContextValidate validates this add service OK body elasticache valkey service based on context it is used +func (o *AddServiceOKBodyElasticacheValkeyService) ContextValidate(ctx context.Context, formats strfmt.Registry) error { return nil } // MarshalBinary interface implementation -func (o *AddServiceOKBody) MarshalBinary() ([]byte, error) { +func (o *AddServiceOKBodyElasticacheValkeyService) MarshalBinary() ([]byte, error) { if o == nil { return nil, nil } @@ -1420,8 +2145,8 @@ func (o *AddServiceOKBody) MarshalBinary() ([]byte, error) { } // UnmarshalBinary interface implementation -func (o *AddServiceOKBody) UnmarshalBinary(b []byte) error { - var res AddServiceOKBody +func (o *AddServiceOKBodyElasticacheValkeyService) UnmarshalBinary(b []byte) error { + var res AddServiceOKBodyElasticacheValkeyService if err := swag.ReadJSON(b, &res); err != nil { return err } @@ -9329,6 +10054,211 @@ func (o *AddServiceOKBodyValkeyValkeyExporterMetricsResolutions) UnmarshalBinary return nil } +/* +AddServiceParamsBodyElasticache add service params body elasticache +swagger:model AddServiceParamsBodyElasticache +*/ +type AddServiceParamsBodyElasticache struct { + // AWS region. + Region string `json:"region,omitempty"` + + // AWS availability zone. + Az string `json:"az,omitempty"` + + // Replication group identifier. + InstanceID string `json:"instance_id,omitempty"` + + // Cache node type. + NodeModel string `json:"node_model,omitempty"` + + // Primary endpoint address. + Address string `json:"address,omitempty"` + + // Primary endpoint port. + Port int64 `json:"port,omitempty"` + + // DiscoverElastiCacheEngine describes supported ElastiCache engines. + // Enum: ["DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED","DISCOVER_ELASTI_CACHE_ENGINE_REDIS","DISCOVER_ELASTI_CACHE_ENGINE_VALKEY"] + Engine *string `json:"engine,omitempty"` + + // PMM Agent ID. + PMMAgentID string `json:"pmm_agent_id,omitempty"` + + // Unique across all Nodes user-defined name. Defaults to instance_id. + NodeName string `json:"node_name,omitempty"` + + // Unique across all Services user-defined name. Defaults to instance_id. + ServiceName string `json:"service_name,omitempty"` + + // Environment name. + Environment string `json:"environment,omitempty"` + + // Cluster name. + Cluster string `json:"cluster,omitempty"` + + // Replication set name. + ReplicationSet string `json:"replication_set,omitempty"` + + // Username for scraping metrics. + Username string `json:"username,omitempty"` + + // Password for scraping metrics. + Password string `json:"password,omitempty"` + + // Custom user-assigned labels for Node and Service. + CustomLabels map[string]string `json:"custom_labels,omitempty"` + + // Skip connection check. + SkipConnectionCheck bool `json:"skip_connection_check,omitempty"` + + // Use TLS for database connections. + TLS bool `json:"tls,omitempty"` + + // Skip TLS certificate and hostname validation. + TLSSkipVerify bool `json:"tls_skip_verify,omitempty"` + + // MetricsMode defines desired metrics mode for agent, + // it can be pull, push or auto mode chosen by server. + // + // - METRICS_MODE_UNSPECIFIED: Auto + // Enum: ["METRICS_MODE_UNSPECIFIED","METRICS_MODE_PULL","METRICS_MODE_PUSH"] + MetricsMode *string `json:"metrics_mode,omitempty"` + + // Custom password for exporter endpoint /metrics. + AgentPassword string `json:"agent_password,omitempty"` +} + +// Validate validates this add service params body elasticache +func (o *AddServiceParamsBodyElasticache) Validate(formats strfmt.Registry) error { + var res []error + + if err := o.validateEngine(formats); err != nil { + res = append(res, err) + } + + if err := o.validateMetricsMode(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +var addServiceParamsBodyElasticacheTypeEnginePropEnum []any + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED","DISCOVER_ELASTI_CACHE_ENGINE_REDIS","DISCOVER_ELASTI_CACHE_ENGINE_VALKEY"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + addServiceParamsBodyElasticacheTypeEnginePropEnum = append(addServiceParamsBodyElasticacheTypeEnginePropEnum, v) + } +} + +const ( + + // AddServiceParamsBodyElasticacheEngineDISCOVERELASTICACHEENGINEUNSPECIFIED captures enum value "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED" + AddServiceParamsBodyElasticacheEngineDISCOVERELASTICACHEENGINEUNSPECIFIED string = "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED" + + // AddServiceParamsBodyElasticacheEngineDISCOVERELASTICACHEENGINEREDIS captures enum value "DISCOVER_ELASTI_CACHE_ENGINE_REDIS" + AddServiceParamsBodyElasticacheEngineDISCOVERELASTICACHEENGINEREDIS string = "DISCOVER_ELASTI_CACHE_ENGINE_REDIS" + + // AddServiceParamsBodyElasticacheEngineDISCOVERELASTICACHEENGINEVALKEY captures enum value "DISCOVER_ELASTI_CACHE_ENGINE_VALKEY" + AddServiceParamsBodyElasticacheEngineDISCOVERELASTICACHEENGINEVALKEY string = "DISCOVER_ELASTI_CACHE_ENGINE_VALKEY" +) + +// prop value enum +func (o *AddServiceParamsBodyElasticache) validateEngineEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, addServiceParamsBodyElasticacheTypeEnginePropEnum, true); err != nil { + return err + } + return nil +} + +func (o *AddServiceParamsBodyElasticache) validateEngine(formats strfmt.Registry) error { + if swag.IsZero(o.Engine) { // not required + return nil + } + + // value enum + if err := o.validateEngineEnum("body"+"."+"elasticache"+"."+"engine", "body", *o.Engine); err != nil { + return err + } + + return nil +} + +var addServiceParamsBodyElasticacheTypeMetricsModePropEnum []any + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["METRICS_MODE_UNSPECIFIED","METRICS_MODE_PULL","METRICS_MODE_PUSH"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + addServiceParamsBodyElasticacheTypeMetricsModePropEnum = append(addServiceParamsBodyElasticacheTypeMetricsModePropEnum, v) + } +} + +const ( + + // AddServiceParamsBodyElasticacheMetricsModeMETRICSMODEUNSPECIFIED captures enum value "METRICS_MODE_UNSPECIFIED" + AddServiceParamsBodyElasticacheMetricsModeMETRICSMODEUNSPECIFIED string = "METRICS_MODE_UNSPECIFIED" + + // AddServiceParamsBodyElasticacheMetricsModeMETRICSMODEPULL captures enum value "METRICS_MODE_PULL" + AddServiceParamsBodyElasticacheMetricsModeMETRICSMODEPULL string = "METRICS_MODE_PULL" + + // AddServiceParamsBodyElasticacheMetricsModeMETRICSMODEPUSH captures enum value "METRICS_MODE_PUSH" + AddServiceParamsBodyElasticacheMetricsModeMETRICSMODEPUSH string = "METRICS_MODE_PUSH" +) + +// prop value enum +func (o *AddServiceParamsBodyElasticache) validateMetricsModeEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, addServiceParamsBodyElasticacheTypeMetricsModePropEnum, true); err != nil { + return err + } + return nil +} + +func (o *AddServiceParamsBodyElasticache) validateMetricsMode(formats strfmt.Registry) error { + if swag.IsZero(o.MetricsMode) { // not required + return nil + } + + // value enum + if err := o.validateMetricsModeEnum("body"+"."+"elasticache"+"."+"metrics_mode", "body", *o.MetricsMode); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this add service params body elasticache based on context it is used +func (o *AddServiceParamsBodyElasticache) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *AddServiceParamsBodyElasticache) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *AddServiceParamsBodyElasticache) UnmarshalBinary(b []byte) error { + var res AddServiceParamsBodyElasticache + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + /* AddServiceParamsBodyExternal add service params body external swagger:model AddServiceParamsBodyExternal @@ -9549,7 +10479,7 @@ swagger:model AddServiceParamsBodyExternalAddNode */ type AddServiceParamsBodyExternalAddNode struct { // NodeType describes supported Node types. - // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"] + // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"] NodeType *string `json:"node_type,omitempty"` // Unique across all Nodes user-defined name. @@ -9598,7 +10528,7 @@ var addServiceParamsBodyExternalAddNodeTypeNodeTypePropEnum []any func init() { var res []string - if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -9625,6 +10555,9 @@ const ( // AddServiceParamsBodyExternalAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE captures enum value "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" AddServiceParamsBodyExternalAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE string = "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + + // AddServiceParamsBodyExternalAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE captures enum value "NODE_TYPE_REMOTE_ELASTICACHE_NODE" + AddServiceParamsBodyExternalAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE string = "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ) // prop value enum @@ -9883,7 +10816,7 @@ swagger:model AddServiceParamsBodyHaproxyAddNode */ type AddServiceParamsBodyHaproxyAddNode struct { // NodeType describes supported Node types. - // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"] + // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"] NodeType *string `json:"node_type,omitempty"` // Unique across all Nodes user-defined name. @@ -9932,7 +10865,7 @@ var addServiceParamsBodyHaproxyAddNodeTypeNodeTypePropEnum []any func init() { var res []string - if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -9959,6 +10892,9 @@ const ( // AddServiceParamsBodyHaproxyAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE captures enum value "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" AddServiceParamsBodyHaproxyAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE string = "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + + // AddServiceParamsBodyHaproxyAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE captures enum value "NODE_TYPE_REMOTE_ELASTICACHE_NODE" + AddServiceParamsBodyHaproxyAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE string = "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ) // prop value enum @@ -10341,7 +11277,7 @@ swagger:model AddServiceParamsBodyMongodbAddNode */ type AddServiceParamsBodyMongodbAddNode struct { // NodeType describes supported Node types. - // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"] + // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"] NodeType *string `json:"node_type,omitempty"` // Unique across all Nodes user-defined name. @@ -10390,7 +11326,7 @@ var addServiceParamsBodyMongodbAddNodeTypeNodeTypePropEnum []any func init() { var res []string - if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -10417,6 +11353,9 @@ const ( // AddServiceParamsBodyMongodbAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE captures enum value "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" AddServiceParamsBodyMongodbAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE string = "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + + // AddServiceParamsBodyMongodbAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE captures enum value "NODE_TYPE_REMOTE_ELASTICACHE_NODE" + AddServiceParamsBodyMongodbAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE string = "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ) // prop value enum @@ -10793,7 +11732,7 @@ swagger:model AddServiceParamsBodyMysqlAddNode */ type AddServiceParamsBodyMysqlAddNode struct { // NodeType describes supported Node types. - // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"] + // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"] NodeType *string `json:"node_type,omitempty"` // Unique across all Nodes user-defined name. @@ -10842,7 +11781,7 @@ var addServiceParamsBodyMysqlAddNodeTypeNodeTypePropEnum []any func init() { var res []string - if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -10869,6 +11808,9 @@ const ( // AddServiceParamsBodyMysqlAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE captures enum value "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" AddServiceParamsBodyMysqlAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE string = "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + + // AddServiceParamsBodyMysqlAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE captures enum value "NODE_TYPE_REMOTE_ELASTICACHE_NODE" + AddServiceParamsBodyMysqlAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE string = "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ) // prop value enum @@ -11241,7 +12183,7 @@ swagger:model AddServiceParamsBodyPostgresqlAddNode */ type AddServiceParamsBodyPostgresqlAddNode struct { // NodeType describes supported Node types. - // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"] + // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"] NodeType *string `json:"node_type,omitempty"` // Unique across all Nodes user-defined name. @@ -11290,7 +12232,7 @@ var addServiceParamsBodyPostgresqlAddNodeTypeNodeTypePropEnum []any func init() { var res []string - if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -11317,6 +12259,9 @@ const ( // AddServiceParamsBodyPostgresqlAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE captures enum value "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" AddServiceParamsBodyPostgresqlAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE string = "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + + // AddServiceParamsBodyPostgresqlAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE captures enum value "NODE_TYPE_REMOTE_ELASTICACHE_NODE" + AddServiceParamsBodyPostgresqlAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE string = "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ) // prop value enum @@ -11656,7 +12601,7 @@ swagger:model AddServiceParamsBodyProxysqlAddNode */ type AddServiceParamsBodyProxysqlAddNode struct { // NodeType describes supported Node types. - // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"] + // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"] NodeType *string `json:"node_type,omitempty"` // Unique across all Nodes user-defined name. @@ -11705,7 +12650,7 @@ var addServiceParamsBodyProxysqlAddNodeTypeNodeTypePropEnum []any func init() { var res []string - if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -11732,6 +12677,9 @@ const ( // AddServiceParamsBodyProxysqlAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE captures enum value "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" AddServiceParamsBodyProxysqlAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE string = "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + + // AddServiceParamsBodyProxysqlAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE captures enum value "NODE_TYPE_REMOTE_ELASTICACHE_NODE" + AddServiceParamsBodyProxysqlAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE string = "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ) // prop value enum @@ -12326,7 +13274,7 @@ swagger:model AddServiceParamsBodyValkeyAddNode */ type AddServiceParamsBodyValkeyAddNode struct { // NodeType describes supported Node types. - // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"] + // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"] NodeType *string `json:"node_type,omitempty"` // Unique across all Nodes user-defined name. @@ -12375,7 +13323,7 @@ var addServiceParamsBodyValkeyAddNodeTypeNodeTypePropEnum []any func init() { var res []string - if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -12402,6 +13350,9 @@ const ( // AddServiceParamsBodyValkeyAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE captures enum value "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" AddServiceParamsBodyValkeyAddNodeNodeTypeNODETYPEREMOTEAZUREDATABASENODE string = "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + + // AddServiceParamsBodyValkeyAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE captures enum value "NODE_TYPE_REMOTE_ELASTICACHE_NODE" + AddServiceParamsBodyValkeyAddNodeNodeTypeNODETYPEREMOTEELASTICACHENODE string = "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ) // prop value enum diff --git a/api/management/v1/json/client/management_service/discover_elasti_cache_parameters.go b/api/management/v1/json/client/management_service/discover_elasti_cache_parameters.go new file mode 100644 index 00000000000..d367e0c3c88 --- /dev/null +++ b/api/management/v1/json/client/management_service/discover_elasti_cache_parameters.go @@ -0,0 +1,141 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package management_service + +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" +) + +// NewDiscoverElastiCacheParams creates a new DiscoverElastiCacheParams 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 NewDiscoverElastiCacheParams() *DiscoverElastiCacheParams { + return &DiscoverElastiCacheParams{ + timeout: cr.DefaultTimeout, + } +} + +// NewDiscoverElastiCacheParamsWithTimeout creates a new DiscoverElastiCacheParams object +// with the ability to set a timeout on a request. +func NewDiscoverElastiCacheParamsWithTimeout(timeout time.Duration) *DiscoverElastiCacheParams { + return &DiscoverElastiCacheParams{ + timeout: timeout, + } +} + +// NewDiscoverElastiCacheParamsWithContext creates a new DiscoverElastiCacheParams object +// with the ability to set a context for a request. +func NewDiscoverElastiCacheParamsWithContext(ctx context.Context) *DiscoverElastiCacheParams { + return &DiscoverElastiCacheParams{ + Context: ctx, + } +} + +// NewDiscoverElastiCacheParamsWithHTTPClient creates a new DiscoverElastiCacheParams object +// with the ability to set a custom HTTPClient for a request. +func NewDiscoverElastiCacheParamsWithHTTPClient(client *http.Client) *DiscoverElastiCacheParams { + return &DiscoverElastiCacheParams{ + HTTPClient: client, + } +} + +/* +DiscoverElastiCacheParams contains all the parameters to send to the API endpoint + + for the discover elasti cache operation. + + Typically these are written to a http.Request. +*/ +type DiscoverElastiCacheParams struct { + // Body. + Body DiscoverElastiCacheBody + + timeout time.Duration + Context context.Context + HTTPClient *http.Client +} + +// WithDefaults hydrates default values in the discover elasti cache params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *DiscoverElastiCacheParams) WithDefaults() *DiscoverElastiCacheParams { + o.SetDefaults() + return o +} + +// SetDefaults hydrates default values in the discover elasti cache params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *DiscoverElastiCacheParams) SetDefaults() { + // no default values defined for this parameter +} + +// WithTimeout adds the timeout to the discover elasti cache params +func (o *DiscoverElastiCacheParams) WithTimeout(timeout time.Duration) *DiscoverElastiCacheParams { + o.SetTimeout(timeout) + return o +} + +// SetTimeout adds the timeout to the discover elasti cache params +func (o *DiscoverElastiCacheParams) SetTimeout(timeout time.Duration) { + o.timeout = timeout +} + +// WithContext adds the context to the discover elasti cache params +func (o *DiscoverElastiCacheParams) WithContext(ctx context.Context) *DiscoverElastiCacheParams { + o.SetContext(ctx) + return o +} + +// SetContext adds the context to the discover elasti cache params +func (o *DiscoverElastiCacheParams) SetContext(ctx context.Context) { + o.Context = ctx +} + +// WithHTTPClient adds the HTTPClient to the discover elasti cache params +func (o *DiscoverElastiCacheParams) WithHTTPClient(client *http.Client) *DiscoverElastiCacheParams { + o.SetHTTPClient(client) + return o +} + +// SetHTTPClient adds the HTTPClient to the discover elasti cache params +func (o *DiscoverElastiCacheParams) SetHTTPClient(client *http.Client) { + o.HTTPClient = client +} + +// WithBody adds the body to the discover elasti cache params +func (o *DiscoverElastiCacheParams) WithBody(body DiscoverElastiCacheBody) *DiscoverElastiCacheParams { + o.SetBody(body) + return o +} + +// SetBody adds the body to the discover elasti cache params +func (o *DiscoverElastiCacheParams) SetBody(body DiscoverElastiCacheBody) { + o.Body = body +} + +// WriteToRequest writes these params to a swagger request +func (o *DiscoverElastiCacheParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { + if err := r.SetTimeout(o.timeout); err != nil { + return err + } + var res []error + if err := r.SetBodyParam(o.Body); err != nil { + return err + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/api/management/v1/json/client/management_service/discover_elasti_cache_responses.go b/api/management/v1/json/client/management_service/discover_elasti_cache_responses.go new file mode 100644 index 00000000000..d59dbf4a149 --- /dev/null +++ b/api/management/v1/json/client/management_service/discover_elasti_cache_responses.go @@ -0,0 +1,684 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package management_service + +import ( + "context" + "encoding/json" + stderrors "errors" + "fmt" + "io" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// DiscoverElastiCacheReader is a Reader for the DiscoverElastiCache structure. +type DiscoverElastiCacheReader struct { + formats strfmt.Registry +} + +// ReadResponse reads a server response into the received o. +func (o *DiscoverElastiCacheReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (any, error) { + switch response.Code() { + case 200: + result := NewDiscoverElastiCacheOK() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return result, nil + default: + result := NewDiscoverElastiCacheDefault(response.Code()) + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + if response.Code()/100 == 2 { + return result, nil + } + return nil, result + } +} + +// NewDiscoverElastiCacheOK creates a DiscoverElastiCacheOK with default headers values +func NewDiscoverElastiCacheOK() *DiscoverElastiCacheOK { + return &DiscoverElastiCacheOK{} +} + +/* +DiscoverElastiCacheOK describes a response with status code 200, with default header values. + +A successful response. +*/ +type DiscoverElastiCacheOK struct { + Payload *DiscoverElastiCacheOKBody +} + +// IsSuccess returns true when this discover elasti cache Ok response has a 2xx status code +func (o *DiscoverElastiCacheOK) IsSuccess() bool { + return true +} + +// IsRedirect returns true when this discover elasti cache Ok response has a 3xx status code +func (o *DiscoverElastiCacheOK) IsRedirect() bool { + return false +} + +// IsClientError returns true when this discover elasti cache Ok response has a 4xx status code +func (o *DiscoverElastiCacheOK) IsClientError() bool { + return false +} + +// IsServerError returns true when this discover elasti cache Ok response has a 5xx status code +func (o *DiscoverElastiCacheOK) IsServerError() bool { + return false +} + +// IsCode returns true when this discover elasti cache Ok response a status code equal to that given +func (o *DiscoverElastiCacheOK) IsCode(code int) bool { + return code == 200 +} + +// Code gets the status code for the discover elasti cache Ok response +func (o *DiscoverElastiCacheOK) Code() int { + return 200 +} + +func (o *DiscoverElastiCacheOK) Error() string { + payload, _ := json.Marshal(o.Payload) + return fmt.Sprintf("[POST /v1/management/services:discoverElastiCache][%d] discoverElastiCacheOk %s", 200, payload) +} + +func (o *DiscoverElastiCacheOK) String() string { + payload, _ := json.Marshal(o.Payload) + return fmt.Sprintf("[POST /v1/management/services:discoverElastiCache][%d] discoverElastiCacheOk %s", 200, payload) +} + +func (o *DiscoverElastiCacheOK) GetPayload() *DiscoverElastiCacheOKBody { + return o.Payload +} + +func (o *DiscoverElastiCacheOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + o.Payload = new(DiscoverElastiCacheOKBody) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && !stderrors.Is(err, io.EOF) { + return err + } + + return nil +} + +// NewDiscoverElastiCacheDefault creates a DiscoverElastiCacheDefault with default headers values +func NewDiscoverElastiCacheDefault(code int) *DiscoverElastiCacheDefault { + return &DiscoverElastiCacheDefault{ + _statusCode: code, + } +} + +/* +DiscoverElastiCacheDefault describes a response with status code -1, with default header values. + +An unexpected error response. +*/ +type DiscoverElastiCacheDefault struct { + _statusCode int + + Payload *DiscoverElastiCacheDefaultBody +} + +// IsSuccess returns true when this discover elasti cache default response has a 2xx status code +func (o *DiscoverElastiCacheDefault) IsSuccess() bool { + return o._statusCode/100 == 2 +} + +// IsRedirect returns true when this discover elasti cache default response has a 3xx status code +func (o *DiscoverElastiCacheDefault) IsRedirect() bool { + return o._statusCode/100 == 3 +} + +// IsClientError returns true when this discover elasti cache default response has a 4xx status code +func (o *DiscoverElastiCacheDefault) IsClientError() bool { + return o._statusCode/100 == 4 +} + +// IsServerError returns true when this discover elasti cache default response has a 5xx status code +func (o *DiscoverElastiCacheDefault) IsServerError() bool { + return o._statusCode/100 == 5 +} + +// IsCode returns true when this discover elasti cache default response a status code equal to that given +func (o *DiscoverElastiCacheDefault) IsCode(code int) bool { + return o._statusCode == code +} + +// Code gets the status code for the discover elasti cache default response +func (o *DiscoverElastiCacheDefault) Code() int { + return o._statusCode +} + +func (o *DiscoverElastiCacheDefault) Error() string { + payload, _ := json.Marshal(o.Payload) + return fmt.Sprintf("[POST /v1/management/services:discoverElastiCache][%d] DiscoverElastiCache default %s", o._statusCode, payload) +} + +func (o *DiscoverElastiCacheDefault) String() string { + payload, _ := json.Marshal(o.Payload) + return fmt.Sprintf("[POST /v1/management/services:discoverElastiCache][%d] DiscoverElastiCache default %s", o._statusCode, payload) +} + +func (o *DiscoverElastiCacheDefault) GetPayload() *DiscoverElastiCacheDefaultBody { + return o.Payload +} + +func (o *DiscoverElastiCacheDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + o.Payload = new(DiscoverElastiCacheDefaultBody) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && !stderrors.Is(err, io.EOF) { + return err + } + + return nil +} + +/* +DiscoverElastiCacheBody discover elasti cache body +swagger:model DiscoverElastiCacheBody +*/ +type DiscoverElastiCacheBody struct { + // AWS Access key. Optional — if empty, the default credential chain is used. + AWSAccessKey string `json:"aws_access_key,omitempty"` + + // AWS Secret key. Optional. + AWSSecretKey string `json:"aws_secret_key,omitempty"` +} + +// Validate validates this discover elasti cache body +func (o *DiscoverElastiCacheBody) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this discover elasti cache body based on context it is used +func (o *DiscoverElastiCacheBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *DiscoverElastiCacheBody) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *DiscoverElastiCacheBody) UnmarshalBinary(b []byte) error { + var res DiscoverElastiCacheBody + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +DiscoverElastiCacheDefaultBody discover elasti cache default body +swagger:model DiscoverElastiCacheDefaultBody +*/ +type DiscoverElastiCacheDefaultBody struct { + // code + Code int32 `json:"code,omitempty"` + + // message + Message string `json:"message,omitempty"` + + // details + Details []*DiscoverElastiCacheDefaultBodyDetailsItems0 `json:"details"` +} + +// Validate validates this discover elasti cache default body +func (o *DiscoverElastiCacheDefaultBody) Validate(formats strfmt.Registry) error { + var res []error + + if err := o.validateDetails(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *DiscoverElastiCacheDefaultBody) validateDetails(formats strfmt.Registry) error { + if swag.IsZero(o.Details) { // not required + return nil + } + + for i := 0; i < len(o.Details); i++ { + if swag.IsZero(o.Details[i]) { // not required + continue + } + + if o.Details[i] != nil { + if err := o.Details[i].Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("DiscoverElastiCache default" + "." + "details" + "." + strconv.Itoa(i)) + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("DiscoverElastiCache default" + "." + "details" + "." + strconv.Itoa(i)) + } + + return err + } + } + + } + + return nil +} + +// ContextValidate validate this discover elasti cache default body based on the context it is used +func (o *DiscoverElastiCacheDefaultBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := o.contextValidateDetails(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *DiscoverElastiCacheDefaultBody) contextValidateDetails(ctx context.Context, formats strfmt.Registry) error { + for i := 0; i < len(o.Details); i++ { + if o.Details[i] != nil { + + if swag.IsZero(o.Details[i]) { // not required + return nil + } + + if err := o.Details[i].ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("DiscoverElastiCache default" + "." + "details" + "." + strconv.Itoa(i)) + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("DiscoverElastiCache default" + "." + "details" + "." + strconv.Itoa(i)) + } + + return err + } + } + } + + return nil +} + +// MarshalBinary interface implementation +func (o *DiscoverElastiCacheDefaultBody) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *DiscoverElastiCacheDefaultBody) UnmarshalBinary(b []byte) error { + var res DiscoverElastiCacheDefaultBody + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +DiscoverElastiCacheDefaultBodyDetailsItems0 discover elasti cache default body details items0 +swagger:model DiscoverElastiCacheDefaultBodyDetailsItems0 +*/ +type DiscoverElastiCacheDefaultBodyDetailsItems0 struct { + // at type + AtType string `json:"@type,omitempty"` + + // discover elasti cache default body details items0 + DiscoverElastiCacheDefaultBodyDetailsItems0 map[string]any `json:"-"` +} + +// UnmarshalJSON unmarshals this object with additional properties from JSON +func (o *DiscoverElastiCacheDefaultBodyDetailsItems0) UnmarshalJSON(data []byte) error { + // stage 1, bind the properties + var stage1 struct { + // at type + AtType string `json:"@type,omitempty"` + } + if err := json.Unmarshal(data, &stage1); err != nil { + return err + } + var rcv DiscoverElastiCacheDefaultBodyDetailsItems0 + + rcv.AtType = stage1.AtType + *o = rcv + + // stage 2, remove properties and add to map + stage2 := make(map[string]json.RawMessage) + if err := json.Unmarshal(data, &stage2); err != nil { + return err + } + + delete(stage2, "@type") + // stage 3, add additional properties values + if len(stage2) > 0 { + result := make(map[string]any) + for k, v := range stage2 { + var toadd any + if err := json.Unmarshal(v, &toadd); err != nil { + return err + } + result[k] = toadd + } + o.DiscoverElastiCacheDefaultBodyDetailsItems0 = result + } + + return nil +} + +// MarshalJSON marshals this object with additional properties into a JSON object +func (o DiscoverElastiCacheDefaultBodyDetailsItems0) MarshalJSON() ([]byte, error) { + var stage1 struct { + // at type + AtType string `json:"@type,omitempty"` + } + + stage1.AtType = o.AtType + + // make JSON object for known properties + props, err := json.Marshal(stage1) + if err != nil { + return nil, err + } + + if len(o.DiscoverElastiCacheDefaultBodyDetailsItems0) == 0 { // no additional properties + return props, nil + } + + // make JSON object for the additional properties + additional, err := json.Marshal(o.DiscoverElastiCacheDefaultBodyDetailsItems0) + if err != nil { + return nil, err + } + + if len(props) < 3 { // "{}": only additional properties + return additional, nil + } + + // concatenate the 2 objects + return swag.ConcatJSON(props, additional), nil +} + +// Validate validates this discover elasti cache default body details items0 +func (o *DiscoverElastiCacheDefaultBodyDetailsItems0) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this discover elasti cache default body details items0 based on context it is used +func (o *DiscoverElastiCacheDefaultBodyDetailsItems0) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *DiscoverElastiCacheDefaultBodyDetailsItems0) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *DiscoverElastiCacheDefaultBodyDetailsItems0) UnmarshalBinary(b []byte) error { + var res DiscoverElastiCacheDefaultBodyDetailsItems0 + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +DiscoverElastiCacheOKBody discover elasti cache OK body +swagger:model DiscoverElastiCacheOKBody +*/ +type DiscoverElastiCacheOKBody struct { + // elasticache instances + ElasticacheInstances []*DiscoverElastiCacheOKBodyElasticacheInstancesItems0 `json:"elasticache_instances"` +} + +// Validate validates this discover elasti cache OK body +func (o *DiscoverElastiCacheOKBody) Validate(formats strfmt.Registry) error { + var res []error + + if err := o.validateElasticacheInstances(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *DiscoverElastiCacheOKBody) validateElasticacheInstances(formats strfmt.Registry) error { + if swag.IsZero(o.ElasticacheInstances) { // not required + return nil + } + + for i := 0; i < len(o.ElasticacheInstances); i++ { + if swag.IsZero(o.ElasticacheInstances[i]) { // not required + continue + } + + if o.ElasticacheInstances[i] != nil { + if err := o.ElasticacheInstances[i].Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("discoverElastiCacheOk" + "." + "elasticache_instances" + "." + strconv.Itoa(i)) + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("discoverElastiCacheOk" + "." + "elasticache_instances" + "." + strconv.Itoa(i)) + } + + return err + } + } + + } + + return nil +} + +// ContextValidate validate this discover elasti cache OK body based on the context it is used +func (o *DiscoverElastiCacheOKBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := o.contextValidateElasticacheInstances(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *DiscoverElastiCacheOKBody) contextValidateElasticacheInstances(ctx context.Context, formats strfmt.Registry) error { + for i := 0; i < len(o.ElasticacheInstances); i++ { + if o.ElasticacheInstances[i] != nil { + + if swag.IsZero(o.ElasticacheInstances[i]) { // not required + return nil + } + + if err := o.ElasticacheInstances[i].ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("discoverElastiCacheOk" + "." + "elasticache_instances" + "." + strconv.Itoa(i)) + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("discoverElastiCacheOk" + "." + "elasticache_instances" + "." + strconv.Itoa(i)) + } + + return err + } + } + } + + return nil +} + +// MarshalBinary interface implementation +func (o *DiscoverElastiCacheOKBody) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *DiscoverElastiCacheOKBody) UnmarshalBinary(b []byte) error { + var res DiscoverElastiCacheOKBody + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +DiscoverElastiCacheOKBodyElasticacheInstancesItems0 DiscoverElastiCacheInstance models an ElastiCache replication group discovered by the API. +swagger:model DiscoverElastiCacheOKBodyElasticacheInstancesItems0 +*/ +type DiscoverElastiCacheOKBodyElasticacheInstancesItems0 struct { + // AWS region. + Region string `json:"region,omitempty"` + + // AWS availability zone. + Az string `json:"az,omitempty"` + + // Replication group identifier. + InstanceID string `json:"instance_id,omitempty"` + + // Cache node type (e.g. cache.r7g.large). + NodeModel string `json:"node_model,omitempty"` + + // Primary endpoint address. + Address string `json:"address,omitempty"` + + // Primary endpoint port. + Port int64 `json:"port,omitempty"` + + // DiscoverElastiCacheEngine describes supported ElastiCache engines. + // Enum: ["DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED","DISCOVER_ELASTI_CACHE_ENGINE_REDIS","DISCOVER_ELASTI_CACHE_ENGINE_VALKEY"] + Engine *string `json:"engine,omitempty"` + + // Engine version. + EngineVersion string `json:"engine_version,omitempty"` + + // Whether in-transit encryption is enabled. + TransitEncryptionEnabled bool `json:"transit_encryption_enabled,omitempty"` + + // Cluster name (replication group ID). + Cluster string `json:"cluster,omitempty"` +} + +// Validate validates this discover elasti cache OK body elasticache instances items0 +func (o *DiscoverElastiCacheOKBodyElasticacheInstancesItems0) Validate(formats strfmt.Registry) error { + var res []error + + if err := o.validateEngine(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +var discoverElastiCacheOkBodyElasticacheInstancesItems0TypeEnginePropEnum []any + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED","DISCOVER_ELASTI_CACHE_ENGINE_REDIS","DISCOVER_ELASTI_CACHE_ENGINE_VALKEY"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + discoverElastiCacheOkBodyElasticacheInstancesItems0TypeEnginePropEnum = append(discoverElastiCacheOkBodyElasticacheInstancesItems0TypeEnginePropEnum, v) + } +} + +const ( + + // DiscoverElastiCacheOKBodyElasticacheInstancesItems0EngineDISCOVERELASTICACHEENGINEUNSPECIFIED captures enum value "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED" + DiscoverElastiCacheOKBodyElasticacheInstancesItems0EngineDISCOVERELASTICACHEENGINEUNSPECIFIED string = "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED" + + // DiscoverElastiCacheOKBodyElasticacheInstancesItems0EngineDISCOVERELASTICACHEENGINEREDIS captures enum value "DISCOVER_ELASTI_CACHE_ENGINE_REDIS" + DiscoverElastiCacheOKBodyElasticacheInstancesItems0EngineDISCOVERELASTICACHEENGINEREDIS string = "DISCOVER_ELASTI_CACHE_ENGINE_REDIS" + + // DiscoverElastiCacheOKBodyElasticacheInstancesItems0EngineDISCOVERELASTICACHEENGINEVALKEY captures enum value "DISCOVER_ELASTI_CACHE_ENGINE_VALKEY" + DiscoverElastiCacheOKBodyElasticacheInstancesItems0EngineDISCOVERELASTICACHEENGINEVALKEY string = "DISCOVER_ELASTI_CACHE_ENGINE_VALKEY" +) + +// prop value enum +func (o *DiscoverElastiCacheOKBodyElasticacheInstancesItems0) validateEngineEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, discoverElastiCacheOkBodyElasticacheInstancesItems0TypeEnginePropEnum, true); err != nil { + return err + } + return nil +} + +func (o *DiscoverElastiCacheOKBodyElasticacheInstancesItems0) validateEngine(formats strfmt.Registry) error { + if swag.IsZero(o.Engine) { // not required + return nil + } + + // value enum + if err := o.validateEngineEnum("engine", "body", *o.Engine); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this discover elasti cache OK body elasticache instances items0 based on context it is used +func (o *DiscoverElastiCacheOKBodyElasticacheInstancesItems0) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *DiscoverElastiCacheOKBodyElasticacheInstancesItems0) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *DiscoverElastiCacheOKBodyElasticacheInstancesItems0) UnmarshalBinary(b []byte) error { + var res DiscoverElastiCacheOKBodyElasticacheInstancesItems0 + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} diff --git a/api/management/v1/json/client/management_service/management_service_client.go b/api/management/v1/json/client/management_service/management_service_client.go index 34aa5bb1708..665dde3b6b3 100644 --- a/api/management/v1/json/client/management_service/management_service_client.go +++ b/api/management/v1/json/client/management_service/management_service_client.go @@ -59,6 +59,8 @@ type ClientService interface { DiscoverAzureDatabase(params *DiscoverAzureDatabaseParams, opts ...ClientOption) (*DiscoverAzureDatabaseOK, error) + DiscoverElastiCache(params *DiscoverElastiCacheParams, opts ...ClientOption) (*DiscoverElastiCacheOK, error) + DiscoverRDS(params *DiscoverRDSParams, opts ...ClientOption) (*DiscoverRDSOK, error) GetNode(params *GetNodeParams, opts ...ClientOption) (*GetNodeOK, error) @@ -256,6 +258,50 @@ func (a *Client) DiscoverAzureDatabase(params *DiscoverAzureDatabaseParams, opts return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code()) } +/* +DiscoverElastiCache discovers elasti cache + +Discovers ElastiCache replication groups (Valkey/Redis). +*/ +func (a *Client) DiscoverElastiCache(params *DiscoverElastiCacheParams, opts ...ClientOption) (*DiscoverElastiCacheOK, error) { + // NOTE: parameters are not validated before sending + if params == nil { + params = NewDiscoverElastiCacheParams() + } + op := &runtime.ClientOperation{ + ID: "DiscoverElastiCache", + Method: "POST", + PathPattern: "/v1/management/services:discoverElastiCache", + ProducesMediaTypes: []string{"application/json"}, + ConsumesMediaTypes: []string{"application/json"}, + Schemes: []string{"http", "https"}, + Params: params, + Reader: &DiscoverElastiCacheReader{formats: a.formats}, + Context: params.Context, + Client: params.HTTPClient, + } + for _, opt := range opts { + opt(op) + } + result, err := a.transport.Submit(op) + if err != nil { + return nil, err + } + + // only one success response has to be checked + success, ok := result.(*DiscoverElastiCacheOK) + if ok { + return success, nil + } + + // unexpected success response. + // + // a default response is provided: fill this and return an error + unexpectedSuccess := result.(*DiscoverElastiCacheDefault) + + return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code()) +} + /* DiscoverRDS discovers RDS diff --git a/api/management/v1/json/client/management_service/register_node_responses.go b/api/management/v1/json/client/management_service/register_node_responses.go index d1568b72123..0d91d5d84e9 100644 --- a/api/management/v1/json/client/management_service/register_node_responses.go +++ b/api/management/v1/json/client/management_service/register_node_responses.go @@ -191,7 +191,7 @@ swagger:model RegisterNodeBody */ type RegisterNodeBody struct { // NodeType describes supported Node types. - // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"] + // Enum: ["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"] NodeType *string `json:"node_type,omitempty"` // A user-defined name unique across all Nodes. @@ -269,7 +269,7 @@ var registerNodeBodyTypeNodeTypePropEnum []any func init() { var res []string - if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["NODE_TYPE_UNSPECIFIED","NODE_TYPE_GENERIC_NODE","NODE_TYPE_CONTAINER_NODE","NODE_TYPE_REMOTE_NODE","NODE_TYPE_REMOTE_RDS_NODE","NODE_TYPE_REMOTE_AZURE_DATABASE_NODE","NODE_TYPE_REMOTE_ELASTICACHE_NODE"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -296,6 +296,9 @@ const ( // RegisterNodeBodyNodeTypeNODETYPEREMOTEAZUREDATABASENODE captures enum value "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" RegisterNodeBodyNodeTypeNODETYPEREMOTEAZUREDATABASENODE string = "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + + // RegisterNodeBodyNodeTypeNODETYPEREMOTEELASTICACHENODE captures enum value "NODE_TYPE_REMOTE_ELASTICACHE_NODE" + RegisterNodeBodyNodeTypeNODETYPEREMOTEELASTICACHENODE string = "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ) // prop value enum diff --git a/api/management/v1/json/v1.json b/api/management/v1/json/v1.json index 98e5b993d75..051a02a8481 100644 --- a/api/management/v1/json/v1.json +++ b/api/management/v1/json/v1.json @@ -626,7 +626,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "type": "string", "default": "NODE_TYPE_UNSPECIFIED", @@ -864,7 +865,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -2053,7 +2055,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -2322,7 +2325,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -2603,7 +2607,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -2869,7 +2874,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -3077,7 +3083,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -3242,7 +3249,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -3617,7 +3625,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -3804,6 +3813,133 @@ } }, "x-order": 7 + }, + "elasticache": { + "type": "object", + "properties": { + "region": { + "description": "AWS region.", + "type": "string", + "x-order": 0 + }, + "az": { + "description": "AWS availability zone.", + "type": "string", + "x-order": 1 + }, + "instance_id": { + "description": "Replication group identifier.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Cache node type.", + "type": "string", + "x-order": 3 + }, + "address": { + "description": "Primary endpoint address.", + "type": "string", + "x-order": 4 + }, + "port": { + "description": "Primary endpoint port.", + "type": "integer", + "format": "int64", + "x-order": 5 + }, + "engine": { + "description": "DiscoverElastiCacheEngine describes supported ElastiCache engines.", + "type": "string", + "default": "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + "enum": [ + "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + "DISCOVER_ELASTI_CACHE_ENGINE_REDIS", + "DISCOVER_ELASTI_CACHE_ENGINE_VALKEY" + ], + "x-order": 6 + }, + "pmm_agent_id": { + "description": "PMM Agent ID.", + "type": "string", + "x-order": 7 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name. Defaults to instance_id.", + "type": "string", + "x-order": 8 + }, + "service_name": { + "description": "Unique across all Services user-defined name. Defaults to instance_id.", + "type": "string", + "x-order": 9 + }, + "environment": { + "description": "Environment name.", + "type": "string", + "x-order": 10 + }, + "cluster": { + "description": "Cluster name.", + "type": "string", + "x-order": 11 + }, + "replication_set": { + "description": "Replication set name.", + "type": "string", + "x-order": 12 + }, + "username": { + "description": "Username for scraping metrics.", + "type": "string", + "x-order": 13 + }, + "password": { + "description": "Password for scraping metrics.", + "type": "string", + "x-order": 14 + }, + "custom_labels": { + "description": "Custom user-assigned labels for Node and Service.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 15 + }, + "skip_connection_check": { + "description": "Skip connection check.", + "type": "boolean", + "x-order": 16 + }, + "tls": { + "description": "Use TLS for database connections.", + "type": "boolean", + "x-order": 17 + }, + "tls_skip_verify": { + "description": "Skip TLS certificate and hostname validation.", + "type": "boolean", + "x-order": 18 + }, + "metrics_mode": { + "description": "MetricsMode defines desired metrics mode for agent,\nit can be pull, push or auto mode chosen by server.\n\n - METRICS_MODE_UNSPECIFIED: Auto", + "type": "string", + "default": "METRICS_MODE_UNSPECIFIED", + "enum": [ + "METRICS_MODE_UNSPECIFIED", + "METRICS_MODE_PULL", + "METRICS_MODE_PUSH" + ], + "x-order": 19 + }, + "agent_password": { + "description": "Custom password for exporter endpoint /metrics.", + "type": "string", + "x-order": 20 + } + }, + "x-order": 8 } } } @@ -6901,6 +7037,250 @@ } }, "x-order": 7 + }, + "elasticache": { + "type": "object", + "properties": { + "node": { + "description": "RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes.", + "type": "object", + "properties": { + "node_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 1 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 3 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 4 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 5 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 6 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 7 + } + }, + "x-order": 0 + }, + "valkey_service": { + "description": "ValkeyService represents a generic Valkey instance.", + "type": "object", + "properties": { + "service_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "service_name": { + "description": "Unique across all Services user-defined name.", + "type": "string", + "x-order": 1 + }, + "node_id": { + "description": "Node identifier where this instance runs.", + "type": "string", + "x-order": 2 + }, + "address": { + "description": "Access address (DNS name or IP).\nAddress (and port) or socket is required.", + "type": "string", + "x-order": 3 + }, + "port": { + "description": "Access port.\nPort is required when the address present.", + "type": "integer", + "format": "int64", + "x-order": 4 + }, + "socket": { + "description": "Access unix socket.\nAddress (and port) or socket is required.", + "type": "string", + "x-order": 5 + }, + "environment": { + "description": "Environment name.", + "type": "string", + "x-order": 6 + }, + "cluster": { + "description": "Cluster name.", + "type": "string", + "x-order": 7 + }, + "replication_set": { + "description": "Replication set name.", + "type": "string", + "x-order": 8 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 9 + }, + "version": { + "description": "Valkey version.", + "type": "string", + "x-order": 10 + } + }, + "x-order": 1 + }, + "valkey_exporter": { + "description": "ValkeyExporter runs on Generic or Container Node and exposes Valkey Service metrics.", + "type": "object", + "properties": { + "agent_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "pmm_agent_id": { + "description": "The pmm-agent identifier which runs this instance.", + "type": "string", + "x-order": 1 + }, + "disabled": { + "description": "Desired Agent status: enabled (false) or disabled (true).", + "type": "boolean", + "x-order": 2 + }, + "service_id": { + "description": "Service identifier.", + "type": "string", + "x-order": 3 + }, + "username": { + "description": "Valkey username for scraping metrics.", + "type": "string", + "x-order": 4 + }, + "tls": { + "description": "Use TLS for database connections.", + "type": "boolean", + "x-order": 5 + }, + "tls_skip_verify": { + "description": "Skip TLS certificate and hostname verification.", + "type": "boolean", + "x-order": 6 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 7 + }, + "push_metrics_enabled": { + "description": "True if exporter uses push metrics mode.", + "type": "boolean", + "x-order": 8 + }, + "disabled_collectors": { + "description": "List of disabled collector names.", + "type": "array", + "items": { + "type": "string" + }, + "x-order": 9 + }, + "status": { + "description": "AgentStatus represents actual Agent status.\n\n - AGENT_STATUS_STARTING: Agent is starting.\n - AGENT_STATUS_INITIALIZATION_ERROR: Agent encountered error when starting.\n - AGENT_STATUS_RUNNING: Agent is running.\n - AGENT_STATUS_WAITING: Agent encountered error and will be restarted automatically soon.\n - AGENT_STATUS_STOPPING: Agent is stopping.\n - AGENT_STATUS_DONE: Agent has been stopped or disabled.\n - AGENT_STATUS_UNKNOWN: Agent is not connected, we don't know anything about it's state.", + "type": "string", + "default": "AGENT_STATUS_UNSPECIFIED", + "enum": [ + "AGENT_STATUS_UNSPECIFIED", + "AGENT_STATUS_STARTING", + "AGENT_STATUS_INITIALIZATION_ERROR", + "AGENT_STATUS_RUNNING", + "AGENT_STATUS_WAITING", + "AGENT_STATUS_STOPPING", + "AGENT_STATUS_DONE", + "AGENT_STATUS_UNKNOWN" + ], + "x-order": 10 + }, + "listen_port": { + "description": "Listen port for scraping metrics.", + "type": "integer", + "format": "int64", + "x-order": 11 + }, + "process_exec_path": { + "description": "Path to exec process.", + "type": "string", + "x-order": 12 + }, + "expose_exporter": { + "type": "boolean", + "title": "Optionally expose the exporter process on all public interfaces", + "x-order": 13 + }, + "metrics_resolutions": { + "description": "MetricsResolutions represents Prometheus exporters metrics resolutions.", + "type": "object", + "properties": { + "hr": { + "description": "High resolution. In JSON should be represented as a string with number of seconds with `s` suffix.", + "type": "string", + "x-order": 0 + }, + "mr": { + "description": "Medium resolution. In JSON should be represented as a string with number of seconds with `s` suffix.", + "type": "string", + "x-order": 1 + }, + "lr": { + "description": "Low resolution. In JSON should be represented as a string with number of seconds with `s` suffix.", + "type": "string", + "x-order": 2 + } + }, + "x-order": 14 + }, + "connection_timeout": { + "description": "Connection timeout for exporter (if set).", + "type": "string", + "x-order": 15 + } + }, + "x-order": 2 + } + }, + "x-order": 8 } } } @@ -7368,6 +7748,146 @@ } } }, + "/v1/management/services:discoverElastiCache": { + "post": { + "description": "Discovers ElastiCache replication groups (Valkey/Redis).", + "tags": [ + "ManagementService" + ], + "summary": "Discover ElastiCache", + "operationId": "DiscoverElastiCache", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "properties": { + "aws_access_key": { + "description": "AWS Access key. Optional — if empty, the default credential chain is used.", + "type": "string", + "x-order": 0 + }, + "aws_secret_key": { + "description": "AWS Secret key. Optional.", + "type": "string", + "x-order": 1 + } + } + } + } + ], + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "type": "object", + "properties": { + "elasticache_instances": { + "type": "array", + "items": { + "description": "DiscoverElastiCacheInstance models an ElastiCache replication group discovered by the API.", + "type": "object", + "properties": { + "region": { + "description": "AWS region.", + "type": "string", + "x-order": 0 + }, + "az": { + "description": "AWS availability zone.", + "type": "string", + "x-order": 1 + }, + "instance_id": { + "description": "Replication group identifier.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Cache node type (e.g. cache.r7g.large).", + "type": "string", + "x-order": 3 + }, + "address": { + "description": "Primary endpoint address.", + "type": "string", + "x-order": 4 + }, + "port": { + "description": "Primary endpoint port.", + "type": "integer", + "format": "int64", + "x-order": 5 + }, + "engine": { + "description": "DiscoverElastiCacheEngine describes supported ElastiCache engines.", + "type": "string", + "default": "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + "enum": [ + "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + "DISCOVER_ELASTI_CACHE_ENGINE_REDIS", + "DISCOVER_ELASTI_CACHE_ENGINE_VALKEY" + ], + "x-order": 6 + }, + "engine_version": { + "description": "Engine version.", + "type": "string", + "x-order": 7 + }, + "transit_encryption_enabled": { + "description": "Whether in-transit encryption is enabled.", + "type": "boolean", + "x-order": 8 + }, + "cluster": { + "description": "Cluster name (replication group ID).", + "type": "string", + "x-order": 9 + } + } + }, + "x-order": 0 + } + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32", + "x-order": 0 + }, + "message": { + "type": "string", + "x-order": 1 + }, + "details": { + "type": "array", + "items": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "x-order": 0 + } + }, + "additionalProperties": {} + }, + "x-order": 2 + } + } + } + } + } + } + }, "/v1/management/services:discoverRDS": { "post": { "description": "Discovers RDS instances.", diff --git a/api/management/v1/service.pb.go b/api/management/v1/service.pb.go index cbad04b7f53..62116e57152 100644 --- a/api/management/v1/service.pb.go +++ b/api/management/v1/service.pb.go @@ -96,6 +96,7 @@ type AddServiceRequest struct { // *AddServiceRequest_External // *AddServiceRequest_Rds // *AddServiceRequest_Valkey + // *AddServiceRequest_Elasticache Service isAddServiceRequest_Service `protobuf_oneof:"service"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -210,6 +211,15 @@ func (x *AddServiceRequest) GetValkey() *AddValkeyServiceParams { return nil } +func (x *AddServiceRequest) GetElasticache() *AddElastiCacheServiceParams { + if x != nil { + if x, ok := x.Service.(*AddServiceRequest_Elasticache); ok { + return x.Elasticache + } + } + return nil +} + type isAddServiceRequest_Service interface { isAddServiceRequest_Service() } @@ -246,6 +256,10 @@ type AddServiceRequest_Valkey struct { Valkey *AddValkeyServiceParams `protobuf:"bytes,8,opt,name=valkey,proto3,oneof"` } +type AddServiceRequest_Elasticache struct { + Elasticache *AddElastiCacheServiceParams `protobuf:"bytes,9,opt,name=elasticache,proto3,oneof"` +} + func (*AddServiceRequest_Mysql) isAddServiceRequest_Service() {} func (*AddServiceRequest_Mongodb) isAddServiceRequest_Service() {} @@ -262,6 +276,8 @@ func (*AddServiceRequest_Rds) isAddServiceRequest_Service() {} func (*AddServiceRequest_Valkey) isAddServiceRequest_Service() {} +func (*AddServiceRequest_Elasticache) isAddServiceRequest_Service() {} + type AddServiceResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Types that are valid to be assigned to Service: @@ -274,6 +290,7 @@ type AddServiceResponse struct { // *AddServiceResponse_External // *AddServiceResponse_Rds // *AddServiceResponse_Valkey + // *AddServiceResponse_Elasticache Service isAddServiceResponse_Service `protobuf_oneof:"service"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -388,6 +405,15 @@ func (x *AddServiceResponse) GetValkey() *ValkeyServiceResult { return nil } +func (x *AddServiceResponse) GetElasticache() *ElastiCacheServiceResult { + if x != nil { + if x, ok := x.Service.(*AddServiceResponse_Elasticache); ok { + return x.Elasticache + } + } + return nil +} + type isAddServiceResponse_Service interface { isAddServiceResponse_Service() } @@ -424,6 +450,10 @@ type AddServiceResponse_Valkey struct { Valkey *ValkeyServiceResult `protobuf:"bytes,8,opt,name=valkey,proto3,oneof"` } +type AddServiceResponse_Elasticache struct { + Elasticache *ElastiCacheServiceResult `protobuf:"bytes,9,opt,name=elasticache,proto3,oneof"` +} + func (*AddServiceResponse_Mysql) isAddServiceResponse_Service() {} func (*AddServiceResponse_Mongodb) isAddServiceResponse_Service() {} @@ -440,6 +470,8 @@ func (*AddServiceResponse_Rds) isAddServiceResponse_Service() {} func (*AddServiceResponse_Valkey) isAddServiceResponse_Service() {} +func (*AddServiceResponse_Elasticache) isAddServiceResponse_Service() {} + type RemoveServiceRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Either a Service ID or a Service Name. @@ -852,7 +884,7 @@ var File_management_v1_service_proto protoreflect.FileDescriptor const file_management_v1_service_proto_rawDesc = "" + "\n" + - "\x1bmanagement/v1/service.proto\x12\rmanagement.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1binventory/v1/services.proto\x1a\x19management/v1/agent.proto\x1a\x1emanagement/v1/annotation.proto\x1a\x19management/v1/azure.proto\x1a\x1cmanagement/v1/external.proto\x1a\x1bmanagement/v1/haproxy.proto\x1a\x1bmanagement/v1/mongodb.proto\x1a\x19management/v1/mysql.proto\x1a\x18management/v1/node.proto\x1a\x1emanagement/v1/postgresql.proto\x1a\x1cmanagement/v1/proxysql.proto\x1a\x17management/v1/rds.proto\x1a\x1amanagement/v1/valkey.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\"\xb8\x04\n" + + "\x1bmanagement/v1/service.proto\x12\rmanagement.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1binventory/v1/services.proto\x1a\x19management/v1/agent.proto\x1a\x1emanagement/v1/annotation.proto\x1a\x19management/v1/azure.proto\x1a\x1fmanagement/v1/elasticache.proto\x1a\x1cmanagement/v1/external.proto\x1a\x1bmanagement/v1/haproxy.proto\x1a\x1bmanagement/v1/mongodb.proto\x1a\x19management/v1/mysql.proto\x1a\x18management/v1/node.proto\x1a\x1emanagement/v1/postgresql.proto\x1a\x1cmanagement/v1/proxysql.proto\x1a\x17management/v1/rds.proto\x1a\x1amanagement/v1/valkey.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\"\x88\x05\n" + "\x11AddServiceRequest\x12<\n" + "\x05mysql\x18\x01 \x01(\v2$.management.v1.AddMySQLServiceParamsH\x00R\x05mysql\x12B\n" + "\amongodb\x18\x02 \x01(\v2&.management.v1.AddMongoDBServiceParamsH\x00R\amongodb\x12K\n" + @@ -863,8 +895,9 @@ const file_management_v1_service_proto_rawDesc = "" + "\ahaproxy\x18\x05 \x01(\v2&.management.v1.AddHAProxyServiceParamsH\x00R\ahaproxy\x12E\n" + "\bexternal\x18\x06 \x01(\v2'.management.v1.AddExternalServiceParamsH\x00R\bexternal\x126\n" + "\x03rds\x18\a \x01(\v2\".management.v1.AddRDSServiceParamsH\x00R\x03rds\x12?\n" + - "\x06valkey\x18\b \x01(\v2%.management.v1.AddValkeyServiceParamsH\x00R\x06valkeyB\t\n" + - "\aservice\"\xa1\x04\n" + + "\x06valkey\x18\b \x01(\v2%.management.v1.AddValkeyServiceParamsH\x00R\x06valkey\x12N\n" + + "\velasticache\x18\t \x01(\v2*.management.v1.AddElastiCacheServiceParamsH\x00R\velasticacheB\t\n" + + "\aservice\"\xee\x04\n" + "\x12AddServiceResponse\x129\n" + "\x05mysql\x18\x01 \x01(\v2!.management.v1.MySQLServiceResultH\x00R\x05mysql\x12?\n" + "\amongodb\x18\x02 \x01(\v2#.management.v1.MongoDBServiceResultH\x00R\amongodb\x12H\n" + @@ -875,7 +908,8 @@ const file_management_v1_service_proto_rawDesc = "" + "\ahaproxy\x18\x05 \x01(\v2#.management.v1.HAProxyServiceResultH\x00R\ahaproxy\x12B\n" + "\bexternal\x18\x06 \x01(\v2$.management.v1.ExternalServiceResultH\x00R\bexternal\x123\n" + "\x03rds\x18\a \x01(\v2\x1f.management.v1.RDSServiceResultH\x00R\x03rds\x12<\n" + - "\x06valkey\x18\b \x01(\v2\".management.v1.ValkeyServiceResultH\x00R\x06valkeyB\t\n" + + "\x06valkey\x18\b \x01(\v2\".management.v1.ValkeyServiceResultH\x00R\x06valkey\x12K\n" + + "\velasticache\x18\t \x01(\v2'.management.v1.ElastiCacheServiceResultH\x00R\velasticacheB\t\n" + "\aservice\"s\n" + "\x14RemoveServiceRequest\x12\x1d\n" + "\n" + @@ -919,7 +953,7 @@ const file_management_v1_service_proto_rawDesc = "" + "\fservice_type\x18\x02 \x01(\x0e2\x19.inventory.v1.ServiceTypeR\vserviceType\x12%\n" + "\x0eexternal_group\x18\x03 \x01(\tR\rexternalGroup\"S\n" + "\x14ListServicesResponse\x12;\n" + - "\bservices\x18\x01 \x03(\v2\x1f.management.v1.UniversalServiceR\bservices2\xa2\x13\n" + + "\bservices\x18\x01 \x03(\v2\x1f.management.v1.UniversalServiceR\bservices2\x9d\x15\n" + "\x11ManagementService\x12\xac\x01\n" + "\rAddAnnotation\x12#.management.v1.AddAnnotationRequest\x1a$.management.v1.AddAnnotationResponse\"P\x92A(\x12\x11Add an Annotation\x1a\x13Adds an annotation.\x82\xd3\xe4\x93\x02\x1f:\x01*\"\x1a/v1/management/annotations\x12\x9b\x01\n" + "\n" + @@ -935,7 +969,8 @@ const file_management_v1_service_proto_rawDesc = "" + "\fListServices\x12\".management.v1.ListServicesRequest\x1a#.management.v1.ListServicesResponse\"W\x92A5\x12\rList Services\x1a$Returns a filtered list of Services.\x82\xd3\xe4\x93\x02\x19\x12\x17/v1/management/services\x12\xaf\x01\n" + "\vDiscoverRDS\x12!.management.v1.DiscoverRDSRequest\x1a\".management.v1.DiscoverRDSResponse\"Y\x92A(\x12\fDiscover RDS\x1a\x18Discovers RDS instances.\x82\xd3\xe4\x93\x02(:\x01*\"#/v1/management/services:discoverRDS\x12\x8f\x02\n" + "\x15DiscoverAzureDatabase\x12+.management.v1.DiscoverAzureDatabaseRequest\x1a,.management.v1.DiscoverAzureDatabaseResponse\"\x9a\x01\x92Ag\x12\x17Discover Azure Database\x1aLDiscovers Azure Database for MySQL, MariaDB and PostgreSQL Server instances.\x82\xd3\xe4\x93\x02*:\x01*\"%/v1/management/services:discoverAzure\x12\xc6\x01\n" + - "\x10AddAzureDatabase\x12&.management.v1.AddAzureDatabaseRequest\x1a'.management.v1.AddAzureDatabaseResponse\"a\x92A6\x12\x12Add Azure Database\x1a Adds an Azure Database instance.\x82\xd3\xe4\x93\x02\":\x01*\"\x1d/v1/management/services/azure\x12\xc7\x01\n" + + "\x10AddAzureDatabase\x12&.management.v1.AddAzureDatabaseRequest\x1a'.management.v1.AddAzureDatabaseResponse\"a\x92A6\x12\x12Add Azure Database\x1a Adds an Azure Database instance.\x82\xd3\xe4\x93\x02\":\x01*\"\x1d/v1/management/services/azure\x12\xf8\x01\n" + + "\x13DiscoverElastiCache\x12).management.v1.DiscoverElastiCacheRequest\x1a*.management.v1.DiscoverElastiCacheResponse\"\x89\x01\x92AP\x12\x14Discover ElastiCache\x1a8Discovers ElastiCache replication groups (Valkey/Redis).\x82\xd3\xe4\x93\x020:\x01*\"+/v1/management/services:discoverElastiCache\x12\xc7\x01\n" + "\rRemoveService\x12#.management.v1.RemoveServiceRequest\x1a$.management.v1.RemoveServiceResponse\"k\x92A<\x12\x10Remove a Service\x1a(Removes a Service along with its Agents.\x82\xd3\xe4\x93\x02&*$/v1/management/services/{service_id}B\xad\x01\n" + "\x11com.management.v1B\fServiceProtoP\x01Z5github.com/percona/pmm/api/management/v1;managementv1\xa2\x02\x03MXX\xaa\x02\rManagement.V1\xca\x02\rManagement\\V1\xe2\x02\x19Management\\V1\\GPBMetadata\xea\x02\x0eManagement::V1b\x06proto3" @@ -972,37 +1007,41 @@ var ( (*AddExternalServiceParams)(nil), // 14: management.v1.AddExternalServiceParams (*AddRDSServiceParams)(nil), // 15: management.v1.AddRDSServiceParams (*AddValkeyServiceParams)(nil), // 16: management.v1.AddValkeyServiceParams - (*MySQLServiceResult)(nil), // 17: management.v1.MySQLServiceResult - (*MongoDBServiceResult)(nil), // 18: management.v1.MongoDBServiceResult - (*PostgreSQLServiceResult)(nil), // 19: management.v1.PostgreSQLServiceResult - (*ProxySQLServiceResult)(nil), // 20: management.v1.ProxySQLServiceResult - (*HAProxyServiceResult)(nil), // 21: management.v1.HAProxyServiceResult - (*ExternalServiceResult)(nil), // 22: management.v1.ExternalServiceResult - (*RDSServiceResult)(nil), // 23: management.v1.RDSServiceResult - (*ValkeyServiceResult)(nil), // 24: management.v1.ValkeyServiceResult - v1.ServiceType(0), // 25: inventory.v1.ServiceType - (*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp - (*UniversalAgent)(nil), // 27: management.v1.UniversalAgent - (*AddAnnotationRequest)(nil), // 28: management.v1.AddAnnotationRequest - (*ListAgentsRequest)(nil), // 29: management.v1.ListAgentsRequest - (*ListAgentVersionsRequest)(nil), // 30: management.v1.ListAgentVersionsRequest - (*RegisterNodeRequest)(nil), // 31: management.v1.RegisterNodeRequest - (*UnregisterNodeRequest)(nil), // 32: management.v1.UnregisterNodeRequest - (*ListNodesRequest)(nil), // 33: management.v1.ListNodesRequest - (*GetNodeRequest)(nil), // 34: management.v1.GetNodeRequest - (*DiscoverRDSRequest)(nil), // 35: management.v1.DiscoverRDSRequest - (*DiscoverAzureDatabaseRequest)(nil), // 36: management.v1.DiscoverAzureDatabaseRequest - (*AddAzureDatabaseRequest)(nil), // 37: management.v1.AddAzureDatabaseRequest - (*AddAnnotationResponse)(nil), // 38: management.v1.AddAnnotationResponse - (*ListAgentsResponse)(nil), // 39: management.v1.ListAgentsResponse - (*ListAgentVersionsResponse)(nil), // 40: management.v1.ListAgentVersionsResponse - (*RegisterNodeResponse)(nil), // 41: management.v1.RegisterNodeResponse - (*UnregisterNodeResponse)(nil), // 42: management.v1.UnregisterNodeResponse - (*ListNodesResponse)(nil), // 43: management.v1.ListNodesResponse - (*GetNodeResponse)(nil), // 44: management.v1.GetNodeResponse - (*DiscoverRDSResponse)(nil), // 45: management.v1.DiscoverRDSResponse - (*DiscoverAzureDatabaseResponse)(nil), // 46: management.v1.DiscoverAzureDatabaseResponse - (*AddAzureDatabaseResponse)(nil), // 47: management.v1.AddAzureDatabaseResponse + (*AddElastiCacheServiceParams)(nil), // 17: management.v1.AddElastiCacheServiceParams + (*MySQLServiceResult)(nil), // 18: management.v1.MySQLServiceResult + (*MongoDBServiceResult)(nil), // 19: management.v1.MongoDBServiceResult + (*PostgreSQLServiceResult)(nil), // 20: management.v1.PostgreSQLServiceResult + (*ProxySQLServiceResult)(nil), // 21: management.v1.ProxySQLServiceResult + (*HAProxyServiceResult)(nil), // 22: management.v1.HAProxyServiceResult + (*ExternalServiceResult)(nil), // 23: management.v1.ExternalServiceResult + (*RDSServiceResult)(nil), // 24: management.v1.RDSServiceResult + (*ValkeyServiceResult)(nil), // 25: management.v1.ValkeyServiceResult + (*ElastiCacheServiceResult)(nil), // 26: management.v1.ElastiCacheServiceResult + v1.ServiceType(0), // 27: inventory.v1.ServiceType + (*timestamppb.Timestamp)(nil), // 28: google.protobuf.Timestamp + (*UniversalAgent)(nil), // 29: management.v1.UniversalAgent + (*AddAnnotationRequest)(nil), // 30: management.v1.AddAnnotationRequest + (*ListAgentsRequest)(nil), // 31: management.v1.ListAgentsRequest + (*ListAgentVersionsRequest)(nil), // 32: management.v1.ListAgentVersionsRequest + (*RegisterNodeRequest)(nil), // 33: management.v1.RegisterNodeRequest + (*UnregisterNodeRequest)(nil), // 34: management.v1.UnregisterNodeRequest + (*ListNodesRequest)(nil), // 35: management.v1.ListNodesRequest + (*GetNodeRequest)(nil), // 36: management.v1.GetNodeRequest + (*DiscoverRDSRequest)(nil), // 37: management.v1.DiscoverRDSRequest + (*DiscoverAzureDatabaseRequest)(nil), // 38: management.v1.DiscoverAzureDatabaseRequest + (*AddAzureDatabaseRequest)(nil), // 39: management.v1.AddAzureDatabaseRequest + (*DiscoverElastiCacheRequest)(nil), // 40: management.v1.DiscoverElastiCacheRequest + (*AddAnnotationResponse)(nil), // 41: management.v1.AddAnnotationResponse + (*ListAgentsResponse)(nil), // 42: management.v1.ListAgentsResponse + (*ListAgentVersionsResponse)(nil), // 43: management.v1.ListAgentVersionsResponse + (*RegisterNodeResponse)(nil), // 44: management.v1.RegisterNodeResponse + (*UnregisterNodeResponse)(nil), // 45: management.v1.UnregisterNodeResponse + (*ListNodesResponse)(nil), // 46: management.v1.ListNodesResponse + (*GetNodeResponse)(nil), // 47: management.v1.GetNodeResponse + (*DiscoverRDSResponse)(nil), // 48: management.v1.DiscoverRDSResponse + (*DiscoverAzureDatabaseResponse)(nil), // 49: management.v1.DiscoverAzureDatabaseResponse + (*AddAzureDatabaseResponse)(nil), // 50: management.v1.AddAzureDatabaseResponse + (*DiscoverElastiCacheResponse)(nil), // 51: management.v1.DiscoverElastiCacheResponse } ) @@ -1015,53 +1054,57 @@ var file_management_v1_service_proto_depIdxs = []int32{ 14, // 5: management.v1.AddServiceRequest.external:type_name -> management.v1.AddExternalServiceParams 15, // 6: management.v1.AddServiceRequest.rds:type_name -> management.v1.AddRDSServiceParams 16, // 7: management.v1.AddServiceRequest.valkey:type_name -> management.v1.AddValkeyServiceParams - 17, // 8: management.v1.AddServiceResponse.mysql:type_name -> management.v1.MySQLServiceResult - 18, // 9: management.v1.AddServiceResponse.mongodb:type_name -> management.v1.MongoDBServiceResult - 19, // 10: management.v1.AddServiceResponse.postgresql:type_name -> management.v1.PostgreSQLServiceResult - 20, // 11: management.v1.AddServiceResponse.proxysql:type_name -> management.v1.ProxySQLServiceResult - 21, // 12: management.v1.AddServiceResponse.haproxy:type_name -> management.v1.HAProxyServiceResult - 22, // 13: management.v1.AddServiceResponse.external:type_name -> management.v1.ExternalServiceResult - 23, // 14: management.v1.AddServiceResponse.rds:type_name -> management.v1.RDSServiceResult - 24, // 15: management.v1.AddServiceResponse.valkey:type_name -> management.v1.ValkeyServiceResult - 25, // 16: management.v1.RemoveServiceRequest.service_type:type_name -> inventory.v1.ServiceType - 8, // 17: management.v1.UniversalService.custom_labels:type_name -> management.v1.UniversalService.CustomLabelsEntry - 26, // 18: management.v1.UniversalService.created_at:type_name -> google.protobuf.Timestamp - 26, // 19: management.v1.UniversalService.updated_at:type_name -> google.protobuf.Timestamp - 27, // 20: management.v1.UniversalService.agents:type_name -> management.v1.UniversalAgent - 0, // 21: management.v1.UniversalService.status:type_name -> management.v1.UniversalService.Status - 25, // 22: management.v1.ListServicesRequest.service_type:type_name -> inventory.v1.ServiceType - 5, // 23: management.v1.ListServicesResponse.services:type_name -> management.v1.UniversalService - 28, // 24: management.v1.ManagementService.AddAnnotation:input_type -> management.v1.AddAnnotationRequest - 29, // 25: management.v1.ManagementService.ListAgents:input_type -> management.v1.ListAgentsRequest - 30, // 26: management.v1.ManagementService.ListAgentVersions:input_type -> management.v1.ListAgentVersionsRequest - 31, // 27: management.v1.ManagementService.RegisterNode:input_type -> management.v1.RegisterNodeRequest - 32, // 28: management.v1.ManagementService.UnregisterNode:input_type -> management.v1.UnregisterNodeRequest - 33, // 29: management.v1.ManagementService.ListNodes:input_type -> management.v1.ListNodesRequest - 34, // 30: management.v1.ManagementService.GetNode:input_type -> management.v1.GetNodeRequest - 1, // 31: management.v1.ManagementService.AddService:input_type -> management.v1.AddServiceRequest - 6, // 32: management.v1.ManagementService.ListServices:input_type -> management.v1.ListServicesRequest - 35, // 33: management.v1.ManagementService.DiscoverRDS:input_type -> management.v1.DiscoverRDSRequest - 36, // 34: management.v1.ManagementService.DiscoverAzureDatabase:input_type -> management.v1.DiscoverAzureDatabaseRequest - 37, // 35: management.v1.ManagementService.AddAzureDatabase:input_type -> management.v1.AddAzureDatabaseRequest - 3, // 36: management.v1.ManagementService.RemoveService:input_type -> management.v1.RemoveServiceRequest - 38, // 37: management.v1.ManagementService.AddAnnotation:output_type -> management.v1.AddAnnotationResponse - 39, // 38: management.v1.ManagementService.ListAgents:output_type -> management.v1.ListAgentsResponse - 40, // 39: management.v1.ManagementService.ListAgentVersions:output_type -> management.v1.ListAgentVersionsResponse - 41, // 40: management.v1.ManagementService.RegisterNode:output_type -> management.v1.RegisterNodeResponse - 42, // 41: management.v1.ManagementService.UnregisterNode:output_type -> management.v1.UnregisterNodeResponse - 43, // 42: management.v1.ManagementService.ListNodes:output_type -> management.v1.ListNodesResponse - 44, // 43: management.v1.ManagementService.GetNode:output_type -> management.v1.GetNodeResponse - 2, // 44: management.v1.ManagementService.AddService:output_type -> management.v1.AddServiceResponse - 7, // 45: management.v1.ManagementService.ListServices:output_type -> management.v1.ListServicesResponse - 45, // 46: management.v1.ManagementService.DiscoverRDS:output_type -> management.v1.DiscoverRDSResponse - 46, // 47: management.v1.ManagementService.DiscoverAzureDatabase:output_type -> management.v1.DiscoverAzureDatabaseResponse - 47, // 48: management.v1.ManagementService.AddAzureDatabase:output_type -> management.v1.AddAzureDatabaseResponse - 4, // 49: management.v1.ManagementService.RemoveService:output_type -> management.v1.RemoveServiceResponse - 37, // [37:50] is the sub-list for method output_type - 24, // [24:37] is the sub-list for method input_type - 24, // [24:24] is the sub-list for extension type_name - 24, // [24:24] is the sub-list for extension extendee - 0, // [0:24] is the sub-list for field type_name + 17, // 8: management.v1.AddServiceRequest.elasticache:type_name -> management.v1.AddElastiCacheServiceParams + 18, // 9: management.v1.AddServiceResponse.mysql:type_name -> management.v1.MySQLServiceResult + 19, // 10: management.v1.AddServiceResponse.mongodb:type_name -> management.v1.MongoDBServiceResult + 20, // 11: management.v1.AddServiceResponse.postgresql:type_name -> management.v1.PostgreSQLServiceResult + 21, // 12: management.v1.AddServiceResponse.proxysql:type_name -> management.v1.ProxySQLServiceResult + 22, // 13: management.v1.AddServiceResponse.haproxy:type_name -> management.v1.HAProxyServiceResult + 23, // 14: management.v1.AddServiceResponse.external:type_name -> management.v1.ExternalServiceResult + 24, // 15: management.v1.AddServiceResponse.rds:type_name -> management.v1.RDSServiceResult + 25, // 16: management.v1.AddServiceResponse.valkey:type_name -> management.v1.ValkeyServiceResult + 26, // 17: management.v1.AddServiceResponse.elasticache:type_name -> management.v1.ElastiCacheServiceResult + 27, // 18: management.v1.RemoveServiceRequest.service_type:type_name -> inventory.v1.ServiceType + 8, // 19: management.v1.UniversalService.custom_labels:type_name -> management.v1.UniversalService.CustomLabelsEntry + 28, // 20: management.v1.UniversalService.created_at:type_name -> google.protobuf.Timestamp + 28, // 21: management.v1.UniversalService.updated_at:type_name -> google.protobuf.Timestamp + 29, // 22: management.v1.UniversalService.agents:type_name -> management.v1.UniversalAgent + 0, // 23: management.v1.UniversalService.status:type_name -> management.v1.UniversalService.Status + 27, // 24: management.v1.ListServicesRequest.service_type:type_name -> inventory.v1.ServiceType + 5, // 25: management.v1.ListServicesResponse.services:type_name -> management.v1.UniversalService + 30, // 26: management.v1.ManagementService.AddAnnotation:input_type -> management.v1.AddAnnotationRequest + 31, // 27: management.v1.ManagementService.ListAgents:input_type -> management.v1.ListAgentsRequest + 32, // 28: management.v1.ManagementService.ListAgentVersions:input_type -> management.v1.ListAgentVersionsRequest + 33, // 29: management.v1.ManagementService.RegisterNode:input_type -> management.v1.RegisterNodeRequest + 34, // 30: management.v1.ManagementService.UnregisterNode:input_type -> management.v1.UnregisterNodeRequest + 35, // 31: management.v1.ManagementService.ListNodes:input_type -> management.v1.ListNodesRequest + 36, // 32: management.v1.ManagementService.GetNode:input_type -> management.v1.GetNodeRequest + 1, // 33: management.v1.ManagementService.AddService:input_type -> management.v1.AddServiceRequest + 6, // 34: management.v1.ManagementService.ListServices:input_type -> management.v1.ListServicesRequest + 37, // 35: management.v1.ManagementService.DiscoverRDS:input_type -> management.v1.DiscoverRDSRequest + 38, // 36: management.v1.ManagementService.DiscoverAzureDatabase:input_type -> management.v1.DiscoverAzureDatabaseRequest + 39, // 37: management.v1.ManagementService.AddAzureDatabase:input_type -> management.v1.AddAzureDatabaseRequest + 40, // 38: management.v1.ManagementService.DiscoverElastiCache:input_type -> management.v1.DiscoverElastiCacheRequest + 3, // 39: management.v1.ManagementService.RemoveService:input_type -> management.v1.RemoveServiceRequest + 41, // 40: management.v1.ManagementService.AddAnnotation:output_type -> management.v1.AddAnnotationResponse + 42, // 41: management.v1.ManagementService.ListAgents:output_type -> management.v1.ListAgentsResponse + 43, // 42: management.v1.ManagementService.ListAgentVersions:output_type -> management.v1.ListAgentVersionsResponse + 44, // 43: management.v1.ManagementService.RegisterNode:output_type -> management.v1.RegisterNodeResponse + 45, // 44: management.v1.ManagementService.UnregisterNode:output_type -> management.v1.UnregisterNodeResponse + 46, // 45: management.v1.ManagementService.ListNodes:output_type -> management.v1.ListNodesResponse + 47, // 46: management.v1.ManagementService.GetNode:output_type -> management.v1.GetNodeResponse + 2, // 47: management.v1.ManagementService.AddService:output_type -> management.v1.AddServiceResponse + 7, // 48: management.v1.ManagementService.ListServices:output_type -> management.v1.ListServicesResponse + 48, // 49: management.v1.ManagementService.DiscoverRDS:output_type -> management.v1.DiscoverRDSResponse + 49, // 50: management.v1.ManagementService.DiscoverAzureDatabase:output_type -> management.v1.DiscoverAzureDatabaseResponse + 50, // 51: management.v1.ManagementService.AddAzureDatabase:output_type -> management.v1.AddAzureDatabaseResponse + 51, // 52: management.v1.ManagementService.DiscoverElastiCache:output_type -> management.v1.DiscoverElastiCacheResponse + 4, // 53: management.v1.ManagementService.RemoveService:output_type -> management.v1.RemoveServiceResponse + 40, // [40:54] is the sub-list for method output_type + 26, // [26:40] is the sub-list for method input_type + 26, // [26:26] is the sub-list for extension type_name + 26, // [26:26] is the sub-list for extension extendee + 0, // [0:26] is the sub-list for field type_name } func init() { file_management_v1_service_proto_init() } @@ -1072,6 +1115,7 @@ func file_management_v1_service_proto_init() { file_management_v1_agent_proto_init() file_management_v1_annotation_proto_init() file_management_v1_azure_proto_init() + file_management_v1_elasticache_proto_init() file_management_v1_external_proto_init() file_management_v1_haproxy_proto_init() file_management_v1_mongodb_proto_init() @@ -1090,6 +1134,7 @@ func file_management_v1_service_proto_init() { (*AddServiceRequest_External)(nil), (*AddServiceRequest_Rds)(nil), (*AddServiceRequest_Valkey)(nil), + (*AddServiceRequest_Elasticache)(nil), } file_management_v1_service_proto_msgTypes[1].OneofWrappers = []any{ (*AddServiceResponse_Mysql)(nil), @@ -1100,6 +1145,7 @@ func file_management_v1_service_proto_init() { (*AddServiceResponse_External)(nil), (*AddServiceResponse_Rds)(nil), (*AddServiceResponse_Valkey)(nil), + (*AddServiceResponse_Elasticache)(nil), } type x struct{} out := protoimpl.TypeBuilder{ diff --git a/api/management/v1/service.pb.gw.go b/api/management/v1/service.pb.gw.go index 18c78ee4db1..32f6c5a7fed 100644 --- a/api/management/v1/service.pb.gw.go +++ b/api/management/v1/service.pb.gw.go @@ -415,6 +415,33 @@ func local_request_ManagementService_AddAzureDatabase_0(ctx context.Context, mar return msg, metadata, err } +func request_ManagementService_DiscoverElastiCache_0(ctx context.Context, marshaler runtime.Marshaler, client ManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq DiscoverElastiCacheRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.DiscoverElastiCache(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_ManagementService_DiscoverElastiCache_0(ctx context.Context, marshaler runtime.Marshaler, server ManagementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq DiscoverElastiCacheRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.DiscoverElastiCache(ctx, &protoReq) + return msg, metadata, err +} + var filter_ManagementService_RemoveService_0 = &utilities.DoubleArray{Encoding: map[string]int{"service_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} func request_ManagementService_RemoveService_0(ctx context.Context, marshaler runtime.Marshaler, client ManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { @@ -714,6 +741,26 @@ func RegisterManagementServiceHandlerServer(ctx context.Context, mux *runtime.Se } forward_ManagementService_AddAzureDatabase_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodPost, pattern_ManagementService_DiscoverElastiCache_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/management.v1.ManagementService/DiscoverElastiCache", runtime.WithHTTPPathPattern("/v1/management/services:discoverElastiCache")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_ManagementService_DiscoverElastiCache_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_ManagementService_DiscoverElastiCache_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) mux.Handle(http.MethodDelete, pattern_ManagementService_RemoveService_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -978,6 +1025,23 @@ func RegisterManagementServiceHandlerClient(ctx context.Context, mux *runtime.Se } forward_ManagementService_AddAzureDatabase_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodPost, pattern_ManagementService_DiscoverElastiCache_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/management.v1.ManagementService/DiscoverElastiCache", runtime.WithHTTPPathPattern("/v1/management/services:discoverElastiCache")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_ManagementService_DiscoverElastiCache_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_ManagementService_DiscoverElastiCache_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) mux.Handle(http.MethodDelete, pattern_ManagementService_RemoveService_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1011,6 +1075,7 @@ var ( pattern_ManagementService_DiscoverRDS_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "management", "services"}, "discoverRDS")) pattern_ManagementService_DiscoverAzureDatabase_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "management", "services"}, "discoverAzure")) pattern_ManagementService_AddAzureDatabase_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "management", "services", "azure"}, "")) + pattern_ManagementService_DiscoverElastiCache_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "management", "services"}, "discoverElastiCache")) pattern_ManagementService_RemoveService_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "management", "services", "service_id"}, "")) ) @@ -1027,5 +1092,6 @@ var ( forward_ManagementService_DiscoverRDS_0 = runtime.ForwardResponseMessage forward_ManagementService_DiscoverAzureDatabase_0 = runtime.ForwardResponseMessage forward_ManagementService_AddAzureDatabase_0 = runtime.ForwardResponseMessage + forward_ManagementService_DiscoverElastiCache_0 = runtime.ForwardResponseMessage forward_ManagementService_RemoveService_0 = runtime.ForwardResponseMessage ) diff --git a/api/management/v1/service.pb.validate.go b/api/management/v1/service.pb.validate.go index 3f144eddbdc..97eb98b0e73 100644 --- a/api/management/v1/service.pb.validate.go +++ b/api/management/v1/service.pb.validate.go @@ -390,6 +390,47 @@ func (m *AddServiceRequest) validate(all bool) error { } } + case *AddServiceRequest_Elasticache: + if v == nil { + err := AddServiceRequestValidationError{ + field: "Service", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetElasticache()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, AddServiceRequestValidationError{ + field: "Elasticache", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, AddServiceRequestValidationError{ + field: "Elasticache", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetElasticache()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AddServiceRequestValidationError{ + field: "Elasticache", + reason: "embedded message failed validation", + cause: err, + } + } + } + default: _ = v // ensures v is used } @@ -826,6 +867,47 @@ func (m *AddServiceResponse) validate(all bool) error { } } + case *AddServiceResponse_Elasticache: + if v == nil { + err := AddServiceResponseValidationError{ + field: "Service", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetElasticache()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, AddServiceResponseValidationError{ + field: "Elasticache", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, AddServiceResponseValidationError{ + field: "Elasticache", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetElasticache()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AddServiceResponseValidationError{ + field: "Elasticache", + reason: "embedded message failed validation", + cause: err, + } + } + } + default: _ = v // ensures v is used } diff --git a/api/management/v1/service.proto b/api/management/v1/service.proto index afdcfacd5c2..9c00cf77f08 100644 --- a/api/management/v1/service.proto +++ b/api/management/v1/service.proto @@ -8,6 +8,7 @@ import "inventory/v1/services.proto"; import "management/v1/agent.proto"; import "management/v1/annotation.proto"; import "management/v1/azure.proto"; +import "management/v1/elasticache.proto"; import "management/v1/external.proto"; import "management/v1/haproxy.proto"; import "management/v1/mongodb.proto"; @@ -29,6 +30,7 @@ message AddServiceRequest { AddExternalServiceParams external = 6; AddRDSServiceParams rds = 7; AddValkeyServiceParams valkey = 8; + AddElastiCacheServiceParams elasticache = 9; } } @@ -42,6 +44,7 @@ message AddServiceResponse { ExternalServiceResult external = 6; RDSServiceResult rds = 7; ValkeyServiceResult valkey = 8; + ElastiCacheServiceResult elasticache = 9; } } @@ -270,6 +273,17 @@ service ManagementService { description: "Adds an Azure Database instance." }; } + // DiscoverElastiCache discovers ElastiCache replication groups (Valkey/Redis). + rpc DiscoverElastiCache(DiscoverElastiCacheRequest) returns (DiscoverElastiCacheResponse) { + option (google.api.http) = { + post: "/v1/management/services:discoverElastiCache" + body: "*" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "Discover ElastiCache" + description: "Discovers ElastiCache replication groups (Valkey/Redis)." + }; + } // RemoveService removes a Service along with its Agents. rpc RemoveService(RemoveServiceRequest) returns (RemoveServiceResponse) { option (google.api.http) = {delete: "/v1/management/services/{service_id}"}; diff --git a/api/management/v1/service_grpc.pb.go b/api/management/v1/service_grpc.pb.go index b50380dc4b5..21b6c95f4df 100644 --- a/api/management/v1/service_grpc.pb.go +++ b/api/management/v1/service_grpc.pb.go @@ -32,6 +32,7 @@ const ( ManagementService_DiscoverRDS_FullMethodName = "/management.v1.ManagementService/DiscoverRDS" ManagementService_DiscoverAzureDatabase_FullMethodName = "/management.v1.ManagementService/DiscoverAzureDatabase" ManagementService_AddAzureDatabase_FullMethodName = "/management.v1.ManagementService/AddAzureDatabase" + ManagementService_DiscoverElastiCache_FullMethodName = "/management.v1.ManagementService/DiscoverElastiCache" ManagementService_RemoveService_FullMethodName = "/management.v1.ManagementService/RemoveService" ) @@ -65,6 +66,8 @@ type ManagementServiceClient interface { DiscoverAzureDatabase(ctx context.Context, in *DiscoverAzureDatabaseRequest, opts ...grpc.CallOption) (*DiscoverAzureDatabaseResponse, error) // AddAzureDatabase adds Azure Database instance. AddAzureDatabase(ctx context.Context, in *AddAzureDatabaseRequest, opts ...grpc.CallOption) (*AddAzureDatabaseResponse, error) + // DiscoverElastiCache discovers ElastiCache replication groups (Valkey/Redis). + DiscoverElastiCache(ctx context.Context, in *DiscoverElastiCacheRequest, opts ...grpc.CallOption) (*DiscoverElastiCacheResponse, error) // RemoveService removes a Service along with its Agents. RemoveService(ctx context.Context, in *RemoveServiceRequest, opts ...grpc.CallOption) (*RemoveServiceResponse, error) } @@ -197,6 +200,16 @@ func (c *managementServiceClient) AddAzureDatabase(ctx context.Context, in *AddA return out, nil } +func (c *managementServiceClient) DiscoverElastiCache(ctx context.Context, in *DiscoverElastiCacheRequest, opts ...grpc.CallOption) (*DiscoverElastiCacheResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DiscoverElastiCacheResponse) + err := c.cc.Invoke(ctx, ManagementService_DiscoverElastiCache_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *managementServiceClient) RemoveService(ctx context.Context, in *RemoveServiceRequest, opts ...grpc.CallOption) (*RemoveServiceResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(RemoveServiceResponse) @@ -237,6 +250,8 @@ type ManagementServiceServer interface { DiscoverAzureDatabase(context.Context, *DiscoverAzureDatabaseRequest) (*DiscoverAzureDatabaseResponse, error) // AddAzureDatabase adds Azure Database instance. AddAzureDatabase(context.Context, *AddAzureDatabaseRequest) (*AddAzureDatabaseResponse, error) + // DiscoverElastiCache discovers ElastiCache replication groups (Valkey/Redis). + DiscoverElastiCache(context.Context, *DiscoverElastiCacheRequest) (*DiscoverElastiCacheResponse, error) // RemoveService removes a Service along with its Agents. RemoveService(context.Context, *RemoveServiceRequest) (*RemoveServiceResponse, error) mustEmbedUnimplementedManagementServiceServer() @@ -297,6 +312,10 @@ func (UnimplementedManagementServiceServer) AddAzureDatabase(context.Context, *A return nil, status.Error(codes.Unimplemented, "method AddAzureDatabase not implemented") } +func (UnimplementedManagementServiceServer) DiscoverElastiCache(context.Context, *DiscoverElastiCacheRequest) (*DiscoverElastiCacheResponse, error) { + return nil, status.Error(codes.Unimplemented, "method DiscoverElastiCache not implemented") +} + func (UnimplementedManagementServiceServer) RemoveService(context.Context, *RemoveServiceRequest) (*RemoveServiceResponse, error) { return nil, status.Error(codes.Unimplemented, "method RemoveService not implemented") } @@ -537,6 +556,24 @@ func _ManagementService_AddAzureDatabase_Handler(srv interface{}, ctx context.Co return interceptor(ctx, in, info, handler) } +func _ManagementService_DiscoverElastiCache_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DiscoverElastiCacheRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ManagementServiceServer).DiscoverElastiCache(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ManagementService_DiscoverElastiCache_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ManagementServiceServer).DiscoverElastiCache(ctx, req.(*DiscoverElastiCacheRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _ManagementService_RemoveService_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RemoveServiceRequest) if err := dec(in); err != nil { @@ -610,6 +647,10 @@ var ManagementService_ServiceDesc = grpc.ServiceDesc{ MethodName: "AddAzureDatabase", Handler: _ManagementService_AddAzureDatabase_Handler, }, + { + MethodName: "DiscoverElastiCache", + Handler: _ManagementService_DiscoverElastiCache_Handler, + }, { MethodName: "RemoveService", Handler: _ManagementService_RemoveService_Handler, diff --git a/api/swagger/swagger-dev.json b/api/swagger/swagger-dev.json index f521777f744..f62f4e1e084 100644 --- a/api/swagger/swagger-dev.json +++ b/api/swagger/swagger-dev.json @@ -17476,7 +17476,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "type": "string", "default": "NODE_TYPE_UNSPECIFIED", @@ -17770,6 +17771,59 @@ } }, "x-order": 4 + }, + "remote_elasticache": { + "type": "array", + "items": { + "description": "RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes.", + "type": "object", + "properties": { + "node_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 1 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 3 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 4 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 5 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 6 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 7 + } + } + }, + "x-order": 5 } } } @@ -18041,6 +18095,50 @@ } }, "x-order": 4 + }, + "remote_elasticache": { + "type": "object", + "properties": { + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 0 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 1 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 2 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 3 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 4 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 5 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 6 + } + }, + "x-order": 5 } } } @@ -18316,6 +18414,56 @@ } }, "x-order": 4 + }, + "remote_elasticache": { + "description": "RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes.", + "type": "object", + "properties": { + "node_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 1 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 3 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 4 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 5 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 6 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 7 + } + }, + "x-order": 5 } } } @@ -18641,6 +18789,56 @@ } }, "x-order": 4 + }, + "remote_elasticache": { + "description": "RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes.", + "type": "object", + "properties": { + "node_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 1 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 3 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 4 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 5 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 6 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 7 + } + }, + "x-order": 5 } } } @@ -22012,7 +22210,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "type": "string", "default": "NODE_TYPE_UNSPECIFIED", @@ -22250,7 +22449,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -23439,7 +23639,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -23708,7 +23909,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -23989,7 +24191,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -24255,7 +24458,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -24463,7 +24667,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -24628,7 +24833,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -25003,7 +25209,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -25190,85 +25397,212 @@ } }, "x-order": 7 - } - } - } - } - ], - "responses": { - "200": { - "description": "A successful response.", - "schema": { - "type": "object", - "properties": { - "mysql": { + }, + "elasticache": { "type": "object", "properties": { - "service": { - "description": "MySQLService represents a generic MySQL instance.", - "type": "object", - "properties": { - "service_id": { - "description": "Unique randomly generated instance identifier.", - "type": "string", - "x-order": 0 - }, - "service_name": { - "description": "Unique across all Services user-defined name.", - "type": "string", - "x-order": 1 - }, - "node_id": { - "description": "Node identifier where this instance runs.", - "type": "string", - "x-order": 2 - }, - "address": { - "description": "Access address (DNS name or IP).\nAddress (and port) or socket is required.", - "type": "string", - "x-order": 3 - }, - "port": { - "description": "Access port.\nPort is required when the address present.", - "type": "integer", - "format": "int64", - "x-order": 4 - }, - "socket": { - "description": "Access unix socket.\nAddress (and port) or socket is required.", - "type": "string", - "x-order": 5 - }, - "environment": { - "description": "Environment name.", - "type": "string", - "x-order": 6 - }, - "cluster": { - "description": "Cluster name.", - "type": "string", - "x-order": 7 - }, - "replication_set": { - "description": "Replication set name.", - "type": "string", - "x-order": 8 - }, - "custom_labels": { - "description": "Custom user-assigned labels.", - "type": "object", - "additionalProperties": { - "type": "string" - }, - "x-order": 9 - }, - "version": { - "description": "MySQL version.", - "type": "string", - "x-order": 10 - }, - "extra_dsn_params": { - "description": "Extra parameters to be added to the DSN.", + "region": { + "description": "AWS region.", + "type": "string", + "x-order": 0 + }, + "az": { + "description": "AWS availability zone.", + "type": "string", + "x-order": 1 + }, + "instance_id": { + "description": "Replication group identifier.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Cache node type.", + "type": "string", + "x-order": 3 + }, + "address": { + "description": "Primary endpoint address.", + "type": "string", + "x-order": 4 + }, + "port": { + "description": "Primary endpoint port.", + "type": "integer", + "format": "int64", + "x-order": 5 + }, + "engine": { + "description": "DiscoverElastiCacheEngine describes supported ElastiCache engines.", + "type": "string", + "default": "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + "enum": [ + "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + "DISCOVER_ELASTI_CACHE_ENGINE_REDIS", + "DISCOVER_ELASTI_CACHE_ENGINE_VALKEY" + ], + "x-order": 6 + }, + "pmm_agent_id": { + "description": "PMM Agent ID.", + "type": "string", + "x-order": 7 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name. Defaults to instance_id.", + "type": "string", + "x-order": 8 + }, + "service_name": { + "description": "Unique across all Services user-defined name. Defaults to instance_id.", + "type": "string", + "x-order": 9 + }, + "environment": { + "description": "Environment name.", + "type": "string", + "x-order": 10 + }, + "cluster": { + "description": "Cluster name.", + "type": "string", + "x-order": 11 + }, + "replication_set": { + "description": "Replication set name.", + "type": "string", + "x-order": 12 + }, + "username": { + "description": "Username for scraping metrics.", + "type": "string", + "x-order": 13 + }, + "password": { + "description": "Password for scraping metrics.", + "type": "string", + "x-order": 14 + }, + "custom_labels": { + "description": "Custom user-assigned labels for Node and Service.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 15 + }, + "skip_connection_check": { + "description": "Skip connection check.", + "type": "boolean", + "x-order": 16 + }, + "tls": { + "description": "Use TLS for database connections.", + "type": "boolean", + "x-order": 17 + }, + "tls_skip_verify": { + "description": "Skip TLS certificate and hostname validation.", + "type": "boolean", + "x-order": 18 + }, + "metrics_mode": { + "description": "MetricsMode defines desired metrics mode for agent,\nit can be pull, push or auto mode chosen by server.\n\n - METRICS_MODE_UNSPECIFIED: Auto", + "type": "string", + "default": "METRICS_MODE_UNSPECIFIED", + "enum": [ + "METRICS_MODE_UNSPECIFIED", + "METRICS_MODE_PULL", + "METRICS_MODE_PUSH" + ], + "x-order": 19 + }, + "agent_password": { + "description": "Custom password for exporter endpoint /metrics.", + "type": "string", + "x-order": 20 + } + }, + "x-order": 8 + } + } + } + } + ], + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "type": "object", + "properties": { + "mysql": { + "type": "object", + "properties": { + "service": { + "description": "MySQLService represents a generic MySQL instance.", + "type": "object", + "properties": { + "service_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "service_name": { + "description": "Unique across all Services user-defined name.", + "type": "string", + "x-order": 1 + }, + "node_id": { + "description": "Node identifier where this instance runs.", + "type": "string", + "x-order": 2 + }, + "address": { + "description": "Access address (DNS name or IP).\nAddress (and port) or socket is required.", + "type": "string", + "x-order": 3 + }, + "port": { + "description": "Access port.\nPort is required when the address present.", + "type": "integer", + "format": "int64", + "x-order": 4 + }, + "socket": { + "description": "Access unix socket.\nAddress (and port) or socket is required.", + "type": "string", + "x-order": 5 + }, + "environment": { + "description": "Environment name.", + "type": "string", + "x-order": 6 + }, + "cluster": { + "description": "Cluster name.", + "type": "string", + "x-order": 7 + }, + "replication_set": { + "description": "Replication set name.", + "type": "string", + "x-order": 8 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 9 + }, + "version": { + "description": "MySQL version.", + "type": "string", + "x-order": 10 + }, + "extra_dsn_params": { + "description": "Extra parameters to be added to the DSN.", "type": "object", "additionalProperties": { "type": "string" @@ -28287,72 +28621,316 @@ } }, "x-order": 7 - } - } - } - }, - "default": { - "description": "An unexpected error response.", - "schema": { - "type": "object", - "properties": { - "code": { - "type": "integer", - "format": "int32", - "x-order": 0 - }, - "message": { - "type": "string", - "x-order": 1 - }, - "details": { - "type": "array", - "items": { - "type": "object", - "properties": { - "@type": { - "type": "string", - "x-order": 0 - } - }, - "additionalProperties": {} - }, - "x-order": 2 - } - } - } - } - } - } - }, - "/v1/management/services/azure": { - "post": { - "description": "Adds an Azure Database instance.", - "tags": [ - "ManagementService" - ], - "summary": "Add Azure Database", - "operationId": "AddAzureDatabase", - "parameters": [ - { - "name": "body", - "in": "body", - "required": true, - "schema": { - "type": "object", - "properties": { - "region": { - "description": "Azure database location.", - "type": "string", - "x-order": 0 - }, - "az": { - "description": "Azure database availability zone.", - "type": "string", - "x-order": 1 }, - "instance_id": { - "description": "Azure database instance ID.", + "elasticache": { + "type": "object", + "properties": { + "node": { + "description": "RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes.", + "type": "object", + "properties": { + "node_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 1 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 3 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 4 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 5 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 6 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 7 + } + }, + "x-order": 0 + }, + "valkey_service": { + "description": "ValkeyService represents a generic Valkey instance.", + "type": "object", + "properties": { + "service_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "service_name": { + "description": "Unique across all Services user-defined name.", + "type": "string", + "x-order": 1 + }, + "node_id": { + "description": "Node identifier where this instance runs.", + "type": "string", + "x-order": 2 + }, + "address": { + "description": "Access address (DNS name or IP).\nAddress (and port) or socket is required.", + "type": "string", + "x-order": 3 + }, + "port": { + "description": "Access port.\nPort is required when the address present.", + "type": "integer", + "format": "int64", + "x-order": 4 + }, + "socket": { + "description": "Access unix socket.\nAddress (and port) or socket is required.", + "type": "string", + "x-order": 5 + }, + "environment": { + "description": "Environment name.", + "type": "string", + "x-order": 6 + }, + "cluster": { + "description": "Cluster name.", + "type": "string", + "x-order": 7 + }, + "replication_set": { + "description": "Replication set name.", + "type": "string", + "x-order": 8 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 9 + }, + "version": { + "description": "Valkey version.", + "type": "string", + "x-order": 10 + } + }, + "x-order": 1 + }, + "valkey_exporter": { + "description": "ValkeyExporter runs on Generic or Container Node and exposes Valkey Service metrics.", + "type": "object", + "properties": { + "agent_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "pmm_agent_id": { + "description": "The pmm-agent identifier which runs this instance.", + "type": "string", + "x-order": 1 + }, + "disabled": { + "description": "Desired Agent status: enabled (false) or disabled (true).", + "type": "boolean", + "x-order": 2 + }, + "service_id": { + "description": "Service identifier.", + "type": "string", + "x-order": 3 + }, + "username": { + "description": "Valkey username for scraping metrics.", + "type": "string", + "x-order": 4 + }, + "tls": { + "description": "Use TLS for database connections.", + "type": "boolean", + "x-order": 5 + }, + "tls_skip_verify": { + "description": "Skip TLS certificate and hostname verification.", + "type": "boolean", + "x-order": 6 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 7 + }, + "push_metrics_enabled": { + "description": "True if exporter uses push metrics mode.", + "type": "boolean", + "x-order": 8 + }, + "disabled_collectors": { + "description": "List of disabled collector names.", + "type": "array", + "items": { + "type": "string" + }, + "x-order": 9 + }, + "status": { + "description": "AgentStatus represents actual Agent status.\n\n - AGENT_STATUS_STARTING: Agent is starting.\n - AGENT_STATUS_INITIALIZATION_ERROR: Agent encountered error when starting.\n - AGENT_STATUS_RUNNING: Agent is running.\n - AGENT_STATUS_WAITING: Agent encountered error and will be restarted automatically soon.\n - AGENT_STATUS_STOPPING: Agent is stopping.\n - AGENT_STATUS_DONE: Agent has been stopped or disabled.\n - AGENT_STATUS_UNKNOWN: Agent is not connected, we don't know anything about it's state.", + "type": "string", + "default": "AGENT_STATUS_UNSPECIFIED", + "enum": [ + "AGENT_STATUS_UNSPECIFIED", + "AGENT_STATUS_STARTING", + "AGENT_STATUS_INITIALIZATION_ERROR", + "AGENT_STATUS_RUNNING", + "AGENT_STATUS_WAITING", + "AGENT_STATUS_STOPPING", + "AGENT_STATUS_DONE", + "AGENT_STATUS_UNKNOWN" + ], + "x-order": 10 + }, + "listen_port": { + "description": "Listen port for scraping metrics.", + "type": "integer", + "format": "int64", + "x-order": 11 + }, + "process_exec_path": { + "description": "Path to exec process.", + "type": "string", + "x-order": 12 + }, + "expose_exporter": { + "type": "boolean", + "title": "Optionally expose the exporter process on all public interfaces", + "x-order": 13 + }, + "metrics_resolutions": { + "description": "MetricsResolutions represents Prometheus exporters metrics resolutions.", + "type": "object", + "properties": { + "hr": { + "description": "High resolution. In JSON should be represented as a string with number of seconds with `s` suffix.", + "type": "string", + "x-order": 0 + }, + "mr": { + "description": "Medium resolution. In JSON should be represented as a string with number of seconds with `s` suffix.", + "type": "string", + "x-order": 1 + }, + "lr": { + "description": "Low resolution. In JSON should be represented as a string with number of seconds with `s` suffix.", + "type": "string", + "x-order": 2 + } + }, + "x-order": 14 + }, + "connection_timeout": { + "description": "Connection timeout for exporter (if set).", + "type": "string", + "x-order": 15 + } + }, + "x-order": 2 + } + }, + "x-order": 8 + } + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32", + "x-order": 0 + }, + "message": { + "type": "string", + "x-order": 1 + }, + "details": { + "type": "array", + "items": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "x-order": 0 + } + }, + "additionalProperties": {} + }, + "x-order": 2 + } + } + } + } + } + } + }, + "/v1/management/services/azure": { + "post": { + "description": "Adds an Azure Database instance.", + "tags": [ + "ManagementService" + ], + "summary": "Add Azure Database", + "operationId": "AddAzureDatabase", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "properties": { + "region": { + "description": "Azure database location.", + "type": "string", + "x-order": 0 + }, + "az": { + "description": "Azure database availability zone.", + "type": "string", + "x-order": 1 + }, + "instance_id": { + "description": "Azure database instance ID.", "type": "string", "x-order": 2 }, @@ -28754,6 +29332,146 @@ } } }, + "/v1/management/services:discoverElastiCache": { + "post": { + "description": "Discovers ElastiCache replication groups (Valkey/Redis).", + "tags": [ + "ManagementService" + ], + "summary": "Discover ElastiCache", + "operationId": "DiscoverElastiCache", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "properties": { + "aws_access_key": { + "description": "AWS Access key. Optional — if empty, the default credential chain is used.", + "type": "string", + "x-order": 0 + }, + "aws_secret_key": { + "description": "AWS Secret key. Optional.", + "type": "string", + "x-order": 1 + } + } + } + } + ], + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "type": "object", + "properties": { + "elasticache_instances": { + "type": "array", + "items": { + "description": "DiscoverElastiCacheInstance models an ElastiCache replication group discovered by the API.", + "type": "object", + "properties": { + "region": { + "description": "AWS region.", + "type": "string", + "x-order": 0 + }, + "az": { + "description": "AWS availability zone.", + "type": "string", + "x-order": 1 + }, + "instance_id": { + "description": "Replication group identifier.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Cache node type (e.g. cache.r7g.large).", + "type": "string", + "x-order": 3 + }, + "address": { + "description": "Primary endpoint address.", + "type": "string", + "x-order": 4 + }, + "port": { + "description": "Primary endpoint port.", + "type": "integer", + "format": "int64", + "x-order": 5 + }, + "engine": { + "description": "DiscoverElastiCacheEngine describes supported ElastiCache engines.", + "type": "string", + "default": "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + "enum": [ + "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + "DISCOVER_ELASTI_CACHE_ENGINE_REDIS", + "DISCOVER_ELASTI_CACHE_ENGINE_VALKEY" + ], + "x-order": 6 + }, + "engine_version": { + "description": "Engine version.", + "type": "string", + "x-order": 7 + }, + "transit_encryption_enabled": { + "description": "Whether in-transit encryption is enabled.", + "type": "boolean", + "x-order": 8 + }, + "cluster": { + "description": "Cluster name (replication group ID).", + "type": "string", + "x-order": 9 + } + } + }, + "x-order": 0 + } + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32", + "x-order": 0 + }, + "message": { + "type": "string", + "x-order": 1 + }, + "details": { + "type": "array", + "items": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "x-order": 0 + } + }, + "additionalProperties": {} + }, + "x-order": 2 + } + } + } + } + } + } + }, "/v1/management/services:discoverRDS": { "post": { "description": "Discovers RDS instances.", diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index ae34b9296a5..76bd2362e14 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -16503,7 +16503,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "type": "string", "default": "NODE_TYPE_UNSPECIFIED", @@ -16797,6 +16798,59 @@ } }, "x-order": 4 + }, + "remote_elasticache": { + "type": "array", + "items": { + "description": "RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes.", + "type": "object", + "properties": { + "node_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 1 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 3 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 4 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 5 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 6 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 7 + } + } + }, + "x-order": 5 } } } @@ -17068,6 +17122,50 @@ } }, "x-order": 4 + }, + "remote_elasticache": { + "type": "object", + "properties": { + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 0 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 1 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 2 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 3 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 4 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 5 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 6 + } + }, + "x-order": 5 } } } @@ -17343,6 +17441,56 @@ } }, "x-order": 4 + }, + "remote_elasticache": { + "description": "RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes.", + "type": "object", + "properties": { + "node_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 1 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 3 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 4 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 5 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 6 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 7 + } + }, + "x-order": 5 } } } @@ -17668,6 +17816,56 @@ } }, "x-order": 4 + }, + "remote_elasticache": { + "description": "RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes.", + "type": "object", + "properties": { + "node_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 1 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 3 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 4 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 5 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 6 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 7 + } + }, + "x-order": 5 } } } @@ -21039,7 +21237,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "type": "string", "default": "NODE_TYPE_UNSPECIFIED", @@ -21277,7 +21476,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -22466,7 +22666,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -22735,7 +22936,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -23016,7 +23218,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -23282,7 +23485,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -23490,7 +23694,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -23655,7 +23860,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -24030,7 +24236,8 @@ "NODE_TYPE_CONTAINER_NODE", "NODE_TYPE_REMOTE_NODE", "NODE_TYPE_REMOTE_RDS_NODE", - "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE" + "NODE_TYPE_REMOTE_AZURE_DATABASE_NODE", + "NODE_TYPE_REMOTE_ELASTICACHE_NODE" ], "x-order": 0 }, @@ -24217,85 +24424,212 @@ } }, "x-order": 7 - } - } - } - } - ], - "responses": { - "200": { - "description": "A successful response.", - "schema": { - "type": "object", - "properties": { - "mysql": { + }, + "elasticache": { "type": "object", "properties": { - "service": { - "description": "MySQLService represents a generic MySQL instance.", - "type": "object", - "properties": { - "service_id": { - "description": "Unique randomly generated instance identifier.", - "type": "string", - "x-order": 0 - }, - "service_name": { - "description": "Unique across all Services user-defined name.", - "type": "string", - "x-order": 1 - }, - "node_id": { - "description": "Node identifier where this instance runs.", - "type": "string", - "x-order": 2 - }, - "address": { - "description": "Access address (DNS name or IP).\nAddress (and port) or socket is required.", - "type": "string", - "x-order": 3 - }, - "port": { - "description": "Access port.\nPort is required when the address present.", - "type": "integer", - "format": "int64", - "x-order": 4 - }, - "socket": { - "description": "Access unix socket.\nAddress (and port) or socket is required.", - "type": "string", - "x-order": 5 - }, - "environment": { - "description": "Environment name.", - "type": "string", - "x-order": 6 - }, - "cluster": { - "description": "Cluster name.", - "type": "string", - "x-order": 7 - }, - "replication_set": { - "description": "Replication set name.", - "type": "string", - "x-order": 8 - }, - "custom_labels": { - "description": "Custom user-assigned labels.", - "type": "object", - "additionalProperties": { - "type": "string" - }, - "x-order": 9 - }, - "version": { - "description": "MySQL version.", - "type": "string", - "x-order": 10 - }, - "extra_dsn_params": { - "description": "Extra parameters to be added to the DSN.", + "region": { + "description": "AWS region.", + "type": "string", + "x-order": 0 + }, + "az": { + "description": "AWS availability zone.", + "type": "string", + "x-order": 1 + }, + "instance_id": { + "description": "Replication group identifier.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Cache node type.", + "type": "string", + "x-order": 3 + }, + "address": { + "description": "Primary endpoint address.", + "type": "string", + "x-order": 4 + }, + "port": { + "description": "Primary endpoint port.", + "type": "integer", + "format": "int64", + "x-order": 5 + }, + "engine": { + "description": "DiscoverElastiCacheEngine describes supported ElastiCache engines.", + "type": "string", + "default": "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + "enum": [ + "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + "DISCOVER_ELASTI_CACHE_ENGINE_REDIS", + "DISCOVER_ELASTI_CACHE_ENGINE_VALKEY" + ], + "x-order": 6 + }, + "pmm_agent_id": { + "description": "PMM Agent ID.", + "type": "string", + "x-order": 7 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name. Defaults to instance_id.", + "type": "string", + "x-order": 8 + }, + "service_name": { + "description": "Unique across all Services user-defined name. Defaults to instance_id.", + "type": "string", + "x-order": 9 + }, + "environment": { + "description": "Environment name.", + "type": "string", + "x-order": 10 + }, + "cluster": { + "description": "Cluster name.", + "type": "string", + "x-order": 11 + }, + "replication_set": { + "description": "Replication set name.", + "type": "string", + "x-order": 12 + }, + "username": { + "description": "Username for scraping metrics.", + "type": "string", + "x-order": 13 + }, + "password": { + "description": "Password for scraping metrics.", + "type": "string", + "x-order": 14 + }, + "custom_labels": { + "description": "Custom user-assigned labels for Node and Service.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 15 + }, + "skip_connection_check": { + "description": "Skip connection check.", + "type": "boolean", + "x-order": 16 + }, + "tls": { + "description": "Use TLS for database connections.", + "type": "boolean", + "x-order": 17 + }, + "tls_skip_verify": { + "description": "Skip TLS certificate and hostname validation.", + "type": "boolean", + "x-order": 18 + }, + "metrics_mode": { + "description": "MetricsMode defines desired metrics mode for agent,\nit can be pull, push or auto mode chosen by server.\n\n - METRICS_MODE_UNSPECIFIED: Auto", + "type": "string", + "default": "METRICS_MODE_UNSPECIFIED", + "enum": [ + "METRICS_MODE_UNSPECIFIED", + "METRICS_MODE_PULL", + "METRICS_MODE_PUSH" + ], + "x-order": 19 + }, + "agent_password": { + "description": "Custom password for exporter endpoint /metrics.", + "type": "string", + "x-order": 20 + } + }, + "x-order": 8 + } + } + } + } + ], + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "type": "object", + "properties": { + "mysql": { + "type": "object", + "properties": { + "service": { + "description": "MySQLService represents a generic MySQL instance.", + "type": "object", + "properties": { + "service_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "service_name": { + "description": "Unique across all Services user-defined name.", + "type": "string", + "x-order": 1 + }, + "node_id": { + "description": "Node identifier where this instance runs.", + "type": "string", + "x-order": 2 + }, + "address": { + "description": "Access address (DNS name or IP).\nAddress (and port) or socket is required.", + "type": "string", + "x-order": 3 + }, + "port": { + "description": "Access port.\nPort is required when the address present.", + "type": "integer", + "format": "int64", + "x-order": 4 + }, + "socket": { + "description": "Access unix socket.\nAddress (and port) or socket is required.", + "type": "string", + "x-order": 5 + }, + "environment": { + "description": "Environment name.", + "type": "string", + "x-order": 6 + }, + "cluster": { + "description": "Cluster name.", + "type": "string", + "x-order": 7 + }, + "replication_set": { + "description": "Replication set name.", + "type": "string", + "x-order": 8 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 9 + }, + "version": { + "description": "MySQL version.", + "type": "string", + "x-order": 10 + }, + "extra_dsn_params": { + "description": "Extra parameters to be added to the DSN.", "type": "object", "additionalProperties": { "type": "string" @@ -27314,72 +27648,316 @@ } }, "x-order": 7 - } - } - } - }, - "default": { - "description": "An unexpected error response.", - "schema": { - "type": "object", - "properties": { - "code": { - "type": "integer", - "format": "int32", - "x-order": 0 - }, - "message": { - "type": "string", - "x-order": 1 - }, - "details": { - "type": "array", - "items": { - "type": "object", - "properties": { - "@type": { - "type": "string", - "x-order": 0 - } - }, - "additionalProperties": {} - }, - "x-order": 2 - } - } - } - } - } - } - }, - "/v1/management/services/azure": { - "post": { - "description": "Adds an Azure Database instance.", - "tags": [ - "ManagementService" - ], - "summary": "Add Azure Database", - "operationId": "AddAzureDatabase", - "parameters": [ - { - "name": "body", - "in": "body", - "required": true, - "schema": { - "type": "object", - "properties": { - "region": { - "description": "Azure database location.", - "type": "string", - "x-order": 0 - }, - "az": { - "description": "Azure database availability zone.", - "type": "string", - "x-order": 1 }, - "instance_id": { - "description": "Azure database instance ID.", + "elasticache": { + "type": "object", + "properties": { + "node": { + "description": "RemoteElastiCacheNode represents remote ElastiCache Node. Agents can't run on Remote ElastiCache Nodes.", + "type": "object", + "properties": { + "node_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "node_name": { + "description": "Unique across all Nodes user-defined name.", + "type": "string", + "x-order": 1 + }, + "address": { + "description": "ElastiCache primary endpoint address.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Node model (cache node type).", + "type": "string", + "x-order": 3 + }, + "region": { + "description": "Node region.", + "type": "string", + "x-order": 4 + }, + "az": { + "description": "Node availability zone.", + "type": "string", + "x-order": 5 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 6 + }, + "instance_id": { + "description": "AWS instance ID (replication group ID).", + "type": "string", + "x-order": 7 + } + }, + "x-order": 0 + }, + "valkey_service": { + "description": "ValkeyService represents a generic Valkey instance.", + "type": "object", + "properties": { + "service_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "service_name": { + "description": "Unique across all Services user-defined name.", + "type": "string", + "x-order": 1 + }, + "node_id": { + "description": "Node identifier where this instance runs.", + "type": "string", + "x-order": 2 + }, + "address": { + "description": "Access address (DNS name or IP).\nAddress (and port) or socket is required.", + "type": "string", + "x-order": 3 + }, + "port": { + "description": "Access port.\nPort is required when the address present.", + "type": "integer", + "format": "int64", + "x-order": 4 + }, + "socket": { + "description": "Access unix socket.\nAddress (and port) or socket is required.", + "type": "string", + "x-order": 5 + }, + "environment": { + "description": "Environment name.", + "type": "string", + "x-order": 6 + }, + "cluster": { + "description": "Cluster name.", + "type": "string", + "x-order": 7 + }, + "replication_set": { + "description": "Replication set name.", + "type": "string", + "x-order": 8 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 9 + }, + "version": { + "description": "Valkey version.", + "type": "string", + "x-order": 10 + } + }, + "x-order": 1 + }, + "valkey_exporter": { + "description": "ValkeyExporter runs on Generic or Container Node and exposes Valkey Service metrics.", + "type": "object", + "properties": { + "agent_id": { + "description": "Unique randomly generated instance identifier.", + "type": "string", + "x-order": 0 + }, + "pmm_agent_id": { + "description": "The pmm-agent identifier which runs this instance.", + "type": "string", + "x-order": 1 + }, + "disabled": { + "description": "Desired Agent status: enabled (false) or disabled (true).", + "type": "boolean", + "x-order": 2 + }, + "service_id": { + "description": "Service identifier.", + "type": "string", + "x-order": 3 + }, + "username": { + "description": "Valkey username for scraping metrics.", + "type": "string", + "x-order": 4 + }, + "tls": { + "description": "Use TLS for database connections.", + "type": "boolean", + "x-order": 5 + }, + "tls_skip_verify": { + "description": "Skip TLS certificate and hostname verification.", + "type": "boolean", + "x-order": 6 + }, + "custom_labels": { + "description": "Custom user-assigned labels.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "x-order": 7 + }, + "push_metrics_enabled": { + "description": "True if exporter uses push metrics mode.", + "type": "boolean", + "x-order": 8 + }, + "disabled_collectors": { + "description": "List of disabled collector names.", + "type": "array", + "items": { + "type": "string" + }, + "x-order": 9 + }, + "status": { + "description": "AgentStatus represents actual Agent status.\n\n - AGENT_STATUS_STARTING: Agent is starting.\n - AGENT_STATUS_INITIALIZATION_ERROR: Agent encountered error when starting.\n - AGENT_STATUS_RUNNING: Agent is running.\n - AGENT_STATUS_WAITING: Agent encountered error and will be restarted automatically soon.\n - AGENT_STATUS_STOPPING: Agent is stopping.\n - AGENT_STATUS_DONE: Agent has been stopped or disabled.\n - AGENT_STATUS_UNKNOWN: Agent is not connected, we don't know anything about it's state.", + "type": "string", + "default": "AGENT_STATUS_UNSPECIFIED", + "enum": [ + "AGENT_STATUS_UNSPECIFIED", + "AGENT_STATUS_STARTING", + "AGENT_STATUS_INITIALIZATION_ERROR", + "AGENT_STATUS_RUNNING", + "AGENT_STATUS_WAITING", + "AGENT_STATUS_STOPPING", + "AGENT_STATUS_DONE", + "AGENT_STATUS_UNKNOWN" + ], + "x-order": 10 + }, + "listen_port": { + "description": "Listen port for scraping metrics.", + "type": "integer", + "format": "int64", + "x-order": 11 + }, + "process_exec_path": { + "description": "Path to exec process.", + "type": "string", + "x-order": 12 + }, + "expose_exporter": { + "type": "boolean", + "title": "Optionally expose the exporter process on all public interfaces", + "x-order": 13 + }, + "metrics_resolutions": { + "description": "MetricsResolutions represents Prometheus exporters metrics resolutions.", + "type": "object", + "properties": { + "hr": { + "description": "High resolution. In JSON should be represented as a string with number of seconds with `s` suffix.", + "type": "string", + "x-order": 0 + }, + "mr": { + "description": "Medium resolution. In JSON should be represented as a string with number of seconds with `s` suffix.", + "type": "string", + "x-order": 1 + }, + "lr": { + "description": "Low resolution. In JSON should be represented as a string with number of seconds with `s` suffix.", + "type": "string", + "x-order": 2 + } + }, + "x-order": 14 + }, + "connection_timeout": { + "description": "Connection timeout for exporter (if set).", + "type": "string", + "x-order": 15 + } + }, + "x-order": 2 + } + }, + "x-order": 8 + } + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32", + "x-order": 0 + }, + "message": { + "type": "string", + "x-order": 1 + }, + "details": { + "type": "array", + "items": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "x-order": 0 + } + }, + "additionalProperties": {} + }, + "x-order": 2 + } + } + } + } + } + } + }, + "/v1/management/services/azure": { + "post": { + "description": "Adds an Azure Database instance.", + "tags": [ + "ManagementService" + ], + "summary": "Add Azure Database", + "operationId": "AddAzureDatabase", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "properties": { + "region": { + "description": "Azure database location.", + "type": "string", + "x-order": 0 + }, + "az": { + "description": "Azure database availability zone.", + "type": "string", + "x-order": 1 + }, + "instance_id": { + "description": "Azure database instance ID.", "type": "string", "x-order": 2 }, @@ -27781,6 +28359,146 @@ } } }, + "/v1/management/services:discoverElastiCache": { + "post": { + "description": "Discovers ElastiCache replication groups (Valkey/Redis).", + "tags": [ + "ManagementService" + ], + "summary": "Discover ElastiCache", + "operationId": "DiscoverElastiCache", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "properties": { + "aws_access_key": { + "description": "AWS Access key. Optional — if empty, the default credential chain is used.", + "type": "string", + "x-order": 0 + }, + "aws_secret_key": { + "description": "AWS Secret key. Optional.", + "type": "string", + "x-order": 1 + } + } + } + } + ], + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "type": "object", + "properties": { + "elasticache_instances": { + "type": "array", + "items": { + "description": "DiscoverElastiCacheInstance models an ElastiCache replication group discovered by the API.", + "type": "object", + "properties": { + "region": { + "description": "AWS region.", + "type": "string", + "x-order": 0 + }, + "az": { + "description": "AWS availability zone.", + "type": "string", + "x-order": 1 + }, + "instance_id": { + "description": "Replication group identifier.", + "type": "string", + "x-order": 2 + }, + "node_model": { + "description": "Cache node type (e.g. cache.r7g.large).", + "type": "string", + "x-order": 3 + }, + "address": { + "description": "Primary endpoint address.", + "type": "string", + "x-order": 4 + }, + "port": { + "description": "Primary endpoint port.", + "type": "integer", + "format": "int64", + "x-order": 5 + }, + "engine": { + "description": "DiscoverElastiCacheEngine describes supported ElastiCache engines.", + "type": "string", + "default": "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + "enum": [ + "DISCOVER_ELASTI_CACHE_ENGINE_UNSPECIFIED", + "DISCOVER_ELASTI_CACHE_ENGINE_REDIS", + "DISCOVER_ELASTI_CACHE_ENGINE_VALKEY" + ], + "x-order": 6 + }, + "engine_version": { + "description": "Engine version.", + "type": "string", + "x-order": 7 + }, + "transit_encryption_enabled": { + "description": "Whether in-transit encryption is enabled.", + "type": "boolean", + "x-order": 8 + }, + "cluster": { + "description": "Cluster name (replication group ID).", + "type": "string", + "x-order": 9 + } + } + }, + "x-order": 0 + } + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32", + "x-order": 0 + }, + "message": { + "type": "string", + "x-order": 1 + }, + "details": { + "type": "array", + "items": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "x-order": 0 + } + }, + "additionalProperties": {} + }, + "x-order": 2 + } + } + } + } + } + } + }, "/v1/management/services:discoverRDS": { "post": { "description": "Discovers RDS instances.", diff --git a/go.mod b/go.mod index e218543ceb1..473698a0e2c 100644 --- a/go.mod +++ b/go.mod @@ -16,9 +16,10 @@ require ( github.com/alecthomas/kingpin/v2 v2.4.0 github.com/alecthomas/kong v1.15.0 github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b - github.com/aws/aws-sdk-go-v2 v1.41.5 + github.com/aws/aws-sdk-go-v2 v1.41.6 github.com/aws/aws-sdk-go-v2/config v1.32.12 github.com/aws/aws-sdk-go-v2/credentials v1.19.12 + github.com/aws/aws-sdk-go-v2/service/elasticache v1.52.1 github.com/aws/aws-sdk-go-v2/service/rds v1.118.0 github.com/aws/smithy-go v1.25.0 github.com/blang/semver v3.5.1+incompatible @@ -121,8 +122,8 @@ require ( github.com/apache/skywalking-eyes v0.8.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect diff --git a/go.sum b/go.sum index 621d69937ae..aaf125c8746 100644 --- a/go.sum +++ b/go.sum @@ -129,20 +129,22 @@ github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJ github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY= -github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2 v1.41.6 h1:1AX0AthnBQzMx1vbmir3Y4WsnJgiydmnJjiLu+LvXOg= +github.com/aws/aws-sdk-go-v2 v1.41.6/go.mod h1:dy0UzBIfwSeot4grGvY1AqFWN5zgziMmWGzysDnHFcQ= github.com/aws/aws-sdk-go-v2/config v1.32.12 h1:O3csC7HUGn2895eNrLytOJQdoL2xyJy0iYXhoZ1OmP0= github.com/aws/aws-sdk-go-v2/config v1.32.12/go.mod h1:96zTvoOFR4FURjI+/5wY1vc1ABceROO4lWgWJuxgy0g= github.com/aws/aws-sdk-go-v2/credentials v1.19.12 h1:oqtA6v+y5fZg//tcTWahyN9PEn5eDU/Wpvc2+kJ4aY8= github.com/aws/aws-sdk-go-v2/credentials v1.19.12/go.mod h1:U3R1RtSHx6NB0DvEQFGyf/0sbrpJrluENHdPy1j/3TE= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 h1:zOgq3uezl5nznfoK3ODuqbhVg1JzAGDUhXOsU0IDCAo= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20/go.mod h1:z/MVwUARehy6GAg/yQ1GO2IMl0k++cu1ohP9zo887wE= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 h1:GmLa5Kw1ESqtFpXsx5MmC84QWa/ZrLZvlJGa2y+4kcQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22/go.mod h1:6sW9iWm9DK9YRpRGga/qzrzNLgKpT2cIxb7Vo2eNOp0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 h1:dY4kWZiSaXIzxnKlj17nHnBcXXBfac6UlsAx2qL6XrU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22/go.mod h1:KIpEUx0JuRZLO7U6cbV204cWAEco2iC3l061IxlwLtI= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/service/elasticache v1.52.1 h1:OiVtvILStTDHhiq60Y3H3BnJFSNecBiNn/gmiWrjPOA= +github.com/aws/aws-sdk-go-v2/service/elasticache v1.52.1/go.mod h1:D73K84NboORJenKGZJFzx7/eZFJh+px5WRHnGuVaa2U= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto= diff --git a/managed/cmd/pmm-managed/main.go b/managed/cmd/pmm-managed/main.go index 90f6eb5fcc6..6ee53b0d6c7 100644 --- a/managed/cmd/pmm-managed/main.go +++ b/managed/cmd/pmm-managed/main.go @@ -1020,6 +1020,7 @@ func main() { //nolint:gocognit,maintidx,cyclop schedulerService := scheduler.New(db, backupService) versionCache := versioncache.New(db, versioner) + elasticacheDiscovery := management.NewElastiCacheDiscovery(db, agentsStateUpdater) dumpService := dump.New(db, &dump.URLs{ ClickhouseURL: chURI.String(), @@ -1160,6 +1161,11 @@ func main() { //nolint:gocognit,maintidx,cyclop return nil })) + haService.AddLeaderService(ha.NewContextService("elasticacheDiscovery", func(ctx context.Context) error { + elasticacheDiscovery.Run(ctx) + return nil + })) + wg.Go(func() { runGRPCServer(ctx, &gRPCServerDeps{ diff --git a/managed/models/agent_helpers.go b/managed/models/agent_helpers.go index 0f2f88b5e00..60b2e1e1139 100644 --- a/managed/models/agent_helpers.go +++ b/managed/models/agent_helpers.go @@ -820,6 +820,7 @@ func compatibleNodeAndAgent(nodeType NodeType, agentType AgentType) bool { RemoteNodeType: ExternalExporterType, RemoteRDSNodeType: RDSExporterType, RemoteAzureDatabaseNodeType: AzureDatabaseExporterType, + RemoteElastiCacheNodeType: allowAll, } allowed, ok := allow[nodeType] diff --git a/managed/models/node_model.go b/managed/models/node_model.go index bf6bf74a082..307c8cf319b 100644 --- a/managed/models/node_model.go +++ b/managed/models/node_model.go @@ -36,6 +36,7 @@ const ( RemoteNodeType NodeType = "remote" RemoteRDSNodeType NodeType = "remote_rds" RemoteAzureDatabaseNodeType NodeType = "remote_azure_database" + RemoteElastiCacheNodeType NodeType = "remote_elasticache" ) // PMMServerNodeID is a special Node ID representing PMM Server Node. diff --git a/managed/services/converters.go b/managed/services/converters.go index 886493122a0..54b5f1623af 100644 --- a/managed/services/converters.go +++ b/managed/services/converters.go @@ -101,6 +101,18 @@ func ToAPINode(node *models.Node) (inventoryv1.Node, error) { //nolint:ireturn Address: node.Address, }, nil + case models.RemoteElastiCacheNodeType: + return &inventoryv1.RemoteElastiCacheNode{ + NodeId: node.NodeID, + NodeName: node.NodeName, + NodeModel: node.NodeModel, + Region: pointer.GetString(node.Region), + Az: node.AZ, + CustomLabels: labels, + Address: node.Address, + InstanceId: node.InstanceID, + }, nil + default: panic(fmt.Errorf("unhandled Node type %s", node.NodeType)) } @@ -666,6 +678,7 @@ var nodeTypes = map[inventoryv1.NodeType]models.NodeType{ inventoryv1.NodeType_NODE_TYPE_REMOTE_NODE: models.RemoteNodeType, inventoryv1.NodeType_NODE_TYPE_REMOTE_RDS_NODE: models.RemoteRDSNodeType, inventoryv1.NodeType_NODE_TYPE_REMOTE_AZURE_DATABASE_NODE: models.RemoteAzureDatabaseNodeType, + inventoryv1.NodeType_NODE_TYPE_REMOTE_ELASTICACHE_NODE: models.RemoteElastiCacheNodeType, } // ProtoToModelNodeType converts a NodeType from protobuf to model. diff --git a/managed/services/inventory/grpc/nodes_server.go b/managed/services/inventory/grpc/nodes_server.go index 1ff504f94c7..b4d2c710638 100644 --- a/managed/services/inventory/grpc/nodes_server.go +++ b/managed/services/inventory/grpc/nodes_server.go @@ -41,6 +41,7 @@ var nodeTypes = map[inventoryv1.NodeType]models.NodeType{ inventoryv1.NodeType_NODE_TYPE_REMOTE_NODE: models.RemoteNodeType, inventoryv1.NodeType_NODE_TYPE_REMOTE_RDS_NODE: models.RemoteRDSNodeType, inventoryv1.NodeType_NODE_TYPE_REMOTE_AZURE_DATABASE_NODE: models.RemoteAzureDatabaseNodeType, + inventoryv1.NodeType_NODE_TYPE_REMOTE_ELASTICACHE_NODE: models.RemoteElastiCacheNodeType, } func nodeType(nodeType inventoryv1.NodeType) *models.NodeType { @@ -73,6 +74,8 @@ func (s *nodesServer) ListNodes(ctx context.Context, req *inventoryv1.ListNodesR res.RemoteRds = append(res.RemoteRds, node) case *inventoryv1.RemoteAzureDatabaseNode: res.RemoteAzureDatabase = append(res.RemoteAzureDatabase, node) + case *inventoryv1.RemoteElastiCacheNode: + res.RemoteElasticache = append(res.RemoteElasticache, node) default: panic(fmt.Errorf("unhandled inventory Node type %T", node)) } @@ -99,6 +102,8 @@ func (s *nodesServer) GetNode(ctx context.Context, req *inventoryv1.GetNodeReque res.Node = &inventoryv1.GetNodeResponse_RemoteRds{RemoteRds: node} case *inventoryv1.RemoteAzureDatabaseNode: res.Node = &inventoryv1.GetNodeResponse_RemoteAzureDatabase{RemoteAzureDatabase: node} + case *inventoryv1.RemoteElastiCacheNode: + res.Node = &inventoryv1.GetNodeResponse_RemoteElasticache{RemoteElasticache: node} default: panic(fmt.Errorf("unhandled inventory Node type %T", node)) } diff --git a/managed/services/inventory/nodes.go b/managed/services/inventory/nodes.go index 87504d9733b..2f17fc67849 100644 --- a/managed/services/inventory/nodes.go +++ b/managed/services/inventory/nodes.go @@ -125,6 +125,12 @@ func (s *NodesService) AddNode(ctx context.Context, req *inventoryv1.AddNodeRequ return nil, err } res.Node = &inventoryv1.AddNodeResponse_RemoteAzureDatabase{RemoteAzureDatabase: node} + case *inventoryv1.AddNodeRequest_RemoteElasticache: + node, err := s.AddRemoteElastiCacheNode(ctx, req.GetRemoteElasticache()) + if err != nil { + return nil, err + } + res.Node = &inventoryv1.AddNodeResponse_RemoteElasticache{RemoteElasticache: node} default: return nil, errors.Errorf("invalid request %v", req.GetNode()) } @@ -299,6 +305,40 @@ func (s *NodesService) AddRemoteAzureDatabaseNode(ctx context.Context, req *inve return invNode.(*inventoryv1.RemoteAzureDatabaseNode), nil //nolint:forcetypeassert } +// AddRemoteElastiCacheNode adds a new ElastiCache node. +// +//nolint:dupl +func (s *NodesService) AddRemoteElastiCacheNode(ctx context.Context, req *inventoryv1.AddRemoteElastiCacheNodeParams) (*inventoryv1.RemoteElastiCacheNode, error) { + params := &models.CreateNodeParams{ + NodeName: req.NodeName, + Address: req.Address, + NodeModel: req.NodeModel, + Region: pointer.ToStringOrNil(req.Region), + AZ: req.Az, + CustomLabels: req.CustomLabels, + } + + node := &models.Node{} + e := s.db.InTransactionContext(ctx, nil, func(tx *reform.TX) error { + var err error + node, err = models.CreateNode(tx.Querier, models.RemoteElastiCacheNodeType, params) + if err != nil { + return err + } + return nil + }) + if e != nil { + return nil, e + } + + invNode, err := services.ToAPINode(node) + if err != nil { + return nil, err + } + + return invNode.(*inventoryv1.RemoteElastiCacheNode), nil //nolint:forcetypeassert +} + // Remove removes Node without any Agents and Services. // Removes Node with the Agents and Services if force == true. // Returns an error if force == false and Node has Agents or Services. diff --git a/managed/services/inventory/nodes_test.go b/managed/services/inventory/nodes_test.go index fee6179a00a..f74866b8aff 100644 --- a/managed/services/inventory/nodes_test.go +++ b/managed/services/inventory/nodes_test.go @@ -207,6 +207,7 @@ func TestAddNode(t *testing.T) { nodeID3 = "00000000-0000-4000-8000-000000000007" nodeID4 = "00000000-0000-4000-8000-000000000008" nodeID5 = "00000000-0000-4000-8000-000000000009" + nodeID6 = "00000000-0000-4000-8000-00000000000a" ) _, _, ns, teardown, ctx, _ := setup(t) t.Cleanup(func() { teardown(t) }) @@ -317,13 +318,33 @@ func TestAddNode(t *testing.T) { require.NoError(t, err) assert.Equal(t, expectedNode5, addNodeResponse.GetRemoteRds()) + expectedNode6 := &inventoryv1.RemoteElastiCacheNode{ + NodeId: nodeID6, + NodeName: "test-name6", + Region: "test-region", + Az: "test-region-az", + Address: "test6", + } + addNodeResponse, err = ns.AddNode(ctx, &inventoryv1.AddNodeRequest{ + Node: &inventoryv1.AddNodeRequest_RemoteElasticache{ + RemoteElasticache: &inventoryv1.AddRemoteElastiCacheNodeParams{ + NodeName: "test-name6", + Region: "test-region", + Az: "test-region-az", + Address: "test6", + }, + }, + }) + require.NoError(t, err) + assert.Equal(t, expectedNode6, addNodeResponse.GetRemoteElasticache()) + getNodeResponse, err := ns.Get(ctx, &inventoryv1.GetNodeRequest{NodeId: nodeID1}) require.NoError(t, err) assert.Equal(t, expectedNode1, getNodeResponse) nodesResponse, err := ns.List(ctx, models.NodeFilters{}) require.NoError(t, err) - require.Len(t, nodesResponse, 6) + require.Len(t, nodesResponse, 7) assert.Equal(t, expectedNode1, nodesResponse[0]) err = ns.Remove(ctx, nodeID1, false) @@ -333,6 +354,80 @@ func TestAddNode(t *testing.T) { assert.Nil(t, getNodeResponse) }) + t.Run("AddRemoteElastiCacheNode", func(t *testing.T) { + const nodeID = "00000000-0000-4000-8000-000000000005" + _, _, ns, teardown, ctx, _ := setup(t) + t.Cleanup(func() { teardown(t) }) + + addNodeResponse, err := ns.AddNode(ctx, &inventoryv1.AddNodeRequest{ + Node: &inventoryv1.AddNodeRequest_RemoteElasticache{ + RemoteElasticache: &inventoryv1.AddRemoteElastiCacheNodeParams{ + NodeName: "test-elasticache", + Address: "my-cluster.abc123.use1.cache.amazonaws.com", + Region: "us-east-1", + Az: "us-east-1a", + NodeModel: "cache.r6g.large", + CustomLabels: map[string]string{ + "env": "production", + }, + }, + }, + }) + require.NoError(t, err) + + expectedNode := &inventoryv1.RemoteElastiCacheNode{ + NodeId: nodeID, + NodeName: "test-elasticache", + Address: "my-cluster.abc123.use1.cache.amazonaws.com", + Region: "us-east-1", + Az: "us-east-1a", + NodeModel: "cache.r6g.large", + CustomLabels: map[string]string{ + "env": "production", + }, + } + assert.Equal(t, expectedNode, addNodeResponse.GetRemoteElasticache()) + + getNodeResponse, err := ns.Get(ctx, &inventoryv1.GetNodeRequest{NodeId: nodeID}) + require.NoError(t, err) + assert.Equal(t, expectedNode, getNodeResponse) + + err = ns.Remove(ctx, nodeID, false) + require.NoError(t, err) + + getNodeResponse, err = ns.Get(ctx, &inventoryv1.GetNodeRequest{NodeId: nodeID}) + tests.AssertGRPCError(t, status.New(codes.NotFound, fmt.Sprintf("Node with ID %q not found.", nodeID)), err) + assert.Nil(t, getNodeResponse) + }) + + t.Run("AddRemoteElastiCacheNodeNonUnique", func(t *testing.T) { + _, _, ns, teardown, ctx, _ := setup(t) + t.Cleanup(func() { teardown(t) }) + + _, err := ns.AddNode(ctx, &inventoryv1.AddNodeRequest{ + Node: &inventoryv1.AddNodeRequest_RemoteElasticache{ + RemoteElasticache: &inventoryv1.AddRemoteElastiCacheNodeParams{ + NodeName: "test1", + Region: "test-region", + Address: "test-address", + }, + }, + }) + require.NoError(t, err) + + _, err = ns.AddNode(ctx, &inventoryv1.AddNodeRequest{ + Node: &inventoryv1.AddNodeRequest_RemoteElasticache{ + RemoteElasticache: &inventoryv1.AddRemoteElastiCacheNodeParams{ + NodeName: "test2", + Region: "test-region", + Address: "test-address", + }, + }, + }) + expected := status.New(codes.AlreadyExists, `Node with address "test-address" and region "test-region" already exists.`) + tests.AssertGRPCError(t, expected, err) + }) + t.Run("AddRemoteRDSNodeNonUnique", func(t *testing.T) { _, _, ns, teardown, ctx, _ := setup(t) t.Cleanup(func() { teardown(t) }) diff --git a/managed/services/inventory/services.go b/managed/services/inventory/services.go index 4211b9b4587..3b5b83a69a7 100644 --- a/managed/services/inventory/services.go +++ b/managed/services/inventory/services.go @@ -333,8 +333,8 @@ func (ss *ServicesService) Remove(ctx context.Context, id string, force bool) er return err } - // For RDS and Azure remove also node. - if node.NodeType == models.RemoteRDSNodeType || node.NodeType == models.RemoteAzureDatabaseNodeType { + // For RDS, Azure and ElastiCache remove also node. + if node.NodeType == models.RemoteRDSNodeType || node.NodeType == models.RemoteAzureDatabaseNodeType || node.NodeType == models.RemoteElastiCacheNodeType { agents, err := models.FindAgents(tx.Querier, models.AgentFilters{NodeID: node.NodeID}) if err != nil { return err diff --git a/managed/services/management/elasticache.go b/managed/services/management/elasticache.go new file mode 100644 index 00000000000..e0922e39a68 --- /dev/null +++ b/managed/services/management/elasticache.go @@ -0,0 +1,333 @@ +// Copyright (C) 2023 Percona LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package management + +import ( + "context" + "net/http" + "sort" + + "github.com/AlekSi/pointer" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/elasticache" + ectypes "github.com/aws/aws-sdk-go-v2/service/elasticache/types" + "github.com/aws/smithy-go" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "golang.org/x/sync/errgroup" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "gopkg.in/reform.v1" + + inventoryv1 "github.com/percona/pmm/api/inventory/v1" + managementv1 "github.com/percona/pmm/api/management/v1" + "github.com/percona/pmm/managed/models" + "github.com/percona/pmm/managed/services" + "github.com/percona/pmm/utils/logger" +) + +// elasticacheEngines maps AWS engine names to our proto enum. +var elasticacheEngines = map[string]managementv1.DiscoverElastiCacheEngine{ + "redis": managementv1.DiscoverElastiCacheEngine_DISCOVER_ELASTI_CACHE_ENGINE_REDIS, + "valkey": managementv1.DiscoverElastiCacheEngine_DISCOVER_ELASTI_CACHE_ENGINE_VALKEY, +} + +// discoverElastiCacheRegion returns a list of ElastiCache replication groups from a single region. +func discoverElastiCacheRegion(ctx context.Context, cfg aws.Config, region string) ([]ectypes.ReplicationGroup, error) { + var res []ectypes.ReplicationGroup + client := elasticache.NewFromConfig(cfg, func(o *elasticache.Options) { + o.Region = region + }) + + paginator := elasticache.NewDescribeReplicationGroupsPaginator(client, &elasticache.DescribeReplicationGroupsInput{}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + return res, err + } + res = append(res, page.ReplicationGroups...) + } + + return res, nil +} + +// listElastiCacheRegions returns a list of AWS regions where ElastiCache is available. +// ElastiCache is available in the same regions as RDS, so we reuse the same list. +func listElastiCacheRegions(partitions []string) []string { + return listRegions(partitions) +} + +// DiscoverElastiCache discovers ElastiCache replication groups (Valkey/Redis). +func (s *ManagementService) DiscoverElastiCache(ctx context.Context, req *managementv1.DiscoverElastiCacheRequest) (*managementv1.DiscoverElastiCacheResponse, error) { //nolint:gocognit,cyclop,lll + l := logger.Get(ctx).WithField("component", "discover/elasticache") + + settings, err := models.GetSettings(s.db.Querier) + if err != nil { + return nil, err + } + + // Use given credentials, or default credential chain. + var creds aws.CredentialsProvider + if req.AwsAccessKey != "" && req.AwsSecretKey != "" { + creds = credentials.NewStaticCredentialsProvider(req.AwsAccessKey, req.AwsSecretKey, "") + } + + opts := []func(*config.LoadOptions) error{ + config.WithCredentialsProvider(creds), + config.WithHTTPClient(&http.Client{}), + } + if l.Logger != nil && l.Logger.Level >= logrus.DebugLevel { + opts = append(opts, config.WithClientLogMode(aws.LogRetries|aws.LogRequestWithBody|aws.LogResponseWithBody)) + } + + cfg, err := config.LoadDefaultConfig(ctx, opts...) + if err != nil { + return nil, errors.WithStack(err) + } + + // Default to standard AWS partition if none configured. + partitions := settings.AWSPartitions + if len(partitions) == 0 { + partitions = []string{"aws"} + } + + ctx, cancel := context.WithTimeout(ctx, awsDiscoverTimeout) + defer cancel() + var wg errgroup.Group + instances := make(chan *managementv1.DiscoverElastiCacheInstance) + + for _, region := range listElastiCacheRegions(partitions) { + wg.Go(func() error { + regGroups, err := discoverElastiCacheRegion(ctx, cfg, region) + if err != nil { + l.Debugf("%s: %+v", region, err) + } + + for _, rg := range regGroups { + if rg.Status == nil || *rg.Status != "available" { + continue + } + + engine, ok := elasticacheEngines[pointer.GetString(rg.Engine)] + if !ok { + continue + } + + clusterName := pointer.GetString(rg.ReplicationGroupId) + nodeType := pointer.GetString(rg.CacheNodeType) + transitEncryption := rg.TransitEncryptionEnabled != nil && *rg.TransitEncryptionEnabled + + // Cluster Mode Enabled: use ConfigurationEndpoint. + if rg.ClusterEnabled != nil && *rg.ClusterEnabled && rg.ConfigurationEndpoint != nil { + az := "" + if len(rg.NodeGroups) > 0 && len(rg.NodeGroups[0].NodeGroupMembers) > 0 { + az = pointer.GetString(rg.NodeGroups[0].NodeGroupMembers[0].PreferredAvailabilityZone) + } + instances <- &managementv1.DiscoverElastiCacheInstance{ + Region: region, + Az: az, + InstanceId: clusterName, + NodeModel: nodeType, + Address: pointer.GetString(rg.ConfigurationEndpoint.Address), + Port: uint32(pointer.GetInt32(rg.ConfigurationEndpoint.Port)), //nolint:gosec + Engine: engine, + TransitEncryptionEnabled: transitEncryption, + Cluster: clusterName, + } + continue + } + + // Cluster Mode Disabled: report per-shard endpoints. + for _, ng := range rg.NodeGroups { + if ng.PrimaryEndpoint == nil { + continue + } + + az := "" + if len(ng.NodeGroupMembers) > 0 { + az = pointer.GetString(ng.NodeGroupMembers[0].PreferredAvailabilityZone) + } + + instances <- &managementv1.DiscoverElastiCacheInstance{ + Region: region, + Az: az, + InstanceId: clusterName, + NodeModel: nodeType, + Address: pointer.GetString(ng.PrimaryEndpoint.Address), + Port: uint32(pointer.GetInt32(ng.PrimaryEndpoint.Port)), //nolint:gosec + Engine: engine, + TransitEncryptionEnabled: transitEncryption, + Cluster: clusterName, + } + } + } + + return err + }) + } + + go func() { + _ = wg.Wait() + close(instances) + }() + + res := &managementv1.DiscoverElastiCacheResponse{} + for i := range instances { + res.ElasticacheInstances = append(res.ElasticacheInstances, i) + } + + sort.Slice(res.ElasticacheInstances, func(i, j int) bool { + if res.ElasticacheInstances[i].Region != res.ElasticacheInstances[j].Region { + return res.ElasticacheInstances[i].Region < res.ElasticacheInstances[j].Region + } + return res.ElasticacheInstances[i].InstanceId < res.ElasticacheInstances[j].InstanceId + }) + + if len(res.ElasticacheInstances) != 0 { + return res, nil + } + + // Return better gRPC errors in typical cases. + err = wg.Wait() + if err != nil { + var apiErr *smithy.GenericAPIError + if errors.As(err, &apiErr) { + switch { + case apiErr.Code == "InvalidClientTokenId": + return res, status.Error(codes.InvalidArgument, apiErr.Message) + case errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded): + return res, status.Error(codes.DeadlineExceeded, "Request timeout.") + default: + return res, status.Error(codes.Unknown, apiErr.Error()) + } + } + + if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { + return res, status.Error(codes.DeadlineExceeded, "Request timeout.") + } + + return res, status.Error(codes.Unknown, err.Error()) + } + + return res, nil +} + +// addElastiCache adds an ElastiCache instance as a Valkey service. +func (s *ManagementService) addElastiCache(ctx context.Context, req *managementv1.AddElastiCacheServiceParams) (*managementv1.AddServiceResponse, error) { + ec := &managementv1.ElastiCacheServiceResult{} + + pmmAgentID := models.PMMServerAgentID + if req.GetPmmAgentId() != "" { + pmmAgentID = req.GetPmmAgentId() + } + + errTx := s.db.InTransactionContext(ctx, nil, func(tx *reform.TX) error { + if req.NodeName == "" { + req.NodeName = req.InstanceId + } + if req.ServiceName == "" { + req.ServiceName = req.InstanceId + } + + node, err := models.CreateNode(tx.Querier, models.RemoteElastiCacheNodeType, &models.CreateNodeParams{ + NodeName: req.NodeName, + NodeModel: req.NodeModel, + AZ: req.Az, + InstanceID: req.InstanceId, + Address: req.Address, + Region: &req.Region, + CustomLabels: req.CustomLabels, + }) + if err != nil { + return err + } + invNode, err := services.ToAPINode(node) + if err != nil { + return err + } + ec.Node = invNode.(*inventoryv1.RemoteElastiCacheNode) //nolint:forcetypeassert + + metricsMode, err := supportedMetricsMode(req.MetricsMode, pmmAgentID) + if err != nil { + return err + } + + service, err := models.AddNewService(tx.Querier, models.ValkeyServiceType, &models.AddDBMSServiceParams{ + ServiceName: req.ServiceName, + NodeID: node.NodeID, + Environment: req.Environment, + Cluster: req.Cluster, + ReplicationSet: req.ReplicationSet, + CustomLabels: req.CustomLabels, + Address: &req.Address, + Port: pointer.ToUint16(uint16(req.Port)), //nolint:gosec,modernize + }) + if err != nil { + return err + } + invService, err := services.ToAPIService(service) + if err != nil { + return err + } + ec.ValkeyService = invService.(*inventoryv1.ValkeyService) //nolint:forcetypeassert + + valkeyExporter, err := models.CreateAgent(tx.Querier, models.ValkeyExporterType, &models.CreateAgentParams{ + PMMAgentID: pmmAgentID, + ServiceID: service.ServiceID, + Username: req.Username, + Password: req.Password, + TLS: req.Tls, + TLSSkipVerify: req.TlsSkipVerify, + ExporterOptions: models.ExporterOptions{ + PushMetrics: isPushMode(metricsMode), + }, + }) + if err != nil { + return err + } + + if !req.SkipConnectionCheck { + if err = s.cc.CheckConnectionToService(ctx, tx.Querier, service, valkeyExporter); err != nil { + return err + } + if err = s.sib.GetInfoFromService(ctx, tx.Querier, service, valkeyExporter); err != nil { + return err + } + } + + invAgent, err := services.ToAPIAgent(tx.Querier, valkeyExporter) + if err != nil { + return err + } + ec.ValkeyExporter = invAgent.(*inventoryv1.ValkeyExporter) //nolint:forcetypeassert + + return nil + }) + + if errTx != nil { + return nil, errTx + } + + s.state.RequestStateUpdate(ctx, pmmAgentID) + + return &managementv1.AddServiceResponse{ + Service: &managementv1.AddServiceResponse_Elasticache{ + Elasticache: ec, + }, + }, nil +} diff --git a/managed/services/management/elasticache_discovery.go b/managed/services/management/elasticache_discovery.go new file mode 100644 index 00000000000..efac010ab19 --- /dev/null +++ b/managed/services/management/elasticache_discovery.go @@ -0,0 +1,537 @@ +// Copyright (C) 2023 Percona LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package management + +import ( + "context" + "fmt" + "net/http" + "sort" + "sync/atomic" + "time" + + "github.com/AlekSi/pointer" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/elasticache" + ectypes "github.com/aws/aws-sdk-go-v2/service/elasticache/types" + "github.com/sirupsen/logrus" + "golang.org/x/sync/errgroup" + "gopkg.in/reform.v1" + + "github.com/percona/pmm/managed/models" +) + +const ( + // How long to wait after startup before first discovery run. + elasticacheDiscoveryStartupDelay = 30 * time.Second + // How often to run the reconciliation loop. + elasticacheDiscoveryInterval = 5 * time.Minute + // Timeout for a single discovery cycle (all regions). + elasticacheDiscoveryTimeout = 60 * time.Second + // Tag that must be "true" on a replication group for it to be auto-added. + elasticacheTagKey = "pmm_enable" + elasticacheTagValue = "true" + // Label used to identify services managed by auto-discovery. + elasticacheManagedByLabel = "elasticache-autodiscovery" +) + +// ElastiCacheDiscovery is a background service that periodically discovers +// ElastiCache replication groups tagged with pmm_enable=true and reconciles +// them with the PMM inventory. +type ElastiCacheDiscovery struct { + db *reform.DB + state agentsStateUpdater + l *logrus.Entry +} + +// NewElastiCacheDiscovery creates a new ElastiCacheDiscovery service. +func NewElastiCacheDiscovery(db *reform.DB, state agentsStateUpdater) *ElastiCacheDiscovery { + return &ElastiCacheDiscovery{ + db: db, + state: state, + l: logrus.WithField("component", "elasticache-discovery"), + } +} + +// discoveredInstance holds info about an ElastiCache endpoint discovered from AWS. +type discoveredInstance struct { + Region string + AZ string + ClusterID string // ReplicationGroupId + NodeType string // CacheNodeType + Address string + Port int32 + Engine string // "redis" or "valkey" + TLS bool + Environment string // from AWS "Environment" tag + Role string // "primary", "reader", or "cluster" for cluster mode +} + +// Run starts the background discovery loop. It blocks until ctx is cancelled. +func (d *ElastiCacheDiscovery) Run(ctx context.Context) { + d.l.Info("Starting (waiting for initial delay)...") + select { + case <-time.After(elasticacheDiscoveryStartupDelay): + case <-ctx.Done(): + return + } + + d.l.Info("Started.") + ticker := time.NewTicker(elasticacheDiscoveryInterval) + defer ticker.Stop() + + for { + d.reconcile(ctx) + + select { + case <-ticker.C: + case <-ctx.Done(): + d.l.Info("Stopped.") + return + } + } +} + +// reconcile runs a single discovery + sync cycle. +func (d *ElastiCacheDiscovery) reconcile(ctx context.Context) { + d.l.Info("Running reconciliation...") + + settings, err := models.GetSettings(d.db.Querier) + if err != nil { + d.l.Warnf("Failed to get settings: %v", err) + return + } + + // Default to standard AWS partition if none configured. + partitions := settings.AWSPartitions + if len(partitions) == 0 { + partitions = []string{"aws"} + } + + regions := listElastiCacheRegions(partitions) + discovered, scanComplete, err := d.discoverTaggedInstances(ctx, regions) + if err != nil { + d.l.Warnf("Discovery failed: %v", err) + return + } + + managed, err := d.findManagedServices() + if err != nil { + d.l.Warnf("Failed to list managed services: %v", err) + return + } + + d.l.Infof("Discovered %d endpoint(s), PMM has %d managed service(s)", len(discovered), len(managed)) + + // Build maps keyed by address for diffing. + expectedByAddr := make(map[string]discoveredInstance, len(discovered)) + for _, inst := range discovered { + expectedByAddr[inst.Address] = inst + } + + managedByAddr := make(map[string]*models.Service, len(managed)) + for _, svc := range managed { + if svc.Address != nil { + managedByAddr[*svc.Address] = svc + } + } + + // Add missing. Adds are safe even on a partial scan: any tagged cluster we + // did see is still legitimately tagged, and the operation is idempotent. + var added, addFailed int + for addr, inst := range expectedByAddr { + if _, exists := managedByAddr[addr]; exists { + continue + } + if err := d.addInstance(ctx, inst); err != nil { + d.l.Warnf("Failed to add %s (%s): %v", inst.ClusterID, addr, err) + addFailed++ + continue + } + added++ + } + + // Remove stale — only when the AWS scan completed cleanly across every + // region and tag lookup. A partial scan would make legitimate services look + // "missing" (e.g. throttled ListTagsForResource → cluster appears untagged) + // and trigger false removals. + var removed int + if !scanComplete { + d.l.Warnf("Discovery scan was incomplete; skipping stale-removal this cycle") + } else { + for addr, svc := range managedByAddr { + if _, exists := expectedByAddr[addr]; exists { + continue + } + if err := d.removeService(ctx, svc); err != nil { + d.l.Warnf("Failed to remove %s (%s): %v", svc.ServiceName, addr, err) + continue + } + removed++ + } + } + + unchanged := len(expectedByAddr) - added - addFailed + d.l.Infof("Reconciliation complete: +%d added, -%d removed, =%d unchanged, %d failed (scan complete: %t)", + added, removed, unchanged, addFailed, scanComplete) +} + +// discoverTaggedInstances discovers ElastiCache replication groups across regions +// and filters to those tagged with pmm_enable=true. +// +// Returns (instances, scanComplete, error). The scanComplete flag is false +// when any region scan or per-cluster tag lookup failed; callers must not use +// the result to drive destructive operations (e.g. stale-removal) in that case. +func (d *ElastiCacheDiscovery) discoverTaggedInstances(ctx context.Context, regions []string) ([]discoveredInstance, bool, error) { + cfg, err := config.LoadDefaultConfig( + ctx, + config.WithHTTPClient(&http.Client{}), + ) + if err != nil { + return nil, false, fmt.Errorf("failed to load AWS config: %w", err) + } + + d.l.Debugf("Scanning %d region(s)", len(regions)) + + ctx, cancel := context.WithTimeout(ctx, elasticacheDiscoveryTimeout) + defer cancel() + + var wg errgroup.Group + results := make(chan discoveredInstance) + var scanFailed atomic.Bool + + for _, region := range regions { + wg.Go(func() error { + instances, complete := d.discoverRegionTagged(ctx, cfg, region) + if !complete { + scanFailed.Store(true) + } + if len(instances) > 0 { + d.l.Debugf("Region %s: found %d tagged endpoint(s)", region, len(instances)) + } + for _, inst := range instances { + results <- inst + } + return nil + }) + } + + go func() { + _ = wg.Wait() + close(results) + }() + + var discovered []discoveredInstance + for inst := range results { + discovered = append(discovered, inst) + } + + sort.Slice(discovered, func(i, j int) bool { + if discovered[i].Region != discovered[j].Region { + return discovered[i].Region < discovered[j].Region + } + return discovered[i].Address < discovered[j].Address + }) + + return discovered, !scanFailed.Load(), nil +} + +// discoverRegionTagged returns ElastiCache replication groups in a region that are tagged pmm_enable=true. +// +// The second return value is true only when every AWS call in this region +// succeeded. A false value means the caller should not trust the absence of any +// previously-known cluster from the returned slice (e.g. throttled +// DescribeReplicationGroups or ListTagsForResource). +func (d *ElastiCacheDiscovery) discoverRegionTagged(ctx context.Context, cfg aws.Config, region string) ([]discoveredInstance, bool) { //nolint:gocognit + client := elasticache.NewFromConfig(cfg, func(o *elasticache.Options) { + o.Region = region + }) + + var instances []discoveredInstance + complete := true + + paginator := elasticache.NewDescribeReplicationGroupsPaginator(client, &elasticache.DescribeReplicationGroupsInput{}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + d.l.Warnf("Region %s: DescribeReplicationGroups failed: %v", region, err) + return instances, false + } + + for _, rg := range page.ReplicationGroups { + if rg.Status == nil || *rg.Status != "available" { + continue + } + + engine := pointer.GetString(rg.Engine) + if engine != "redis" && engine != "valkey" { + continue + } + + clusterName := pointer.GetString(rg.ReplicationGroupId) + + // Skip clusters with authentication enabled (no credentials support). + if rg.AuthTokenEnabled != nil && *rg.AuthTokenEnabled { + d.l.Debugf("Skipping %s: AUTH token enabled", clusterName) + continue + } + if len(rg.UserGroupIds) > 0 { + d.l.Debugf("Skipping %s: ACL user groups configured", clusterName) + continue + } + + // Check tags for pmm_enable=true and extract Environment. + // On error we mark the region as incomplete and skip this cluster: + // we can't tell whether it's tagged, and silently treating the + // unknown as "not tagged" would let stale-removal delete a + // legitimately-managed service. + tags, err := d.checkTags(ctx, client, rg) + if err != nil { + d.l.Warnf("Region %s cluster %s: ListTagsForResource failed: %v", region, clusterName, err) + complete = false + continue + } + if !tags.enabled { + continue + } + + nodeType := pointer.GetString(rg.CacheNodeType) + tls := rg.TransitEncryptionEnabled != nil && *rg.TransitEncryptionEnabled + + // Cluster Mode Enabled: use the ConfigurationEndpoint (covers all shards). + if rg.ClusterEnabled != nil && *rg.ClusterEnabled && rg.ConfigurationEndpoint != nil { + az := "" + if len(rg.NodeGroups) > 0 && len(rg.NodeGroups[0].NodeGroupMembers) > 0 { + az = pointer.GetString(rg.NodeGroups[0].NodeGroupMembers[0].PreferredAvailabilityZone) + } + + instances = append(instances, discoveredInstance{ + Region: region, + AZ: az, + ClusterID: clusterName, + NodeType: nodeType, + Address: pointer.GetString(rg.ConfigurationEndpoint.Address), + Port: pointer.GetInt32(rg.ConfigurationEndpoint.Port), + Engine: engine, + TLS: tls, + Environment: tags.environment, + Role: "cluster", + }) + continue + } + + // Cluster Mode Disabled: add primary (writer) and reader endpoints per shard. + for _, ng := range rg.NodeGroups { + az := "" + if len(ng.NodeGroupMembers) > 0 { + az = pointer.GetString(ng.NodeGroupMembers[0].PreferredAvailabilityZone) + } + + if ng.PrimaryEndpoint != nil { + instances = append(instances, discoveredInstance{ + Region: region, + AZ: az, + ClusterID: clusterName, + NodeType: nodeType, + Address: pointer.GetString(ng.PrimaryEndpoint.Address), + Port: pointer.GetInt32(ng.PrimaryEndpoint.Port), + Engine: engine, + TLS: tls, + Environment: tags.environment, + Role: "primary", + }) + } + + if ng.ReaderEndpoint != nil { + instances = append(instances, discoveredInstance{ + Region: region, + AZ: az, + ClusterID: clusterName, + NodeType: nodeType, + Address: pointer.GetString(ng.ReaderEndpoint.Address), + Port: pointer.GetInt32(ng.ReaderEndpoint.Port), + Engine: engine, + TLS: tls, + Environment: tags.environment, + Role: "reader", + }) + } + } + } + } + + return instances, complete +} + +// tagResult holds the result of a tag check. +type tagResult struct { + enabled bool + environment string +} + +// checkTags checks if a replication group has the pmm_enable=true tag and extracts the Environment tag. +// +// A non-nil error means the AWS call failed; callers must treat the result as +// unknown (not as "not tagged") to avoid false stale-removals. +func (d *ElastiCacheDiscovery) checkTags(ctx context.Context, client *elasticache.Client, rg ectypes.ReplicationGroup) (tagResult, error) { + if rg.ARN == nil { + return tagResult{}, nil + } + + resp, err := client.ListTagsForResource(ctx, &elasticache.ListTagsForResourceInput{ + ResourceName: rg.ARN, + }) + if err != nil { + return tagResult{}, fmt.Errorf("list tags for %s: %w", pointer.GetString(rg.ReplicationGroupId), err) + } + + result := tagResult{} + for _, tag := range resp.TagList { + key := pointer.GetString(tag.Key) + value := pointer.GetString(tag.Value) + if key == elasticacheTagKey && value == elasticacheTagValue { + result.enabled = true + } + if key == "Environment" { + result.environment = value + } + } + return result, nil +} + +// findManagedServices returns all Valkey services in the inventory that were added by auto-discovery. +func (d *ElastiCacheDiscovery) findManagedServices() ([]*models.Service, error) { + valkeyType := models.ValkeyServiceType + allServices, err := models.FindServices(d.db.Querier, models.ServiceFilters{ + ServiceType: &valkeyType, + }) + if err != nil { + return nil, err + } + + var managed []*models.Service + for _, svc := range allServices { + labels, err := svc.GetCustomLabels() + if err != nil { + continue + } + if labels["managed_by"] == elasticacheManagedByLabel { + managed = append(managed, svc) + } + } + return managed, nil +} + +// addInstance creates a RemoteElastiCacheNode + ValkeyService + ValkeyExporter for a discovered instance. +func (d *ElastiCacheDiscovery) addInstance(ctx context.Context, inst discoveredInstance) error { + serviceName := fmt.Sprintf("elasticache-%s", inst.ClusterID) + if inst.Role == "reader" { + serviceName = fmt.Sprintf("elasticache-%s-reader", inst.ClusterID) + } + d.l.Infof("ADD %s [%s] %s:%d (env=%s)", serviceName, inst.Role, inst.Address, inst.Port, inst.Environment) + + pmmAgentID := models.PMMServerAgentID + + return d.db.InTransactionContext(ctx, nil, func(tx *reform.TX) error { + node, err := models.CreateNode(tx.Querier, models.RemoteElastiCacheNodeType, &models.CreateNodeParams{ + NodeName: serviceName, + NodeModel: inst.NodeType, + AZ: inst.AZ, + InstanceID: inst.ClusterID, + Address: inst.Address, + Region: &inst.Region, + CustomLabels: map[string]string{ + "managed_by": elasticacheManagedByLabel, + "source": "elasticache", + }, + }) + if err != nil { + return fmt.Errorf("create node: %w", err) + } + + service, err := models.AddNewService(tx.Querier, models.ValkeyServiceType, &models.AddDBMSServiceParams{ + ServiceName: serviceName, + NodeID: node.NodeID, + Environment: inst.Environment, + Cluster: inst.ClusterID, + Address: &inst.Address, + Port: pointer.ToUint16(uint16(inst.Port)), //nolint:gosec,modernize + CustomLabels: map[string]string{ + "managed_by": elasticacheManagedByLabel, + "source": "elasticache", + "engine": inst.Engine, + "role": inst.Role, + }, + }) + if err != nil { + return fmt.Errorf("add service: %w", err) + } + + _, err = models.CreateAgent(tx.Querier, models.ValkeyExporterType, &models.CreateAgentParams{ + PMMAgentID: pmmAgentID, + ServiceID: service.ServiceID, + TLS: inst.TLS, + ExporterOptions: models.ExporterOptions{ + PushMetrics: true, + }, + }) + if err != nil { + return fmt.Errorf("create agent: %w", err) + } + + d.state.RequestStateUpdate(ctx, pmmAgentID) + return nil + }) +} + +// removeService removes a service, its agents, and its node. +func (d *ElastiCacheDiscovery) removeService(ctx context.Context, svc *models.Service) error { + d.l.Infof("DEL %s (%s)", svc.ServiceName, pointer.GetString(svc.Address)) + + return d.db.InTransactionContext(ctx, nil, func(tx *reform.TX) error { + agents, err := models.FindAgents(tx.Querier, models.AgentFilters{ServiceID: svc.ServiceID}) + if err != nil { + return err + } + for _, agent := range agents { + if _, err := models.RemoveAgent(tx.Querier, agent.AgentID, models.RemoveRestrict); err != nil { + return err + } + if agent.PMMAgentID != nil { + d.state.RequestStateUpdate(ctx, pointer.GetString(agent.PMMAgentID)) + } + } + + nodeID := svc.NodeID + + if err := models.RemoveService(tx.Querier, svc.ServiceID, models.RemoveCascade); err != nil { + return err + } + + node, err := models.FindNodeByID(tx.Querier, nodeID) + if err != nil { + return err + } + if node.NodeType == models.RemoteElastiCacheNodeType { + if err := models.RemoveNode(tx.Querier, node.NodeID, models.RemoveCascade); err != nil { + return err + } + } + + return nil + }) +} diff --git a/managed/services/management/elasticache_discovery_test.go b/managed/services/management/elasticache_discovery_test.go new file mode 100644 index 00000000000..1a11c933d7a --- /dev/null +++ b/managed/services/management/elasticache_discovery_test.go @@ -0,0 +1,189 @@ +// Copyright (C) 2023 Percona LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package management + +import ( + "context" + "testing" + + "github.com/AlekSi/pointer" + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gopkg.in/reform.v1" + "gopkg.in/reform.v1/dialects/postgresql" + + "github.com/percona/pmm/managed/models" + "github.com/percona/pmm/managed/utils/testdb" + "github.com/percona/pmm/managed/utils/tests" + "github.com/percona/pmm/utils/logger" +) + +func TestElastiCacheDiscovery(t *testing.T) { + t.Run("FindManagedServices", func(t *testing.T) { + t.Run("NoServices", func(t *testing.T) { + _ = logger.Set(t.Context(), t.Name()) + uuid.SetRand(&tests.IDReader{}) + t.Cleanup(func() { uuid.SetRand(nil) }) + + sqlDB := testdb.Open(t, models.SetupFixtures, nil) + t.Cleanup(func() { require.NoError(t, sqlDB.Close()) }) + db := reform.NewDB(sqlDB, postgresql.Dialect, reform.NewPrintfLogger(t.Logf)) + + state := &mockAgentsStateUpdater{} + state.Test(t) + t.Cleanup(func() { state.AssertExpectations(t) }) + + d := NewElastiCacheDiscovery(db, state) + managed, err := d.findManagedServices() + require.NoError(t, err) + assert.Empty(t, managed) + }) + + t.Run("OnlyManagedServicesReturned", func(t *testing.T) { + ctx := logger.Set(t.Context(), t.Name()) + _ = ctx + uuid.SetRand(&tests.IDReader{}) + t.Cleanup(func() { uuid.SetRand(nil) }) + + sqlDB := testdb.Open(t, models.SetupFixtures, nil) + t.Cleanup(func() { require.NoError(t, sqlDB.Close()) }) + db := reform.NewDB(sqlDB, postgresql.Dialect, reform.NewPrintfLogger(t.Logf)) + + state := &mockAgentsStateUpdater{} + state.Test(t) + t.Cleanup(func() { state.AssertExpectations(t) }) + + // Create a node for the services. + node, err := models.CreateNode(db.Querier, models.RemoteElastiCacheNodeType, &models.CreateNodeParams{ + NodeName: "test-node", + Address: "test-address", + Region: pointer.ToString("us-east-1"), //nolint:modernize + }) + require.NoError(t, err) + + // Create a managed Valkey service (with managed_by label). + _, err = models.AddNewService(db.Querier, models.ValkeyServiceType, &models.AddDBMSServiceParams{ + ServiceName: "managed-valkey", + NodeID: node.NodeID, + Address: pointer.ToString("managed.cache.amazonaws.com"), //nolint:modernize + Port: pointer.ToUint16(6379), + CustomLabels: map[string]string{ + "managed_by": elasticacheManagedByLabel, + "source": "elasticache", + }, + }) + require.NoError(t, err) + + // Create a non-managed Valkey service (no managed_by label). + _, err = models.AddNewService(db.Querier, models.ValkeyServiceType, &models.AddDBMSServiceParams{ + ServiceName: "manual-valkey", + NodeID: node.NodeID, + Address: pointer.ToString("manual.cache.amazonaws.com"), //nolint:modernize + Port: pointer.ToUint16(6380), + }) + require.NoError(t, err) + + d := NewElastiCacheDiscovery(db, state) + managed, err := d.findManagedServices() + require.NoError(t, err) + require.Len(t, managed, 1) + assert.Equal(t, "managed-valkey", managed[0].ServiceName) + }) + }) + + t.Run("AddAndRemoveInstance", func(t *testing.T) { + ctx := logger.Set(t.Context(), t.Name()) + uuid.SetRand(&tests.IDReader{}) + t.Cleanup(func() { uuid.SetRand(nil) }) + + sqlDB := testdb.Open(t, models.SetupFixtures, nil) + t.Cleanup(func() { require.NoError(t, sqlDB.Close()) }) + db := reform.NewDB(sqlDB, postgresql.Dialect, reform.NewPrintfLogger(t.Logf)) + + state := &mockAgentsStateUpdater{} + state.Test(t) + t.Cleanup(func() { state.AssertExpectations(t) }) + + d := NewElastiCacheDiscovery(db, state) + + // Add an instance. + state.On("RequestStateUpdate", ctx, models.PMMServerAgentID) + inst := discoveredInstance{ + Region: "us-east-1", + AZ: "us-east-1a", + ClusterID: "my-cluster", + NodeType: "cache.r6g.large", + Address: "my-cluster.abc123.use1.cache.amazonaws.com", + Port: 6379, + Engine: "valkey", + TLS: false, + Environment: "production", + Role: "primary", + } + err := d.addInstance(ctx, inst) + require.NoError(t, err) + + // Verify a managed service was created. + managed, err := d.findManagedServices() + require.NoError(t, err) + require.Len(t, managed, 1) + assert.Equal(t, "elasticache-my-cluster", managed[0].ServiceName) + assert.Equal(t, "my-cluster.abc123.use1.cache.amazonaws.com", pointer.GetString(managed[0].Address)) + + // Remove the service. + err = d.removeService(ctx, managed[0]) + require.NoError(t, err) + + // Verify it's gone. + managed, err = d.findManagedServices() + require.NoError(t, err) + assert.Empty(t, managed) + }) + + t.Run("AddReaderInstance", func(t *testing.T) { + ctx := logger.Set(context.Background(), t.Name()) + uuid.SetRand(&tests.IDReader{}) + t.Cleanup(func() { uuid.SetRand(nil) }) + + sqlDB := testdb.Open(t, models.SetupFixtures, nil) + t.Cleanup(func() { require.NoError(t, sqlDB.Close()) }) + db := reform.NewDB(sqlDB, postgresql.Dialect, reform.NewPrintfLogger(t.Logf)) + + state := &mockAgentsStateUpdater{} + state.Test(t) + t.Cleanup(func() { state.AssertExpectations(t) }) + + d := NewElastiCacheDiscovery(db, state) + + state.On("RequestStateUpdate", ctx, models.PMMServerAgentID) + inst := discoveredInstance{ + Region: "us-east-1", + ClusterID: "my-cluster", + Address: "my-cluster-ro.abc123.use1.cache.amazonaws.com", + Port: 6379, + Engine: "redis", + Role: "reader", + } + err := d.addInstance(ctx, inst) + require.NoError(t, err) + + managed, err := d.findManagedServices() + require.NoError(t, err) + require.Len(t, managed, 1) + assert.Equal(t, "elasticache-my-cluster-reader", managed[0].ServiceName) + }) +} diff --git a/managed/services/management/elasticache_test.go b/managed/services/management/elasticache_test.go new file mode 100644 index 00000000000..f20bdddb37a --- /dev/null +++ b/managed/services/management/elasticache_test.go @@ -0,0 +1,76 @@ +// Copyright (C) 2023 Percona LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package management + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + managementv1 "github.com/percona/pmm/api/management/v1" +) + +func TestListElastiCacheRegions(t *testing.T) { + t.Run("DefaultPartition", func(t *testing.T) { + regions := listElastiCacheRegions([]string{"aws"}) + require.NotEmpty(t, regions) + assert.Contains(t, regions, "us-east-1") + assert.Contains(t, regions, "eu-central-1") + }) + + t.Run("GovCloudPartition", func(t *testing.T) { + regions := listElastiCacheRegions([]string{"aws-us-gov"}) + require.NotEmpty(t, regions) + assert.Contains(t, regions, "us-gov-west-1") + }) + + t.Run("MultiplePartitions", func(t *testing.T) { + regions := listElastiCacheRegions([]string{"aws", "aws-cn"}) + require.NotEmpty(t, regions) + assert.Contains(t, regions, "us-east-1") + assert.Contains(t, regions, "cn-north-1") + }) + + t.Run("EmptyPartitions", func(t *testing.T) { + regions := listElastiCacheRegions([]string{}) + assert.Empty(t, regions) + }) + + t.Run("UnknownPartition", func(t *testing.T) { + regions := listElastiCacheRegions([]string{"unknown"}) + assert.Empty(t, regions) + }) +} + +func TestElastiCacheEngineMap(t *testing.T) { + t.Run("Redis", func(t *testing.T) { + engine, ok := elasticacheEngines["redis"] + assert.True(t, ok) + assert.Equal(t, managementv1.DiscoverElastiCacheEngine_DISCOVER_ELASTI_CACHE_ENGINE_REDIS, engine) + }) + + t.Run("Valkey", func(t *testing.T) { + engine, ok := elasticacheEngines["valkey"] + assert.True(t, ok) + assert.Equal(t, managementv1.DiscoverElastiCacheEngine_DISCOVER_ELASTI_CACHE_ENGINE_VALKEY, engine) + }) + + t.Run("UnsupportedEngine", func(t *testing.T) { + _, ok := elasticacheEngines["memcached"] + assert.False(t, ok) + }) +} diff --git a/managed/services/management/service.go b/managed/services/management/service.go index b616154afb4..5dbfea7dec7 100644 --- a/managed/services/management/service.go +++ b/managed/services/management/service.go @@ -113,6 +113,8 @@ func (s *ManagementService) AddService(ctx context.Context, req *managementv1.Ad return s.addRDS(ctx, req.GetRds()) case *managementv1.AddServiceRequest_Valkey: return s.addValkey(ctx, req.GetValkey()) + case *managementv1.AddServiceRequest_Elasticache: + return s.addElastiCache(ctx, req.GetElasticache()) default: return nil, status.Error(codes.InvalidArgument, "invalid service type") } @@ -313,8 +315,8 @@ func (s *ManagementService) RemoveService(ctx context.Context, req *managementv1 return err } - // For RDS and Azure we also want to remove the node. - if node.NodeType == models.RemoteRDSNodeType || node.NodeType == models.RemoteAzureDatabaseNodeType { + // For RDS, Azure and ElastiCache we also want to remove the node. + if node.NodeType == models.RemoteRDSNodeType || node.NodeType == models.RemoteAzureDatabaseNodeType || node.NodeType == models.RemoteElastiCacheNodeType { agents, err = models.FindAgents(tx.Querier, models.AgentFilters{NodeID: node.NodeID}) if err != nil { return err diff --git a/managed/services/management/service_test.go b/managed/services/management/service_test.go index 310c1d264bb..7d6b6443c92 100644 --- a/managed/services/management/service_test.go +++ b/managed/services/management/service_test.go @@ -20,6 +20,7 @@ import ( "fmt" "testing" + "github.com/AlekSi/pointer" "github.com/google/uuid" "github.com/prometheus/common/model" "github.com/stretchr/testify/assert" @@ -272,6 +273,48 @@ func TestServiceService(t *testing.T) { _, err = models.FindNodeByID(s.db.Querier, node.NodeID) tests.AssertGRPCError(t, status.New(codes.NotFound, fmt.Sprintf(`Node with ID "%s" not found.`, node.NodeID)), err) }) + + t.Run("ElastiCache", func(t *testing.T) { + ctx, s, teardown, _ := setup(t) + defer teardown(t) + + node, err := models.CreateNode(s.db.Querier, models.RemoteElastiCacheNodeType, &models.CreateNodeParams{ + NodeName: "test-elasticache", + Address: "test-address", + Region: pointer.ToString("us-east-1"), //nolint:modernize + }) + require.NoError(t, err) + + service, err := models.AddNewService(s.db.Querier, models.ValkeyServiceType, &models.AddDBMSServiceParams{ + ServiceName: "test-valkey", + NodeID: node.NodeID, + Address: pointer.ToString("test-address"), //nolint:modernize + Port: pointer.ToUint16(6379), + }) + require.NoError(t, err) + + pmmAgent, err := models.CreatePMMAgent(s.db.Querier, models.PMMServerNodeID, nil) + require.NoError(t, err) + + valkeyExporter, err := models.CreateAgent(s.db.Querier, models.ValkeyExporterType, &models.CreateAgentParams{ + PMMAgentID: pmmAgent.AgentID, + ServiceID: service.ServiceID, + }) + require.NoError(t, err) + + s.state.(*mockAgentsStateUpdater).On("RequestStateUpdate", ctx, pmmAgent.AgentID) + _, err = s.RemoveService(ctx, &managementv1.RemoveServiceRequest{ServiceId: service.ServiceName, ServiceType: inventoryv1.ServiceType_SERVICE_TYPE_VALKEY_SERVICE}) + require.NoError(t, err) + + _, err = models.FindServiceByID(s.db.Querier, service.ServiceID) + tests.AssertGRPCError(t, status.New(codes.NotFound, fmt.Sprintf(`Service with ID "%s" not found.`, service.ServiceID)), err) + + _, err = models.FindAgentByID(s.db.Querier, valkeyExporter.AgentID) + tests.AssertGRPCError(t, status.New(codes.NotFound, fmt.Sprintf(`Agent with ID %s not found.`, valkeyExporter.AgentID)), err) + + _, err = models.FindNodeByID(s.db.Querier, node.NodeID) + tests.AssertGRPCError(t, status.New(codes.NotFound, fmt.Sprintf(`Node with ID "%s" not found.`, node.NodeID)), err) + }) }) t.Run("List", func(t *testing.T) { @@ -403,6 +446,50 @@ func TestServiceService(t *testing.T) { assert.Len(t, response.Services[1].Agents, 2) }) + t.Run("ElastiCache", func(t *testing.T) { + ctx, s, teardown, _ := setup(t) + t.Cleanup(func() { teardown(t) }) + + node, err := models.CreateNode(s.db.Querier, models.RemoteElastiCacheNodeType, &models.CreateNodeParams{ + NodeName: "test-elasticache", + Address: "test-address", + Region: pointer.ToString("us-east-1"), //nolint:modernize + }) + require.NoError(t, err) + + service, err := models.AddNewService(s.db.Querier, models.ValkeyServiceType, &models.AddDBMSServiceParams{ + ServiceName: "test-valkey", + NodeID: node.NodeID, + Address: pointer.ToString("test-address"), //nolint:modernize + Port: pointer.ToUint16(6379), + }) + require.NoError(t, err) + + pmmAgent, err := models.CreatePMMAgent(s.db.Querier, models.PMMServerNodeID, nil) + require.NoError(t, err) + + valkeyExporter, err := models.CreateAgent(s.db.Querier, models.ValkeyExporterType, &models.CreateAgentParams{ + PMMAgentID: pmmAgent.AgentID, + ServiceID: service.ServiceID, + }) + require.NoError(t, err) + + s.vmClient.(*mockVictoriaMetricsClient).On("Query", ctx, mock.Anything, mock.Anything).Return(model.Vector{}, nil, nil).Once() + s.r.(*mockAgentsRegistry).On("IsConnected", models.PMMServerAgentID).Return(true).Once() + s.r.(*mockAgentsRegistry).On("IsConnected", pmmAgent.AgentID).Return(true).Once() + s.r.(*mockAgentsRegistry).On("IsConnected", pgExporterID).Return(false).Once() + s.r.(*mockAgentsRegistry).On("IsConnected", pgStatStatementID).Return(false).Once() + s.r.(*mockAgentsRegistry).On("IsConnected", PMMAgentID).Return(false) + s.r.(*mockAgentsRegistry).On("IsConnected", valkeyExporter.AgentID).Return(false).Once() + + response, err := s.ListServices(ctx, &managementv1.ListServicesRequest{}) + + require.NoError(t, err) + assert.Len(t, response.Services, 2) // PMM Server PostgreSQL service, Valkey service + assert.Len(t, response.Services[0].Agents, 4) + assert.Len(t, response.Services[1].Agents, 1) + }) + t.Run("Azure", func(t *testing.T) { ctx, s, teardown, _ := setup(t) t.Cleanup(func() { teardown(t) })