// initOAuthAuthorizationServerMetadataRoute initializes an HTTP endpoint for OAuth 2.0 Authorization Server Metadata discovery // https://tools.ietf.org/id/draft-ietf-oauth-discovery-04.html#rfc.section.2 // masterPublicURL should be internally and externally routable to allow all users to discover this information func initOAuthAuthorizationServerMetadataRoute(apiContainer *genericmux.APIContainer, path, masterPublicURL string) { // Build OAuth metadata once metadata, err := json.MarshalIndent(discovery.Get(masterPublicURL, OpenShiftOAuthAuthorizeURL(masterPublicURL), OpenShiftOAuthTokenURL(masterPublicURL)), "", " ") if err != nil { glog.Errorf("Unable to initialize OAuth authorization server metadata route: %v", err) return } secretContainer := restful.Container{ ServeMux: apiContainer.SecretRoutes.(*http.ServeMux), // we know it's a *http.ServeMux. In kube 1.6, the type will actually be correct. } // Set up a service to return the OAuth metadata. ws := new(restful.WebService) ws.Path(path) ws.Doc("OAuth 2.0 Authorization Server Metadata") ws.Route( ws.GET("/").To(func(_ *restful.Request, resp *restful.Response) { writeJSON(resp, metadata) }). Doc("get the server's OAuth 2.0 Authorization Server Metadata"). Operation("getOAuthAuthorizationServerMetadata"). Produces(restful.MIME_JSON)) secretContainer.Add(ws) }
// Register adds the web service wrapped by the Service to the supplied // container. If the supplied container is nil, then the default container is // used, instead. func (s *Service) Register(container *restful.Container) { if container == nil { container = restful.DefaultContainer } container.Add(s.WebService) }
// Register the mainApi on the specified endpoint. func (a *Api) Register(container *restful.Container) { ws := new(restful.WebService) ws.Path("/api/v1/metric-export"). Doc("Exports the latest point for all Heapster metrics"). Produces(restful.MIME_JSON) ws.Route(ws.GET(""). To(a.exportMetrics). Doc("export the latest data point for all metrics"). Operation("exportMetrics"). Writes([]*types.Timeseries{})) container.Add(ws) ws = new(restful.WebService) ws.Path("/api/v1/metric-export-schema"). Doc("Schema for metrics exported by heapster"). Produces(restful.MIME_JSON) ws.Route(ws.GET(""). To(a.exportMetricsSchema). Doc("export the schema for all metrics"). Operation("exportmetricsSchema"). Writes(types.TimeseriesSchema{})) container.Add(ws) if a.metricSink != nil { a.RegisterModel(container) } if a.historicalSource != nil { a.RegisterHistorical(container) } }
// RegisterMetrics registers the Metrics API endpoints. // All endpoints that end with a {metric-name} also receive a start time query parameter. // The start and end times should be specified as a string, formatted according to RFC 3339. // These apis are experimental, so they may change or disappear in the future. func (a *Api) RegisterMetrics(container *restful.Container) { ws := new(restful.WebService) ws. Path("/experimental/v2"). Doc("Root endpoint of the stats model"). Consumes("*/*"). Produces(restful.MIME_JSON) ws.Route(ws.GET("/nodeMetrics/derived/"). To(a.derivedNodeMetricsList). Filter(compressionFilter). Doc("Get a list of all available metrics for all nodes"). Writes([]types.DerivedNodeMetrics{}). Operation("derivedNodeMetricsList")) ws.Route(ws.GET("/nodeMetrics/derived/{node-name}"). To(a.derivedNodeMetrics). Filter(compressionFilter). Doc("Get a list of all raw metrics for a Node entity"). Writes(types.DerivedNodeMetrics{}). Operation("derivedNodeMetrics"). Param(ws.PathParameter("node-name", "The name of the node to look up").DataType("string"))) container.Add(ws) }
func (a *Api) Register(container *restful.Container) { ws := new(restful.WebService) ws.Path("/apis/metrics/v1alpha1"). Doc("Root endpoint of metrics API"). Produces(restful.MIME_JSON) ws.Route(ws.GET("/nodes/"). To(a.nodeMetricsList). Doc("Get a list of metrics for all available nodes."). Operation("nodeMetricsList")) ws.Route(ws.GET("/nodes/{node-name}/"). To(a.nodeMetrics). Doc("Get a list of all available metrics for the specified node."). Operation("nodeMetrics"). Param(ws.PathParameter("node-name", "The name of the node to lookup").DataType("string"))) ws.Route(ws.GET("/namespaces/{namespace-name}/pods/"). To(a.podMetricsList). Doc("Get a list of metrics for all available pods in the specified namespace."). Operation("podMetricsList"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string"))). Param(ws.QueryParameter("labelSelector", "A selector to restrict the list of returned objects by their labels. Defaults to everything.").DataType("string")) ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/"). To(a.podMetrics). Doc("Get metrics for the specified pod in the specified namespace."). Operation("podMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to lookup").DataType("string"))) container.Add(ws) }
// RegisterHistorical registers the Historical API endpoints. It will register the same endpoints // as those in the model API, plus endpoints for aggregation retrieval, and endpoints to retrieve pod // metrics by using the pod id. func (normalApi *Api) RegisterHistorical(container *restful.Container) { ws := new(restful.WebService) ws.Path("/api/v1/historical"). Doc("Root endpoint of the historical access API"). Consumes("*/*"). Produces(restful.MIME_JSON) a := &HistoricalApi{normalApi} addClusterMetricsRoutes(a, ws) addAggregationRoutes(a, ws) // register the endpoint for fetching raw metrics based on pod id if a.isRunningInKubernetes() { // The /pod-id/{pod-id}/metrics-aggregated/{aggregations}/{metric-name} endpoint exposes // some aggregations for a Pod entity of the historical API. ws.Route(ws.GET("/pod-id/{pod-id}/metrics/{metric-name:*}"). To(metrics.InstrumentRouteFunc("podMetrics", a.podMetrics)). Doc("Export some pod-level metric aggregations"). Operation("podAggregations"). Param(ws.PathParameter("pod-id", "The UID of the pod to lookup").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) // The /pod-id/{pod-id}/containers/{container-name}/metrics-aggregated/{aggregations}/{metric-name} endpoint exposes // some aggregations for a Container entity of the historical API. ws.Route(ws.GET("/pod-id/{pod-id}/containers/{container-name}/metrics/{metric-name:*}"). To(metrics.InstrumentRouteFunc("podContainerMetrics", a.podContainerMetrics)). Doc("Export some aggregations for a Pod Container"). Operation("podContainerAggregations"). Param(ws.PathParameter("pod-id", "The uid of the pod to use").DataType("string")). Param(ws.PathParameter("container-name", "The name of the namespace to use").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) // The /pod-id-list/{pod-id-list}/metrics-aggregated/{aggregations}/{metric-name} endpoint exposes // metrics for a list of pod ids of the historical API. ws.Route(ws.GET("/pod-id-list/{pod-id-list}/metrics/{metric-name:*}"). To(metrics.InstrumentRouteFunc("podListAggregations", a.podListMetrics)). Doc("Export an aggregation for all pods from the given list"). Operation("podListAggregations"). Param(ws.PathParameter("pod-id-list", "Comma separated list of pod UIDs to lookup").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResultList{})) } container.Add(ws) }
func register(container *restful.Container) { restful.RegisterEntityAccessor(MIME_MSGPACK, NewEntityAccessorMsgPack()) ws := new(restful.WebService) ws. Path("/test"). Consumes(restful.MIME_JSON, MIME_MSGPACK). Produces(restful.MIME_JSON, MIME_MSGPACK) // route user api ws.Route(ws.POST("/msgpack"). To(do). Reads(user{}). Writes(userResponse{})) container.Add(ws) }
func (c *MasterConfig) InstallProtectedAPI(container *restful.Container) ([]string, error) { // initialize OpenShift API storage := c.GetRestStorage() messages := []string{} legacyAPIVersions := []string{} currentAPIVersions := []string{} if configapi.HasOpenShiftAPILevel(c.Options, OpenShiftAPIV1) { if err := c.apiLegacyV1(storage).InstallREST(container); err != nil { glog.Fatalf("Unable to initialize v1 API: %v", err) } messages = append(messages, fmt.Sprintf("Started Origin API at %%s%s", OpenShiftAPIPrefixV1)) currentAPIVersions = append(currentAPIVersions, OpenShiftAPIV1) } var root *restful.WebService for _, service := range container.RegisteredWebServices() { switch service.RootPath() { case "/": root = service case OpenShiftAPIPrefixV1: service.Doc("OpenShift REST API, version v1").ApiVersion("v1") } } if root == nil { root = new(restful.WebService) container.Add(root) } // The old API prefix must continue to return 200 (with an empty versions // list) for backwards compatibility, even though we won't service any other // requests through the route. Take care when considering whether to delete // this route. initAPIVersionRoute(root, LegacyOpenShiftAPIPrefix, legacyAPIVersions...) initAPIVersionRoute(root, OpenShiftAPIPrefix, currentAPIVersions...) initControllerRoutes(root, "/controllers", c.Options.Controllers != configapi.ControllersDisabled, c.ControllerPlug) initHealthCheckRoute(root, "/healthz") initReadinessCheckRoute(root, "/healthz/ready", c.ProjectAuthorizationCache.ReadyForAccess) initVersionRoute(container, "/version/openshift") // Set up OAuth metadata only if we are configured to use OAuth if c.Options.OAuthConfig != nil { initOAuthAuthorizationServerMetadataRoute(container, oauthMetadataEndpoint, c.Options.OAuthConfig.MasterPublicURL) } return messages, nil }
func (c *MasterConfig) InstallProtectedAPI(container *restful.Container) []string { // initialize OpenShift API storage := c.GetRestStorage() messages := []string{} legacyAPIVersions := []string{} currentAPIVersions := []string{} if configapi.HasOpenShiftAPILevel(c.Options, OpenShiftAPIV1Beta3) { if err := c.api_v1beta3(storage).InstallREST(container); err != nil { glog.Fatalf("Unable to initialize v1beta3 API: %v", err) } messages = append(messages, fmt.Sprintf("Started Origin API at %%s%s", OpenShiftAPIPrefixV1Beta3)) legacyAPIVersions = append(legacyAPIVersions, OpenShiftAPIV1Beta3) } if configapi.HasOpenShiftAPILevel(c.Options, OpenShiftAPIV1) { if err := c.api_v1(storage).InstallREST(container); err != nil { glog.Fatalf("Unable to initialize v1 API: %v", err) } messages = append(messages, fmt.Sprintf("Started Origin API at %%s%s", OpenShiftAPIPrefixV1)) currentAPIVersions = append(currentAPIVersions, OpenShiftAPIV1) } var root *restful.WebService for _, service := range container.RegisteredWebServices() { switch service.RootPath() { case "/": root = service case OpenShiftAPIPrefixV1Beta3: service.Doc("OpenShift REST API, version v1beta3").ApiVersion("v1beta3") case OpenShiftAPIPrefixV1: service.Doc("OpenShift REST API, version v1").ApiVersion("v1") } } if root == nil { root = new(restful.WebService) container.Add(root) } initAPIVersionRoute(root, LegacyOpenShiftAPIPrefix, legacyAPIVersions...) initAPIVersionRoute(root, OpenShiftAPIPrefix, currentAPIVersions...) initControllerRoutes(root, "/controllers", c.Options.Controllers != configapi.ControllersDisabled, c.ControllerPlug) initHealthCheckRoute(root, "/healthz") initReadinessCheckRoute(root, "/healthz/ready", c.ProjectAuthorizationCache.ReadyForAccess) return messages }
// initReadinessCheckRoute initializes an HTTP endpoint for readiness checking func initVersionRoute(container *restful.Container, path string) { // Set up a service to return the git code version. versionWS := new(restful.WebService) versionWS.Path(path) versionWS.Doc("git code version from which this is built") versionWS.Route( versionWS.GET("/").To(handleVersion). Doc("get the code version"). Operation("getCodeVersion"). Produces(restful.MIME_JSON). Consumes(restful.MIME_JSON)) container.Add(versionWS) }
// RegisterModel registers the Model API endpoints. // All endpoints that end with a {metric-name} also receive a start time query parameter. // The start and end times should be specified as a string, formatted according to RFC 3339. func (a *Api) RegisterModel(container *restful.Container) { ws := new(restful.WebService) ws.Path("/api/v1/model"). Doc("Root endpoint of the stats model"). Consumes("*/*"). Produces(restful.MIME_JSON) addClusterMetricsRoutes(a, ws) ws.Route(ws.GET("/debug/allkeys"). To(metrics.InstrumentRouteFunc("debugAllKeys", a.allKeys)). Doc("Get keys of all metric sets available"). Operation("debugAllKeys")) container.Add(ws) }
func (c *ProxyConfig) InstallAPI(container *restful.Container) ([]string, error) { kubeAddr, err := url.Parse(c.ClientConfig.Host) if err != nil { return nil, err } proxy, err := httpproxy.NewUpgradeAwareSingleHostReverseProxy(c.ClientConfig, kubeAddr) if err != nil { return nil, fmt.Errorf("Unable to initialize the Kubernetes proxy: %v", err) } container.Handle("/api/", proxy) return []string{ "Started Kubernetes proxy at %s/api/", }, nil }
// initOAuthAuthorizationServerMetadataRoute initializes an HTTP endpoint for OAuth 2.0 Authorization Server Metadata discovery // https://tools.ietf.org/id/draft-ietf-oauth-discovery-04.html#rfc.section.2 // masterPublicURL should be internally and externally routable to allow all users to discover this information func initOAuthAuthorizationServerMetadataRoute(container *restful.Container, path, masterPublicURL string) { // Build OAuth metadata once metadata, err := json.MarshalIndent(discovery.Get(masterPublicURL, OpenShiftOAuthAuthorizeURL(masterPublicURL), OpenShiftOAuthTokenURL(masterPublicURL)), "", " ") if err != nil { glog.Errorf("Unable to initialize OAuth authorization server metadata route: %v", err) return } // Set up a service to return the OAuth metadata. oauthWS := new(restful.WebService) oauthWS.Path(path) oauthWS.Doc("OAuth 2.0 Authorization Server Metadata") oauthWS.Route( oauthWS.GET("/").To(func(_ *restful.Request, resp *restful.Response) { writeJSON(resp, metadata) }). Doc("get the server's OAuth 2.0 Authorization Server Metadata"). Operation("getOAuthAuthorizationServerMetadata"). Produces(restful.MIME_JSON)) container.Add(oauthWS) }
// initVersionRoute initializes an HTTP endpoint for the server's version information. func initVersionRoute(container *restful.Container, path string) { // Build version info once versionInfo, err := json.MarshalIndent(version.Get(), "", " ") if err != nil { glog.Errorf("Unable to initialize version route: %v", err) return } // Set up a service to return the git code version. versionWS := new(restful.WebService) versionWS.Path(path) versionWS.Doc("git code version from which this is built") versionWS.Route( versionWS.GET("/").To(func(_ *restful.Request, resp *restful.Response) { writeJSON(resp, versionInfo) }). Doc("get the code version"). Operation("getCodeVersion"). Produces(restful.MIME_JSON)) container.Add(versionWS) }
// Register the Api on the specified endpoint. func (a *Api) Register(container *restful.Container) { ws := new(restful.WebService) ws. Path("/api/v1/metric-export"). Doc("Exports the latest point for all Heapster metrics"). Produces(restful.MIME_JSON) ws.Route(ws.GET(""). Filter(compressionFilter). To(a.exportMetrics). Doc("export the latest data point for all metrics"). Operation("exportMetrics"). Writes([]*Timeseries{})) container.Add(ws) ws = new(restful.WebService) ws.Path("/api/v1/metric-export-schema"). Doc("Schema for metrics exported by heapster"). Produces(restful.MIME_JSON) ws.Route(ws.GET(""). To(a.exportMetricsSchema). Doc("export the schema for all metrics"). Operation("exportmetricsSchema"). Writes(TimeseriesSchema{})) container.Add(ws) }
// Register the Api on the specified endpoint. func (a *Api) Register(container *restful.Container) { ws := new(restful.WebService) ws. Path("/api/v1/metric-export"). Doc("Exports the latest point for all Heapster metrics"). Produces(restful.MIME_JSON) ws.Route(ws.GET(""). Filter(compressionFilter). To(a.exportMetrics). Doc("export the latest data point for all metrics"). Operation("exportMetrics"). Writes([]*Timeseries{})) container.Add(ws) ws = new(restful.WebService) ws.Path("/api/v1/metric-export-schema"). Doc("Schema for metrics exported by heapster"). Produces(restful.MIME_JSON) ws.Route(ws.GET(""). To(a.exportMetricsSchema). Doc("export the schema for all metrics"). Operation("exportmetricsSchema"). Writes(TimeseriesSchema{})) container.Add(ws) ws = new(restful.WebService) ws.Path("/api/v1/sinks"). Doc("Configuration for Heapster sinks for exporting data"). Produces(restful.MIME_JSON) ws.Route(ws.POST(""). To(a.setSinks). Doc("set the current sinks"). Operation("setSinks"). Reads([]string{})) ws.Route(ws.GET(""). To(a.getSinks). Doc("get the current sinks"). Operation("getSinks"). Writes([]string{})) container.Add(ws) // Register the endpoints of the model a.RegisterModel(container) }
// RegisterModel registers the Model API endpoints. // All endpoints that end with a {metric-name} also receive a start time query parameter. // The start and end times should be specified as a string, formatted according to RFC 3339. func (a *Api) RegisterModel(container *restful.Container) { ws := new(restful.WebService) ws. Path("/api/v1/model"). Doc("Root endpoint of the stats model"). Consumes("*/*"). Produces(restful.MIME_JSON) // The / endpoint returns a list of all the entities that are available in the model ws.Route(ws.GET("/"). To(a.allEntities). Filter(compressionFilter). Doc("Get a list of all entities available in the model"). Operation("allEntities")) // The /metrics/ endpoint returns a list of all available metrics for the Cluster entity of the model. ws.Route(ws.GET("/metrics/"). To(a.availableMetrics). Filter(compressionFilter). Doc("Get a list of all available metrics for the Cluster entity"). Operation("availableMetrics")) // The /stats/ endpoint returns a list of all available stats for the Cluster entity of the model. ws.Route(ws.GET("/stats/"). To(a.clusterStats). Filter(compressionFilter). Doc("Get all available stats for the Cluster entity"). Operation("clusterStats")) // The /metrics/{metric-name} endpoint exposes an aggregated metric for the Cluster entity of the model. ws.Route(ws.GET("/metrics/{metric-name}"). To(a.clusterMetrics). Filter(compressionFilter). Doc("Export an aggregated cluster-level metric"). Operation("clusterMetrics"). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metric").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) // The /nodes/ endpoint returns a list of all Node entities in the cluster. ws.Route(ws.GET("/nodes/"). To(a.allNodes). Filter(compressionFilter). Doc("Get a list of all Nodes in the model"). Operation("allNodes"). Writes(types.MetricResult{})) // The /nodes/{node-name} endpoint returns a list of all available API paths for a Node entity. ws.Route(ws.GET("/nodes/{node-name}"). To(a.nodePaths). Filter(compressionFilter). Doc("Get a list of all available API paths for a Node entity"). Operation("nodePaths"). Param(ws.PathParameter("node-name", "The name of the node to lookup").DataType("string"))) // The /nodes/{node-name}/stats endpoint returns all available derived stats for a Node entity. ws.Route(ws.GET("/nodes/{node-name}/stats/"). To(a.nodeStats). Filter(compressionFilter). Doc("Get all available stats for a Node entity."). Operation("nodeStats"). Param(ws.PathParameter("node-name", "The name of the node to lookup").DataType("string"))) // The /nodes/{node-name}/metrics endpoint returns a list of all available metrics for a Node entity. ws.Route(ws.GET("/nodes/{node-name}/metrics/"). To(a.availableMetrics). Filter(compressionFilter). Doc("Get a list of all available metrics for a Node entity"). Operation("availableMetrics"). Param(ws.PathParameter("node-name", "The name of the node to lookup").DataType("string"))) // The /nodes/{node-name}/metrics/{metric-name} endpoint exposes a metric for a Node entity of the model. // The {node-name} parameter is the hostname of a specific node. ws.Route(ws.GET("/nodes/{node-name}/metrics/{metric-name}"). To(a.nodeMetrics). Filter(compressionFilter). Doc("Export a node-level metric"). Operation("nodeMetrics"). Param(ws.PathParameter("node-name", "The name of the node to lookup").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metric").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) if a.runningInKubernetes { // The /namespaces/ endpoint returns a list of all Namespace entities in the model. ws.Route(ws.GET("/namespaces/"). To(a.allNamespaces). Filter(compressionFilter). Doc("Get a list of all Namespaces in the model"). Operation("allNamespaces")) // The /namespaces/{namespace-name} endpoint returns a list of all available API Paths for a Namespace entity. ws.Route(ws.GET("/namespaces/{namespace-name}"). To(a.namespacePaths). Filter(compressionFilter). Doc("Get a list of all available API paths for a namespace entity"). Operation("namespacePaths"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string"))) // The /namespaces/{namespace-name}/stats endpoint returns all available derived stats for a Namespace entity. ws.Route(ws.GET("/namespaces/{namespace-name}/stats/"). To(a.namespaceStats). Filter(compressionFilter). Doc("Get all available stats for a Namespace entity."). Operation("namespaceStats"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string"))) // The /namespaces/{namespace-name}/metrics endpoint returns a list of all available metrics for a Namespace entity. ws.Route(ws.GET("/namespaces/{namespace-name}/metrics"). To(a.availableMetrics). Filter(compressionFilter). Doc("Get a list of all available metrics for a Namespace entity"). Operation("availableMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string"))) // The /namespaces/{namespace-name}/metrics/{metric-name} endpoint exposes an aggregated metrics // for a Namespace entity of the model. ws.Route(ws.GET("/namespaces/{namespace-name}/metrics/{metric-name}"). To(a.namespaceMetrics). Filter(compressionFilter). Doc("Export an aggregated namespace-level metric"). Operation("namespaceMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) // The /namespaces/{namespace-name}/pods endpoint returns a list of all Pod entities in the model, // under a specified namespace. ws.Route(ws.GET("/namespaces/{namespace-name}/pods"). To(a.allPods). Filter(compressionFilter). Doc("Get a list of all Pods in the model, belonging to the specified Namespace"). Operation("allPods"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string"))) // The /namespaces/{namespace-name}/pods/{pod-name} endpoint returns a list of all // API paths available for a pod ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}"). To(a.podPaths). Filter(compressionFilter). Doc("Get a list of all API paths available for a Pod entity"). Operation("podPaths"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to lookup").DataType("string"))) // The /namespaces/{namespace-name}/pods/{pod-name}/stats endpoint returns all available derived stats for a Pod entity. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/stats/"). To(a.podStats). Filter(compressionFilter). Doc("Get all available stats for a Pod entity."). Operation("podStats"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to lookup").DataType("string"))) // The /namespaces/{namespace-name}/pods/{pod-name}/metrics endpoint returns a list of all available metrics for a Pod entity. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/metrics"). To(a.availableMetrics). Filter(compressionFilter). Doc("Get a list of all available metrics for a Pod entity"). Operation("availableMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to lookup").DataType("string"))) // The /namespaces/{namespace-name}/pods/{pod-name}/metrics/{metric-name} endpoint exposes // an aggregated metric for a Pod entity of the model. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/metrics/{metric-name}"). To(a.podMetrics). Filter(compressionFilter). Doc("Export an aggregated pod-level metric"). Operation("podMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to lookup").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) // The /namespaces/{namespace-name}/pods/{pod-name}/containers endpoint returns a list of all Container entities, // under a specified namespace and pod. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/containers"). To(a.allPodContainers). Filter(compressionFilter). Doc("Get a list of all Containers in the model, belonging to the specified Namespace and Pod"). Operation("allPodContainers"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to lookup").DataType("string"))) // The /namespaces/{namespace-name}/pods/{pod-name}/containers/{container-name} endpoint // returns a list of all API paths available for a Pod Container ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/containers/{container-name}"). To(a.containerPaths). Filter(compressionFilter). Doc("Get a list of all API paths available for a Pod Container entity"). Operation("containerPaths"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to lookup").DataType("string")). Param(ws.PathParameter("container-name", "The name of the namespace to use").DataType("string"))) // The /namespaces/{namespace-name}/pods/{pod-name}/containers/{container-name}/stats endpoint returns derived stats for a Pod Container entity. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/containers/{container-name}/stats/"). To(a.podContainerStats). Filter(compressionFilter). Doc("Get all available stats for a Pod Container entity."). Operation("podContainerStats"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to lookup").DataType("string")). Param(ws.PathParameter("container-name", "The name of the namespace to use").DataType("string"))) // The /namespaces/{namespace-name}/pods/{pod-name}/containers/metrics/{container-name}/metrics endpoint // returns a list of all available metrics for a Pod Container entity. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/containers/{container-name}/metrics"). To(a.availableMetrics). Filter(compressionFilter). Doc("Get a list of all available metrics for a Pod entity"). Operation("availableMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to lookup").DataType("string")). Param(ws.PathParameter("container-name", "The name of the namespace to use").DataType("string"))) // The /namespaces/{namespace-name}/pods/{pod-name}/containers/{container-name}/metrics/{metric-name} endpoint exposes // a metric for a Container entity of the model. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/containers/{container-name}/metrics/{metric-name}"). To(a.podContainerMetrics). Filter(compressionFilter). Doc("Export an aggregated metric for a Pod Container"). Operation("podContainerMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to use").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to use").DataType("string")). Param(ws.PathParameter("container-name", "The name of the namespace to use").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) // The /nodes/{node-name}/pods/ endpoint returns a list of all Pods entities under a specified node. ws.Route(ws.GET("/nodes/{node-name}/pods/"). To(a.nodePods). Filter(compressionFilter). Doc("Get a list of all Pods belonging to a specified Node in the model"). Operation("nodePods"). Param(ws.PathParameter("node-name", "The name of the namespace to lookup").DataType("string"))) } // The /nodes/{node-name}/freecontainers/ endpoint returns a list of all free Container entities, // under a specified node. ws.Route(ws.GET("/nodes/{node-name}/freecontainers/"). To(a.allFreeContainers). Filter(compressionFilter). Doc("Get a list of all free Containers in the model, belonging to the specified Node"). Operation("allFreeContainers"). Param(ws.PathParameter("node-name", "The name of the namespace to lookup").DataType("string"))) // The /nodes/{node-name}/freecontainers/{container-name}/ endpoint exposes // the available subpaths for a free container ws.Route(ws.GET("/nodes/{node-name}/freecontainers/{container-name}/"). To(a.containerPaths). Filter(compressionFilter). Doc("Get a list of API paths for a free Container entity"). Operation("freeContainerMetrics"). Param(ws.PathParameter("node-name", "The name of the node to use").DataType("string")). Param(ws.PathParameter("container-name", "The name of the container to use").DataType("string")). Writes(types.MetricResult{})) // The /nodes/{node-name}/freecontainers/{container-name}/stats endpoint returns derived stats for a Free Container entity. ws.Route(ws.GET("/nodes/{node-name}/freecontainers/{container-name}/stats"). To(a.freeContainerStats). Filter(compressionFilter). Doc("Get all available stats for a Free Container entity."). Operation("freeContainerStats"). Param(ws.PathParameter("node-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("container-name", "The name of the namespace to use").DataType("string"))) // The /nodes/{node-name}/freecontainers/{container-name}/metrics endpoint // returns a list of all available metrics for a Free Container entity. ws.Route(ws.GET("/nodes/{node-name}/freecontainers/{container-name}/metrics"). To(a.availableMetrics). Filter(compressionFilter). Doc("Get a list of all available metrics for a free Container entity"). Operation("availableMetrics"). Param(ws.PathParameter("node-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("container-name", "The name of the namespace to use").DataType("string"))) // The /nodes/{node-name}/freecontainers/{container-name}/metrics/{metric-name} endpoint exposes // a metric for a free Container entity of the model. ws.Route(ws.GET("/nodes/{node-name}/freecontainers/{container-name}/metrics/{metric-name}"). To(a.freeContainerMetrics). Filter(compressionFilter). Doc("Export a container-level metric for a free container"). Operation("freeContainerMetrics"). Param(ws.PathParameter("node-name", "The name of the node to use").DataType("string")). Param(ws.PathParameter("container-name", "The name of the container to use").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) if a.runningInKubernetes { // The /namespaces/{namespace-name}/pod-list/{pod-list}/metrics/{metric-name} endpoint exposes // metrics for a list od pods of the model. ws.Route(ws.GET("/namespaces/{namespace-name}/pod-list/{pod-list}/metrics/{metric-name}"). To(a.podListMetrics). Filter(compressionFilter). Doc("Export a metric for all pods from the given list"). Operation("podListMetric"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-list", "Comma separated list of pod names to lookup").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) } container.Add(ws) }
// RegisterModel registers the Model API endpoints. // All endpoints that end with a {metric-name} also receive a start time query parameter. // The start and end times should be specified as a string, formatted according to RFC 3339. func (a *Api) RegisterModel(container *restful.Container) { ws := new(restful.WebService) ws.Path("/api/v1/model"). Doc("Root endpoint of the stats model"). Consumes("*/*"). Produces(restful.MIME_JSON) // The /metrics/ endpoint returns a list of all available metrics for the Cluster entity of the model. ws.Route(ws.GET("/metrics/"). To(metrics.InstrumentRouteFunc("availableClusterMetrics", a.availableClusterMetrics)). Doc("Get a list of all available metrics for the Cluster entity"). Operation("availableClusterMetrics")) // The /metrics/{metric-name} endpoint exposes an aggregated metric for the Cluster entity of the model. ws.Route(ws.GET("/metrics/{metric-name:*}"). To(metrics.InstrumentRouteFunc("clusterMetrics", a.clusterMetrics)). Doc("Export an aggregated cluster-level metric"). Operation("clusterMetrics"). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metric").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) // The /nodes/{node-name}/metrics endpoint returns a list of all nodes with some metrics. ws.Route(ws.GET("/nodes/"). To(metrics.InstrumentRouteFunc("nodeList", a.nodeList)). Doc("Get a list of all nodes that have some current metrics"). Operation("nodeList")) // The /nodes/{node-name}/metrics endpoint returns a list of all available metrics for a Node entity. ws.Route(ws.GET("/nodes/{node-name}/metrics/"). To(metrics.InstrumentRouteFunc("availableNodeMetrics", a.availableNodeMetrics)). Doc("Get a list of all available metrics for a Node entity"). Operation("availableNodeMetrics"). Param(ws.PathParameter("node-name", "The name of the node to lookup").DataType("string"))) // The /nodes/{node-name}/metrics/{metric-name} endpoint exposes a metric for a Node entity of the model. // The {node-name} parameter is the hostname of a specific node. ws.Route(ws.GET("/nodes/{node-name}/metrics/{metric-name:*}"). To(metrics.InstrumentRouteFunc("nodeMetrics", a.nodeMetrics)). Doc("Export a node-level metric"). Operation("nodeMetrics"). Param(ws.PathParameter("node-name", "The name of the node to lookup").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metric").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) if a.runningInKubernetes { ws.Route(ws.GET("/namespaces/"). To(metrics.InstrumentRouteFunc("namespaceList", a.namespaceList)). Doc("Get a list of all namespaces that have some current metrics"). Operation("namespaceList")) // The /namespaces/{namespace-name}/metrics endpoint returns a list of all available metrics for a Namespace entity. ws.Route(ws.GET("/namespaces/{namespace-name}/metrics"). To(metrics.InstrumentRouteFunc("availableNamespaceMetrics", a.availableNamespaceMetrics)). Doc("Get a list of all available metrics for a Namespace entity"). Operation("availableNamespaceMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string"))) // The /namespaces/{namespace-name}/metrics/{metric-name} endpoint exposes an aggregated metrics // for a Namespace entity of the model. ws.Route(ws.GET("/namespaces/{namespace-name}/metrics/{metric-name:*}"). To(metrics.InstrumentRouteFunc("namespaceMetrics", a.namespaceMetrics)). Doc("Export an aggregated namespace-level metric"). Operation("namespaceMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) ws.Route(ws.GET("/namespaces/{namespace-name}/pods/"). To(metrics.InstrumentRouteFunc("namespacePodList", a.namespacePodList)). Doc("Get a list of pods from the given namespace that have some metrics"). Operation("namespacePodList"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string"))) // The /namespaces/{namespace-name}/pods/{pod-name}/metrics endpoint returns a list of all available metrics for a Pod entity. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/metrics"). To(metrics.InstrumentRouteFunc("availablePodMetrics", a.availablePodMetrics)). Doc("Get a list of all available metrics for a Pod entity"). Operation("availablePodMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to lookup").DataType("string"))) // The /namespaces/{namespace-name}/pods/{pod-name}/metrics/{metric-name} endpoint exposes // an aggregated metric for a Pod entity of the model. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/metrics/{metric-name:*}"). To(metrics.InstrumentRouteFunc("podMetrics", a.podMetrics)). Doc("Export an aggregated pod-level metric"). Operation("podMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to lookup").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) // The /namespaces/{namespace-name}/pods/{pod-name}/containers/metrics/{container-name}/metrics endpoint // returns a list of all available metrics for a Pod Container entity. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/containers/{container-name}/metrics"). To(metrics.InstrumentRouteFunc("availableContainerMetrics", a.availablePodContainerMetrics)). Doc("Get a list of all available metrics for a Pod entity"). Operation("availableContainerMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to lookup").DataType("string")). Param(ws.PathParameter("container-name", "The name of the namespace to use").DataType("string"))) // The /namespaces/{namespace-name}/pods/{pod-name}/containers/{container-name}/metrics/{metric-name} endpoint exposes // a metric for a Container entity of the model. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/containers/{container-name}/metrics/{metric-name:*}"). To(metrics.InstrumentRouteFunc("podContainerMetrics", a.podContainerMetrics)). Doc("Export an aggregated metric for a Pod Container"). Operation("podContainerMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to use").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to use").DataType("string")). Param(ws.PathParameter("container-name", "The name of the namespace to use").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) } ws.Route(ws.GET("/nodes/{node-name}/freecontainers/"). To(metrics.InstrumentRouteFunc("systemContainerList", a.nodeSystemContainerList)). Doc("Get a list of all non-pod containers with some metrics"). Operation("systemContainerList"). Param(ws.PathParameter("node-name", "The name of the namespace to lookup").DataType("string"))) // The /nodes/{node-name}/freecontainers/{container-name}/metrics endpoint // returns a list of all available metrics for a Free Container entity. ws.Route(ws.GET("/nodes/{node-name}/freecontainers/{container-name}/metrics"). To(metrics.InstrumentRouteFunc("availableMetrics", a.availableFreeContainerMetrics)). Doc("Get a list of all available metrics for a free Container entity"). Operation("availableMetrics"). Param(ws.PathParameter("node-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("container-name", "The name of the namespace to use").DataType("string"))) // The /nodes/{node-name}/freecontainers/{container-name}/metrics/{metric-name} endpoint exposes // a metric for a free Container entity of the model. ws.Route(ws.GET("/nodes/{node-name}/freecontainers/{container-name}/metrics/{metric-name:*}"). To(metrics.InstrumentRouteFunc("freeContainerMetrics", a.freeContainerMetrics)). Doc("Export a container-level metric for a free container"). Operation("freeContainerMetrics"). Param(ws.PathParameter("node-name", "The name of the node to use").DataType("string")). Param(ws.PathParameter("container-name", "The name of the container to use").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) if a.runningInKubernetes { // The /namespaces/{namespace-name}/pod-list/{pod-list}/metrics/{metric-name} endpoint exposes // metrics for a list od pods of the model. ws.Route(ws.GET("/namespaces/{namespace-name}/pod-list/{pod-list}/metrics/{metric-name:*}"). To(metrics.InstrumentRouteFunc("podListMetric", a.podListMetrics)). Doc("Export a metric for all pods from the given list"). Operation("podListMetric"). Param(ws.PathParameter("namespace-name", "The name of the namespace to lookup").DataType("string")). Param(ws.PathParameter("pod-list", "Comma separated list of pod names to lookup").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Param(ws.QueryParameter("end", "End time for requested metric").DataType("string")). Writes(types.MetricResult{})) } ws.Route(ws.GET("/debug/allkeys"). To(metrics.InstrumentRouteFunc("debugAllKeys", a.allKeys)). Doc("Get keys of all metric sets available"). Operation("debugAllKeys")) container.Add(ws) }
// RegisterModel registers the Model API endpoints. // All endpoints that end with a {metric-name} also receive a start time query parameter. // The start time should be specified as a string, formatted according to RFC 3339. func (a *Api) RegisterModel(container *restful.Container) { ws := new(restful.WebService) ws. Path("/api/v1/model"). Doc("Root endpoint of the stats model"). Consumes("*/*"). Produces(restful.MIME_JSON) // The / endpoint returns a list of all the metrics that are available in the model ws.Route(ws.GET("/"). To(a.availableMetrics). Filter(compressionFilter). Doc("Show which metrics are available"). Operation("clusterMetrics")) // The /cluster/{metric-name} endpoint exposes an aggregated metric for the Cluster entity of the model. ws.Route(ws.GET("/cluster/{metric-name}"). To(a.clusterMetrics). Filter(compressionFilter). Doc("Export an aggregated cluster-level metric"). Operation("clusterMetrics"). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metric").DataType("string")). Writes(MetricResult{})) // The /nodes/{node-name}/{metric-name} endpoint exposes a metric for a Node entity of the model. // The {node-name} parameter is the hostname of a specific node. ws.Route(ws.GET("/nodes/{node-name}/{metric-name}"). To(a.nodeMetrics). Filter(compressionFilter). Doc("Export a node-level metric"). Operation("nodeMetrics"). Param(ws.PathParameter("node-name", "The name of the node to lookup").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metric").DataType("string")). Writes(MetricResult{})) // The /namespaces/{namespace-name}/{metric-name} endpoint exposes an aggregated metrics // for a Namespace entity of the model. ws.Route(ws.GET("/namespaces/{namespace-name}/{metric-name}"). To(a.namespaceMetrics). Filter(compressionFilter). Doc("Export an aggregated namespace-level metric"). Operation("namespaceMetrics"). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Writes(MetricResult{})) // The /namespaces/{namespace-name}/pods/{pod-name}/{metric-name} endpoint exposes // an aggregated metric for a Pod entity of the model. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/{metric-name}"). To(a.podMetrics). Filter(compressionFilter). Doc("Export an aggregated pod-level metric"). Operation("podMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to use").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to use").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Writes(MetricResult{})) // The /namespaces/{namespace-name}/pods/{pod-name}/containers/{container-name}/{metric-name} endpoint exposes // a metric for a Container entity of the model. ws.Route(ws.GET("/namespaces/{namespace-name}/pods/{pod-name}/containers/{container-name}/{metric-name}"). To(a.podContainerMetrics). Filter(compressionFilter). Doc("Export an aggregated metric for a pod container"). Operation("podContainerMetrics"). Param(ws.PathParameter("namespace-name", "The name of the namespace to use").DataType("string")). Param(ws.PathParameter("pod-name", "The name of the pod to use").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Writes(MetricResult{})) // The /nodes/{node-name}/freecontainers/{container-name}/{metric-name} endpoint exposes // a metric for a free Container entity of the model. ws.Route(ws.GET("/nodes/{node-name}/freecontainers/{container-name}/{metric-name}"). To(a.freeContainerMetrics). Filter(compressionFilter). Doc("Export a container-level metric for a free container"). Operation("freeContainerMetrics"). Param(ws.PathParameter("node-name", "The name of the node to use").DataType("string")). Param(ws.PathParameter("container-name", "The name of the container to use").DataType("string")). Param(ws.PathParameter("metric-name", "The name of the requested metric").DataType("string")). Param(ws.QueryParameter("start", "Start time for requested metrics").DataType("string")). Writes(MetricResult{})) container.Add(ws) }