diff --git a/Makefile b/Makefile index 9a86932..e9e8822 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ vendor: rm -rf ./vendor go mod vendor +# Download the latest swagger releases from: https://github.com/go-swagger/go-swagger/releases/ swagger: swagger generate server -t pkg -f ./swagger.yml --exclude-main -A goldpinger && \ swagger generate client -t pkg -f ./swagger.yml -A goldpinger diff --git a/pkg/client/goldpinger_client.go b/pkg/client/goldpinger_client.go index 2f697d8..3db5d96 100644 --- a/pkg/client/goldpinger_client.go +++ b/pkg/client/goldpinger_client.go @@ -6,12 +6,10 @@ package client // Editing this file might prove futile when you re-run the swagger generate command import ( + "github.com/bloomberg/goldpinger/pkg/client/operations" "github.com/go-openapi/runtime" httptransport "github.com/go-openapi/runtime/client" - - strfmt "github.com/go-openapi/strfmt" - - "github.com/bloomberg/goldpinger/pkg/client/operations" + "github.com/go-openapi/strfmt" ) // Default goldpinger HTTP client. @@ -56,9 +54,7 @@ func New(transport runtime.ClientTransport, formats strfmt.Registry) *Goldpinger cli := new(Goldpinger) cli.Transport = transport - cli.Operations = operations.New(transport, formats) - return cli } @@ -103,7 +99,7 @@ func (cfg *TransportConfig) WithSchemes(schemes []string) *TransportConfig { // Goldpinger is a client for goldpinger type Goldpinger struct { - Operations *operations.Client + Operations operations.ClientService Transport runtime.ClientTransport } @@ -111,7 +107,5 @@ type Goldpinger struct { // SetTransport changes the transport on the client and all its subresources func (c *Goldpinger) SetTransport(transport runtime.ClientTransport) { c.Transport = transport - c.Operations.SetTransport(transport) - } diff --git a/pkg/client/operations/check_all_pods_parameters.go b/pkg/client/operations/check_all_pods_parameters.go index 92e99c9..e9a6177 100644 --- a/pkg/client/operations/check_all_pods_parameters.go +++ b/pkg/client/operations/check_all_pods_parameters.go @@ -13,8 +13,7 @@ import ( "github.com/go-openapi/errors" "github.com/go-openapi/runtime" cr "github.com/go-openapi/runtime/client" - - strfmt "github.com/go-openapi/strfmt" + "github.com/go-openapi/strfmt" ) // NewCheckAllPodsParams creates a new CheckAllPodsParams object diff --git a/pkg/client/operations/check_all_pods_responses.go b/pkg/client/operations/check_all_pods_responses.go index 55e6259..057eda4 100644 --- a/pkg/client/operations/check_all_pods_responses.go +++ b/pkg/client/operations/check_all_pods_responses.go @@ -10,10 +10,9 @@ import ( "io" "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" - strfmt "github.com/go-openapi/strfmt" - - models "github.com/bloomberg/goldpinger/pkg/models" + "github.com/bloomberg/goldpinger/pkg/models" ) // CheckAllPodsReader is a Reader for the CheckAllPods structure. @@ -24,7 +23,6 @@ type CheckAllPodsReader struct { // ReadResponse reads a server response into the received o. func (o *CheckAllPodsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { switch response.Code() { - case 200: result := NewCheckAllPodsOK() if err := result.readResponse(response, consumer, o.formats); err != nil { @@ -54,6 +52,10 @@ func (o *CheckAllPodsOK) Error() string { return fmt.Sprintf("[GET /check_all][%d] checkAllPodsOK %+v", 200, o.Payload) } +func (o *CheckAllPodsOK) GetPayload() *models.CheckAllResults { + return o.Payload +} + func (o *CheckAllPodsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { o.Payload = new(models.CheckAllResults) diff --git a/pkg/client/operations/check_service_pods_parameters.go b/pkg/client/operations/check_service_pods_parameters.go index 007ba8c..c620480 100644 --- a/pkg/client/operations/check_service_pods_parameters.go +++ b/pkg/client/operations/check_service_pods_parameters.go @@ -13,8 +13,7 @@ import ( "github.com/go-openapi/errors" "github.com/go-openapi/runtime" cr "github.com/go-openapi/runtime/client" - - strfmt "github.com/go-openapi/strfmt" + "github.com/go-openapi/strfmt" ) // NewCheckServicePodsParams creates a new CheckServicePodsParams object diff --git a/pkg/client/operations/check_service_pods_responses.go b/pkg/client/operations/check_service_pods_responses.go index c4e61d9..e84ca9c 100644 --- a/pkg/client/operations/check_service_pods_responses.go +++ b/pkg/client/operations/check_service_pods_responses.go @@ -10,10 +10,9 @@ import ( "io" "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" - strfmt "github.com/go-openapi/strfmt" - - models "github.com/bloomberg/goldpinger/pkg/models" + "github.com/bloomberg/goldpinger/pkg/models" ) // CheckServicePodsReader is a Reader for the CheckServicePods structure. @@ -24,7 +23,6 @@ type CheckServicePodsReader struct { // ReadResponse reads a server response into the received o. func (o *CheckServicePodsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { switch response.Code() { - case 200: result := NewCheckServicePodsOK() if err := result.readResponse(response, consumer, o.formats); err != nil { @@ -54,6 +52,10 @@ func (o *CheckServicePodsOK) Error() string { return fmt.Sprintf("[GET /check][%d] checkServicePodsOK %+v", 200, o.Payload) } +func (o *CheckServicePodsOK) GetPayload() *models.CheckResults { + return o.Payload +} + func (o *CheckServicePodsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { o.Payload = new(models.CheckResults) diff --git a/pkg/client/operations/healthz_parameters.go b/pkg/client/operations/healthz_parameters.go index f0cfde7..6e04923 100644 --- a/pkg/client/operations/healthz_parameters.go +++ b/pkg/client/operations/healthz_parameters.go @@ -13,8 +13,7 @@ import ( "github.com/go-openapi/errors" "github.com/go-openapi/runtime" cr "github.com/go-openapi/runtime/client" - - strfmt "github.com/go-openapi/strfmt" + "github.com/go-openapi/strfmt" ) // NewHealthzParams creates a new HealthzParams object diff --git a/pkg/client/operations/healthz_responses.go b/pkg/client/operations/healthz_responses.go index ae86c0d..31ccce9 100644 --- a/pkg/client/operations/healthz_responses.go +++ b/pkg/client/operations/healthz_responses.go @@ -10,10 +10,9 @@ import ( "io" "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" - strfmt "github.com/go-openapi/strfmt" - - models "github.com/bloomberg/goldpinger/pkg/models" + "github.com/bloomberg/goldpinger/pkg/models" ) // HealthzReader is a Reader for the Healthz structure. @@ -24,14 +23,12 @@ type HealthzReader struct { // ReadResponse reads a server response into the received o. func (o *HealthzReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { switch response.Code() { - case 200: result := NewHealthzOK() if err := result.readResponse(response, consumer, o.formats); err != nil { return nil, err } return result, nil - case 503: result := NewHealthzServiceUnavailable() if err := result.readResponse(response, consumer, o.formats); err != nil { @@ -61,6 +58,10 @@ func (o *HealthzOK) Error() string { return fmt.Sprintf("[GET /healthz][%d] healthzOK %+v", 200, o.Payload) } +func (o *HealthzOK) GetPayload() *models.HealthCheckResults { + return o.Payload +} + func (o *HealthzOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { o.Payload = new(models.HealthCheckResults) @@ -90,6 +91,10 @@ func (o *HealthzServiceUnavailable) Error() string { return fmt.Sprintf("[GET /healthz][%d] healthzServiceUnavailable %+v", 503, o.Payload) } +func (o *HealthzServiceUnavailable) GetPayload() *models.HealthCheckResults { + return o.Payload +} + func (o *HealthzServiceUnavailable) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { o.Payload = new(models.HealthCheckResults) diff --git a/pkg/client/operations/operations_client.go b/pkg/client/operations/operations_client.go index 9eabd55..cc324ce 100644 --- a/pkg/client/operations/operations_client.go +++ b/pkg/client/operations/operations_client.go @@ -6,13 +6,14 @@ package operations // Editing this file might prove futile when you re-run the swagger generate command import ( - "github.com/go-openapi/runtime" + "fmt" - strfmt "github.com/go-openapi/strfmt" + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" ) // New creates a new operations API client. -func New(transport runtime.ClientTransport, formats strfmt.Registry) *Client { +func New(transport runtime.ClientTransport, formats strfmt.Registry) ClientService { return &Client{transport: transport, formats: formats} } @@ -24,8 +25,21 @@ type Client struct { formats strfmt.Registry } +// ClientService is the interface for Client methods +type ClientService interface { + CheckAllPods(params *CheckAllPodsParams) (*CheckAllPodsOK, error) + + CheckServicePods(params *CheckServicePodsParams) (*CheckServicePodsOK, error) + + Healthz(params *HealthzParams) (*HealthzOK, error) + + Ping(params *PingParams) (*PingOK, error) + + SetTransport(transport runtime.ClientTransport) +} + /* -CheckAllPods Queries the API server for all other pods in this service, and makes all of them query all of their neighbours, using their pods IPs. Calls their /check endpoint. + CheckAllPods Queries the API server for all other pods in this service, and makes all of them query all of their neighbours, using their pods IPs. Calls their /check endpoint. */ func (a *Client) CheckAllPods(params *CheckAllPodsParams) (*CheckAllPodsOK, error) { // TODO: Validate the params before sending @@ -38,7 +52,7 @@ func (a *Client) CheckAllPods(params *CheckAllPodsParams) (*CheckAllPodsOK, erro Method: "GET", PathPattern: "/check_all", ProducesMediaTypes: []string{"application/json"}, - ConsumesMediaTypes: []string{""}, + ConsumesMediaTypes: []string{"application/json"}, Schemes: []string{"http"}, Params: params, Reader: &CheckAllPodsReader{formats: a.formats}, @@ -48,12 +62,18 @@ func (a *Client) CheckAllPods(params *CheckAllPodsParams) (*CheckAllPodsOK, erro if err != nil { return nil, err } - return result.(*CheckAllPodsOK), nil - + success, ok := result.(*CheckAllPodsOK) + if ok { + return success, nil + } + // unexpected success response + // safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue + msg := fmt.Sprintf("unexpected success response for checkAllPods: API contract not enforced by server. Client expected to get an error, but got: %T", result) + panic(msg) } /* -CheckServicePods Queries the API server for all other pods in this service, and pings them via their pods IPs. Calls their /ping endpoint + CheckServicePods Queries the API server for all other pods in this service, and pings them via their pods IPs. Calls their /ping endpoint */ func (a *Client) CheckServicePods(params *CheckServicePodsParams) (*CheckServicePodsOK, error) { // TODO: Validate the params before sending @@ -66,7 +86,7 @@ func (a *Client) CheckServicePods(params *CheckServicePodsParams) (*CheckService Method: "GET", PathPattern: "/check", ProducesMediaTypes: []string{"application/json"}, - ConsumesMediaTypes: []string{""}, + ConsumesMediaTypes: []string{"application/json"}, Schemes: []string{"http"}, Params: params, Reader: &CheckServicePodsReader{formats: a.formats}, @@ -76,12 +96,18 @@ func (a *Client) CheckServicePods(params *CheckServicePodsParams) (*CheckService if err != nil { return nil, err } - return result.(*CheckServicePodsOK), nil - + success, ok := result.(*CheckServicePodsOK) + if ok { + return success, nil + } + // unexpected success response + // safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue + msg := fmt.Sprintf("unexpected success response for checkServicePods: API contract not enforced by server. Client expected to get an error, but got: %T", result) + panic(msg) } /* -Healthz The healthcheck endpoint provides detailed information about the health of a web service. If each of the components required by the service are healthy, then the service is considered healthy and will return a 200 OK response. If any of the components needed by the service are unhealthy, then a 503 Service Unavailable response will be provided. + Healthz The healthcheck endpoint provides detailed information about the health of a web service. If each of the components required by the service are healthy, then the service is considered healthy and will return a 200 OK response. If any of the components needed by the service are unhealthy, then a 503 Service Unavailable response will be provided. */ func (a *Client) Healthz(params *HealthzParams) (*HealthzOK, error) { // TODO: Validate the params before sending @@ -94,7 +120,7 @@ func (a *Client) Healthz(params *HealthzParams) (*HealthzOK, error) { Method: "GET", PathPattern: "/healthz", ProducesMediaTypes: []string{"application/json"}, - ConsumesMediaTypes: []string{""}, + ConsumesMediaTypes: []string{"application/json"}, Schemes: []string{"http"}, Params: params, Reader: &HealthzReader{formats: a.formats}, @@ -104,12 +130,18 @@ func (a *Client) Healthz(params *HealthzParams) (*HealthzOK, error) { if err != nil { return nil, err } - return result.(*HealthzOK), nil - + success, ok := result.(*HealthzOK) + if ok { + return success, nil + } + // unexpected success response + // safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue + msg := fmt.Sprintf("unexpected success response for healthz: API contract not enforced by server. Client expected to get an error, but got: %T", result) + panic(msg) } /* -Ping return query stats + Ping return query stats */ func (a *Client) Ping(params *PingParams) (*PingOK, error) { // TODO: Validate the params before sending @@ -122,7 +154,7 @@ func (a *Client) Ping(params *PingParams) (*PingOK, error) { Method: "GET", PathPattern: "/ping", ProducesMediaTypes: []string{"application/json"}, - ConsumesMediaTypes: []string{""}, + ConsumesMediaTypes: []string{"application/json"}, Schemes: []string{"http"}, Params: params, Reader: &PingReader{formats: a.formats}, @@ -132,8 +164,14 @@ func (a *Client) Ping(params *PingParams) (*PingOK, error) { if err != nil { return nil, err } - return result.(*PingOK), nil - + success, ok := result.(*PingOK) + if ok { + return success, nil + } + // unexpected success response + // safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue + msg := fmt.Sprintf("unexpected success response for ping: API contract not enforced by server. Client expected to get an error, but got: %T", result) + panic(msg) } // SetTransport changes the transport on the client diff --git a/pkg/client/operations/ping_parameters.go b/pkg/client/operations/ping_parameters.go index 2e93062..65e3430 100644 --- a/pkg/client/operations/ping_parameters.go +++ b/pkg/client/operations/ping_parameters.go @@ -13,8 +13,7 @@ import ( "github.com/go-openapi/errors" "github.com/go-openapi/runtime" cr "github.com/go-openapi/runtime/client" - - strfmt "github.com/go-openapi/strfmt" + "github.com/go-openapi/strfmt" ) // NewPingParams creates a new PingParams object diff --git a/pkg/client/operations/ping_responses.go b/pkg/client/operations/ping_responses.go index bcf31ba..6f97e89 100644 --- a/pkg/client/operations/ping_responses.go +++ b/pkg/client/operations/ping_responses.go @@ -10,10 +10,9 @@ import ( "io" "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" - strfmt "github.com/go-openapi/strfmt" - - models "github.com/bloomberg/goldpinger/pkg/models" + "github.com/bloomberg/goldpinger/pkg/models" ) // PingReader is a Reader for the Ping structure. @@ -24,7 +23,6 @@ type PingReader struct { // ReadResponse reads a server response into the received o. func (o *PingReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { switch response.Code() { - case 200: result := NewPingOK() if err := result.readResponse(response, consumer, o.formats); err != nil { @@ -54,6 +52,10 @@ func (o *PingOK) Error() string { return fmt.Sprintf("[GET /ping][%d] pingOK %+v", 200, o.Payload) } +func (o *PingOK) GetPayload() *models.PingResults { + return o.Payload +} + func (o *PingOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { o.Payload = new(models.PingResults) diff --git a/pkg/models/call_stats.go b/pkg/models/call_stats.go index ffdfb56..2f9e227 100644 --- a/pkg/models/call_stats.go +++ b/pkg/models/call_stats.go @@ -6,12 +6,12 @@ package models // Editing this file might prove futile when you re-run the swagger generate command import ( - strfmt "github.com/go-openapi/strfmt" - + "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" ) // CallStats call stats +// // swagger:model CallStats type CallStats struct { diff --git a/pkg/models/check_all_pod_result.go b/pkg/models/check_all_pod_result.go index 17cfb93..fe9e1dd 100644 --- a/pkg/models/check_all_pod_result.go +++ b/pkg/models/check_all_pod_result.go @@ -6,14 +6,14 @@ package models // Editing this file might prove futile when you re-run the swagger generate command import ( - strfmt "github.com/go-openapi/strfmt" - "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" "github.com/go-openapi/validate" ) // CheckAllPodResult check all pod result +// // swagger:model CheckAllPodResult type CheckAllPodResult struct { @@ -24,6 +24,10 @@ type CheckAllPodResult struct { // o k OK *bool `json:"OK,omitempty"` + // pod IP + // Format: ipv4 + PodIP strfmt.IPv4 `json:"PodIP,omitempty"` + // error Error string `json:"error,omitempty"` @@ -42,6 +46,10 @@ func (m *CheckAllPodResult) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validatePodIP(formats); err != nil { + res = append(res, err) + } + if err := m.validateResponse(formats); err != nil { res = append(res, err) } @@ -65,6 +73,19 @@ func (m *CheckAllPodResult) validateHostIP(formats strfmt.Registry) error { return nil } +func (m *CheckAllPodResult) validatePodIP(formats strfmt.Registry) error { + + if swag.IsZero(m.PodIP) { // not required + return nil + } + + if err := validate.FormatOf("PodIP", "body", "ipv4", m.PodIP.String(), formats); err != nil { + return err + } + + return nil +} + func (m *CheckAllPodResult) validateResponse(formats strfmt.Registry) error { if swag.IsZero(m.Response) { // not required diff --git a/pkg/models/check_all_results.go b/pkg/models/check_all_results.go index f84b0f0..b2fb7b8 100644 --- a/pkg/models/check_all_results.go +++ b/pkg/models/check_all_results.go @@ -8,14 +8,14 @@ package models import ( "strconv" - strfmt "github.com/go-openapi/strfmt" - "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" "github.com/go-openapi/validate" ) // CheckAllResults check all results +// // swagger:model CheckAllResults type CheckAllResults struct { @@ -145,6 +145,7 @@ func (m *CheckAllResults) UnmarshalBinary(b []byte) error { } // CheckAllResultsHostsItems0 check all results hosts items0 +// // swagger:model CheckAllResultsHostsItems0 type CheckAllResultsHostsItems0 struct { @@ -155,6 +156,9 @@ type CheckAllResultsHostsItems0 struct { // pod IP // Format: ipv4 PodIP strfmt.IPv4 `json:"podIP,omitempty"` + + // pod name + PodName string `json:"podName,omitempty"` } // Validate validates this check all results hosts items0 diff --git a/pkg/models/check_results.go b/pkg/models/check_results.go index c3a0e1a..b337f71 100644 --- a/pkg/models/check_results.go +++ b/pkg/models/check_results.go @@ -6,14 +6,14 @@ package models // Editing this file might prove futile when you re-run the swagger generate command import ( - strfmt "github.com/go-openapi/strfmt" - "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" "github.com/go-openapi/validate" ) // CheckResults check results +// // swagger:model CheckResults type CheckResults struct { diff --git a/pkg/models/dns_result.go b/pkg/models/dns_result.go index 8ab2c46..1f89d34 100644 --- a/pkg/models/dns_result.go +++ b/pkg/models/dns_result.go @@ -6,12 +6,12 @@ package models // Editing this file might prove futile when you re-run the swagger generate command import ( - strfmt "github.com/go-openapi/strfmt" - + "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" ) // DNSResult Dns result +// // swagger:model DnsResult type DNSResult struct { diff --git a/pkg/models/dns_results.go b/pkg/models/dns_results.go index e1a0e8b..4971cca 100644 --- a/pkg/models/dns_results.go +++ b/pkg/models/dns_results.go @@ -6,13 +6,13 @@ package models // Editing this file might prove futile when you re-run the swagger generate command import ( - strfmt "github.com/go-openapi/strfmt" - "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" "github.com/go-openapi/validate" ) // DNSResults Dns results +// // swagger:model DnsResults type DNSResults map[string]DNSResult diff --git a/pkg/models/health_check_results.go b/pkg/models/health_check_results.go index a7d22dd..a9c5cd6 100644 --- a/pkg/models/health_check_results.go +++ b/pkg/models/health_check_results.go @@ -6,14 +6,14 @@ package models // Editing this file might prove futile when you re-run the swagger generate command import ( - strfmt "github.com/go-openapi/strfmt" - "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" "github.com/go-openapi/validate" ) // HealthCheckResults health check results +// // swagger:model HealthCheckResults type HealthCheckResults struct { diff --git a/pkg/models/ping_results.go b/pkg/models/ping_results.go index da7ab27..3661838 100644 --- a/pkg/models/ping_results.go +++ b/pkg/models/ping_results.go @@ -6,14 +6,14 @@ package models // Editing this file might prove futile when you re-run the swagger generate command import ( - strfmt "github.com/go-openapi/strfmt" - "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" "github.com/go-openapi/validate" ) // PingResults ping results +// // swagger:model PingResults type PingResults struct { diff --git a/pkg/models/pod_result.go b/pkg/models/pod_result.go index 7d33ea2..ea5b553 100644 --- a/pkg/models/pod_result.go +++ b/pkg/models/pod_result.go @@ -6,14 +6,14 @@ package models // Editing this file might prove futile when you re-run the swagger generate command import ( - strfmt "github.com/go-openapi/strfmt" - "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" "github.com/go-openapi/validate" ) // PodResult pod result +// // swagger:model PodResult type PodResult struct { @@ -24,6 +24,10 @@ type PodResult struct { // o k OK *bool `json:"OK,omitempty"` + // pod IP + // Format: ipv4 + PodIP strfmt.IPv4 `json:"PodIP,omitempty"` + // error Error string `json:"error,omitempty"` @@ -45,6 +49,10 @@ func (m *PodResult) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validatePodIP(formats); err != nil { + res = append(res, err) + } + if err := m.validateResponse(formats); err != nil { res = append(res, err) } @@ -68,6 +76,19 @@ func (m *PodResult) validateHostIP(formats strfmt.Registry) error { return nil } +func (m *PodResult) validatePodIP(formats strfmt.Registry) error { + + if swag.IsZero(m.PodIP) { // not required + return nil + } + + if err := validate.FormatOf("PodIP", "body", "ipv4", m.PodIP.String(), formats); err != nil { + return err + } + + return nil +} + func (m *PodResult) validateResponse(formats strfmt.Registry) error { if swag.IsZero(m.Response) { // not required diff --git a/pkg/restapi/doc.go b/pkg/restapi/doc.go index 29ca5ca..e631ad1 100644 --- a/pkg/restapi/doc.go +++ b/pkg/restapi/doc.go @@ -1,20 +1,18 @@ // Code generated by go-swagger; DO NOT EDIT. -/* -Package restapi Goldpinger - - Schemes: - http - Host: localhost - BasePath: / - Version: 2.0.0 - - Consumes: - - application/json - - Produces: - - application/json - -swagger:meta -*/ +// Package restapi Goldpinger +// +// Schemes: +// http +// Host: localhost +// BasePath: / +// Version: 3.0.0 +// +// Consumes: +// - application/json +// +// Produces: +// - application/json +// +// swagger:meta package restapi diff --git a/pkg/restapi/embedded_spec.go b/pkg/restapi/embedded_spec.go index a85e629..b37bc1a 100644 --- a/pkg/restapi/embedded_spec.go +++ b/pkg/restapi/embedded_spec.go @@ -21,7 +21,7 @@ func init() { "swagger": "2.0", "info": { "title": "Goldpinger", - "version": "2.0.0" + "version": "3.0.0" }, "paths": { "/check": { @@ -124,6 +124,10 @@ func init() { "type": "boolean", "default": false }, + "PodIP": { + "type": "string", + "format": "ipv4" + }, "error": { "type": "string" }, @@ -161,6 +165,9 @@ func init() { "podIP": { "type": "string", "format": "ipv4" + }, + "podName": { + "type": "string" } } } @@ -252,6 +259,10 @@ func init() { "type": "boolean", "default": false }, + "PodIP": { + "type": "string", + "format": "ipv4" + }, "error": { "type": "string" }, @@ -275,7 +286,7 @@ func init() { "swagger": "2.0", "info": { "title": "Goldpinger", - "version": "2.0.0" + "version": "3.0.0" }, "paths": { "/check": { @@ -378,6 +389,10 @@ func init() { "type": "boolean", "default": false }, + "PodIP": { + "type": "string", + "format": "ipv4" + }, "error": { "type": "string" }, @@ -406,17 +421,7 @@ func init() { "hosts": { "type": "array", "items": { - "type": "object", - "properties": { - "hostIP": { - "type": "string", - "format": "ipv4" - }, - "podIP": { - "type": "string", - "format": "ipv4" - } - } + "$ref": "#/definitions/CheckAllResultsHostsItems0" } }, "hosts-healthy": { @@ -435,6 +440,22 @@ func init() { } } }, + "CheckAllResultsHostsItems0": { + "type": "object", + "properties": { + "hostIP": { + "type": "string", + "format": "ipv4" + }, + "podIP": { + "type": "string", + "format": "ipv4" + }, + "podName": { + "type": "string" + } + } + }, "CheckResults": { "type": "object", "properties": { @@ -506,6 +527,10 @@ func init() { "type": "boolean", "default": false }, + "PodIP": { + "type": "string", + "format": "ipv4" + }, "error": { "type": "string" }, diff --git a/pkg/restapi/operations/check_all_pods.go b/pkg/restapi/operations/check_all_pods.go index b236af2..679ae55 100644 --- a/pkg/restapi/operations/check_all_pods.go +++ b/pkg/restapi/operations/check_all_pods.go @@ -8,7 +8,7 @@ package operations import ( "net/http" - middleware "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/runtime/middleware" ) // CheckAllPodsHandlerFunc turns a function with the right signature into a check all pods handler diff --git a/pkg/restapi/operations/check_all_pods_responses.go b/pkg/restapi/operations/check_all_pods_responses.go index 55ffa15..ebf3c91 100644 --- a/pkg/restapi/operations/check_all_pods_responses.go +++ b/pkg/restapi/operations/check_all_pods_responses.go @@ -10,7 +10,7 @@ import ( "github.com/go-openapi/runtime" - models "github.com/bloomberg/goldpinger/pkg/models" + "github.com/bloomberg/goldpinger/pkg/models" ) // CheckAllPodsOKCode is the HTTP code returned for type CheckAllPodsOK diff --git a/pkg/restapi/operations/check_service_pods.go b/pkg/restapi/operations/check_service_pods.go index 1b18f29..caaa026 100644 --- a/pkg/restapi/operations/check_service_pods.go +++ b/pkg/restapi/operations/check_service_pods.go @@ -8,7 +8,7 @@ package operations import ( "net/http" - middleware "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/runtime/middleware" ) // CheckServicePodsHandlerFunc turns a function with the right signature into a check service pods handler diff --git a/pkg/restapi/operations/check_service_pods_responses.go b/pkg/restapi/operations/check_service_pods_responses.go index f0b805f..a8bf34e 100644 --- a/pkg/restapi/operations/check_service_pods_responses.go +++ b/pkg/restapi/operations/check_service_pods_responses.go @@ -10,7 +10,7 @@ import ( "github.com/go-openapi/runtime" - models "github.com/bloomberg/goldpinger/pkg/models" + "github.com/bloomberg/goldpinger/pkg/models" ) // CheckServicePodsOKCode is the HTTP code returned for type CheckServicePodsOK diff --git a/pkg/restapi/operations/goldpinger_api.go b/pkg/restapi/operations/goldpinger_api.go index 005e8d9..112bdc0 100644 --- a/pkg/restapi/operations/goldpinger_api.go +++ b/pkg/restapi/operations/goldpinger_api.go @@ -10,13 +10,13 @@ import ( "net/http" "strings" - errors "github.com/go-openapi/errors" - loads "github.com/go-openapi/loads" - runtime "github.com/go-openapi/runtime" - middleware "github.com/go-openapi/runtime/middleware" - security "github.com/go-openapi/runtime/security" - spec "github.com/go-openapi/spec" - strfmt "github.com/go-openapi/strfmt" + "github.com/go-openapi/errors" + "github.com/go-openapi/loads" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/runtime/security" + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" ) @@ -29,14 +29,18 @@ func NewGoldpingerAPI(spec *loads.Document) *GoldpingerAPI { defaultProduces: "application/json", customConsumers: make(map[string]runtime.Consumer), customProducers: make(map[string]runtime.Producer), + PreServerShutdown: func() {}, ServerShutdown: func() {}, spec: spec, ServeError: errors.ServeError, BasicAuthenticator: security.BasicAuth, APIKeyAuthenticator: security.APIKeyAuth, BearerAuthenticator: security.BearerAuth, - JSONConsumer: runtime.JSONConsumer(), - JSONProducer: runtime.JSONProducer(), + + JSONConsumer: runtime.JSONConsumer(), + + JSONProducer: runtime.JSONProducer(), + CheckAllPodsHandler: CheckAllPodsHandlerFunc(func(params CheckAllPodsParams) middleware.Responder { return middleware.NotImplemented("operation CheckAllPods has not yet been implemented") }), @@ -74,10 +78,12 @@ type GoldpingerAPI struct { // It has a default implementation in the security package, however you can replace it for your particular usage. BearerAuthenticator func(string, security.ScopedTokenAuthentication) runtime.Authenticator - // JSONConsumer registers a consumer for a "application/json" mime type + // JSONConsumer registers a consumer for the following mime types: + // - application/json JSONConsumer runtime.Consumer - // JSONProducer registers a producer for a "application/json" mime type + // JSONProducer registers a producer for the following mime types: + // - application/json JSONProducer runtime.Producer // CheckAllPodsHandler sets the operation handler for the check all pods operation @@ -88,11 +94,14 @@ type GoldpingerAPI struct { HealthzHandler HealthzHandler // PingHandler sets the operation handler for the ping operation PingHandler PingHandler - // ServeError is called when an error is received, there is a default handler // but you can set your own with this ServeError func(http.ResponseWriter, *http.Request, error) + // PreServerShutdown is called before the HTTP(S) server is shutdown + // This allows for custom functions to get executed before the HTTP(S) server stops accepting traffic + PreServerShutdown func() + // ServerShutdown is called when the HTTP(S) server is shut down and done // handling all active connections and does not accept connections any more ServerShutdown func() @@ -154,15 +163,12 @@ func (o *GoldpingerAPI) Validate() error { if o.CheckAllPodsHandler == nil { unregistered = append(unregistered, "CheckAllPodsHandler") } - if o.CheckServicePodsHandler == nil { unregistered = append(unregistered, "CheckServicePodsHandler") } - if o.HealthzHandler == nil { unregistered = append(unregistered, "HealthzHandler") } - if o.PingHandler == nil { unregistered = append(unregistered, "PingHandler") } @@ -181,28 +187,22 @@ func (o *GoldpingerAPI) ServeErrorFor(operationID string) func(http.ResponseWrit // AuthenticatorsFor gets the authenticators for the specified security schemes func (o *GoldpingerAPI) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator { - return nil - } // Authorizer returns the registered authorizer func (o *GoldpingerAPI) Authorizer() runtime.Authorizer { - return nil - } -// ConsumersFor gets the consumers for the specified media types +// ConsumersFor gets the consumers for the specified media types. +// MIME type parameters are ignored here. func (o *GoldpingerAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer { - - result := make(map[string]runtime.Consumer) + result := make(map[string]runtime.Consumer, len(mediaTypes)) for _, mt := range mediaTypes { switch mt { - case "application/json": result["application/json"] = o.JSONConsumer - } if c, ok := o.customConsumers[mt]; ok { @@ -210,19 +210,16 @@ func (o *GoldpingerAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Con } } return result - } -// ProducersFor gets the producers for the specified media types +// ProducersFor gets the producers for the specified media types. +// MIME type parameters are ignored here. func (o *GoldpingerAPI) ProducersFor(mediaTypes []string) map[string]runtime.Producer { - - result := make(map[string]runtime.Producer) + result := make(map[string]runtime.Producer, len(mediaTypes)) for _, mt := range mediaTypes { switch mt { - case "application/json": result["application/json"] = o.JSONProducer - } if p, ok := o.customProducers[mt]; ok { @@ -230,7 +227,6 @@ func (o *GoldpingerAPI) ProducersFor(mediaTypes []string) map[string]runtime.Pro } } return result - } // HandlerFor gets a http.Handler for the provided operation method and path @@ -260,7 +256,6 @@ func (o *GoldpingerAPI) Context() *middleware.Context { func (o *GoldpingerAPI) initHandlerCache() { o.Context() // don't care about the result, just that the initialization happened - if o.handlers == nil { o.handlers = make(map[string]map[string]http.Handler) } @@ -269,22 +264,18 @@ func (o *GoldpingerAPI) initHandlerCache() { o.handlers["GET"] = make(map[string]http.Handler) } o.handlers["GET"]["/check_all"] = NewCheckAllPods(o.context, o.CheckAllPodsHandler) - if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } o.handlers["GET"]["/check"] = NewCheckServicePods(o.context, o.CheckServicePodsHandler) - if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } o.handlers["GET"]["/healthz"] = NewHealthz(o.context, o.HealthzHandler) - if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } o.handlers["GET"]["/ping"] = NewPing(o.context, o.PingHandler) - } // Serve creates a http handler to serve the API over HTTP @@ -314,3 +305,15 @@ func (o *GoldpingerAPI) RegisterConsumer(mediaType string, consumer runtime.Cons func (o *GoldpingerAPI) RegisterProducer(mediaType string, producer runtime.Producer) { o.customProducers[mediaType] = producer } + +// AddMiddlewareFor adds a http middleware to existing handler +func (o *GoldpingerAPI) AddMiddlewareFor(method, path string, builder middleware.Builder) { + um := strings.ToUpper(method) + if path == "/" { + path = "" + } + o.Init() + if h, ok := o.handlers[um][path]; ok { + o.handlers[method][path] = builder(h) + } +} diff --git a/pkg/restapi/operations/healthz.go b/pkg/restapi/operations/healthz.go index 7853aaa..e9cba03 100644 --- a/pkg/restapi/operations/healthz.go +++ b/pkg/restapi/operations/healthz.go @@ -8,7 +8,7 @@ package operations import ( "net/http" - middleware "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/runtime/middleware" ) // HealthzHandlerFunc turns a function with the right signature into a healthz handler diff --git a/pkg/restapi/operations/healthz_responses.go b/pkg/restapi/operations/healthz_responses.go index 866be1d..239de3b 100644 --- a/pkg/restapi/operations/healthz_responses.go +++ b/pkg/restapi/operations/healthz_responses.go @@ -10,7 +10,7 @@ import ( "github.com/go-openapi/runtime" - models "github.com/bloomberg/goldpinger/pkg/models" + "github.com/bloomberg/goldpinger/pkg/models" ) // HealthzOKCode is the HTTP code returned for type HealthzOK diff --git a/pkg/restapi/operations/ping.go b/pkg/restapi/operations/ping.go index 85e5704..1ec520e 100644 --- a/pkg/restapi/operations/ping.go +++ b/pkg/restapi/operations/ping.go @@ -8,7 +8,7 @@ package operations import ( "net/http" - middleware "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/runtime/middleware" ) // PingHandlerFunc turns a function with the right signature into a ping handler diff --git a/pkg/restapi/operations/ping_responses.go b/pkg/restapi/operations/ping_responses.go index ee2dbb7..0a2491e 100644 --- a/pkg/restapi/operations/ping_responses.go +++ b/pkg/restapi/operations/ping_responses.go @@ -10,7 +10,7 @@ import ( "github.com/go-openapi/runtime" - models "github.com/bloomberg/goldpinger/pkg/models" + "github.com/bloomberg/goldpinger/pkg/models" ) // PingOKCode is the HTTP code returned for type PingOK diff --git a/pkg/restapi/server.go b/pkg/restapi/server.go index acbcda4..d49487c 100644 --- a/pkg/restapi/server.go +++ b/pkg/restapi/server.go @@ -133,7 +133,6 @@ func (s *Server) SetAPI(api *operations.GoldpingerAPI) { } s.api = api - s.api.Logger = log.Printf s.handler = configureAPI(api) } @@ -174,8 +173,6 @@ func (s *Server) Serve() (err error) { go handleInterrupt(once, s) servers := []*http.Server{} - wg.Add(1) - go s.handleShutdown(wg, &servers) if s.hasScheme(schemeUnix) { domainSocket := new(http.Server) @@ -252,7 +249,7 @@ func (s *Server) Serve() (err error) { // https://github.com/golang/go/tree/master/src/crypto/elliptic CurvePreferences: []tls.CurveID{tls.CurveP256}, // Use modern tls mode https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility - NextProtos: []string{"http/1.1", "h2"}, + NextProtos: []string{"h2", "http/1.1"}, // https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet#Rule_-_Only_Support_Strong_Protocols MinVersion: tls.VersionTLS12, // These ciphersuites support Forward Secrecy: https://en.wikipedia.org/wiki/Forward_secrecy @@ -293,7 +290,7 @@ func (s *Server) Serve() (err error) { // call custom TLS configurator configureTLS(httpsServer.TLSConfig) - if len(httpsServer.TLSConfig.Certificates) == 0 { + if len(httpsServer.TLSConfig.Certificates) == 0 && httpsServer.TLSConfig.GetCertificate == nil { // after standard and custom config are passed, this ends up with no certificate if s.TLSCertificate == "" { if s.TLSCertificateKey == "" { @@ -325,6 +322,9 @@ func (s *Server) Serve() (err error) { }(tls.NewListener(s.httpsServerL, httpsServer.TLSConfig)) } + wg.Add(1) + go s.handleShutdown(wg, &servers) + wg.Wait() return nil } @@ -420,6 +420,9 @@ func (s *Server) handleShutdown(wg *sync.WaitGroup, serversPtr *[]*http.Server) ctx, cancel := context.WithTimeout(context.TODO(), s.GracefulTimeout) defer cancel() + // first execute the pre-shutdown hook + s.api.PreServerShutdown() + shutdownChan := make(chan bool) for i := range servers { server := servers[i] @@ -489,7 +492,7 @@ func (s *Server) TLSListener() (net.Listener, error) { func handleInterrupt(once *sync.Once, s *Server) { once.Do(func() { - for _ = range s.interrupt { + for range s.interrupt { if s.interrupted { s.Logf("Server already shutting down") continue diff --git a/swagger.yml b/swagger.yml index b448ad4..9f8d955 100644 --- a/swagger.yml +++ b/swagger.yml @@ -1,7 +1,7 @@ --- swagger: '2.0' info: - version: 2.0.0 + version: 3.0.0 title: Goldpinger definitions: CallStats: