Skip to content

Commit

Permalink
[FAB-18315] Ch.Part.API: Create Swagger definition for API (hyperledg…
Browse files Browse the repository at this point in the history
…er#2113)

* [FAB-18315] Ch.Part.API: Create Swagger spec for API

- Adds swagger specification for Ch.Part.API
- Adds swagger annotations to Channel Particiaption endpoints
- Adds a script to generate swagger specification

Signed-off-by: Tiffany Harris <[email protected]>

* [FAB-18315] Add operations endpoint to swagger spec

 - Updates swagger spec to be generalized for fabric with each server
 separated into groups (with swagger tags)
 - Add check-swagger to basic-checks

Signed-off-by: Tiffany Harris <[email protected]>
Signed-off-by: Brett Logan <[email protected]>

* [FAB-18315] Cleanup swagger annotations

Signed-off-by: Tiffany Harris <[email protected]>
  • Loading branch information
stephyee authored Jan 5, 2021
1 parent 4220751 commit c2fc776
Show file tree
Hide file tree
Showing 13 changed files with 1,123 additions and 5 deletions.
12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ all: check-go-version native docker checks
checks: basic-checks unit-test integration-test

.PHONY: basic-checks
basic-checks: check-go-version license spelling references trailing-spaces linter check-metrics-doc filename-spaces
basic-checks: check-go-version license spelling references trailing-spaces linter check-metrics-doc filename-spaces check-swagger

.PHONY: desk-checks
desk-check: checks verify
Expand Down Expand Up @@ -193,6 +193,16 @@ generate-metrics-doc:
@echo "Generating metrics reference documentation..."
./scripts/metrics_doc.sh generate

.PHONY: check-swagger
check-swagger: gotool.swagger
@echo "SWAGGER: Checking for outdated swagger..."
./scripts/swagger.sh check

.PHONY: generate-swagger
generate-swagger: gotool.swagger
@echo "Generating swagger..."
./scripts/swagger.sh generate

.PHONY: protos
protos: gotool.protoc-gen-go
@echo "Compiling non-API protos..."
Expand Down
1 change: 1 addition & 0 deletions common/flogging/httpadmin/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type Logging interface {
Spec() string
}

// swagger:model spec
type LogSpec struct {
Spec string `json:"spec,omitempty"`
}
Expand Down
43 changes: 43 additions & 0 deletions core/operations/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ func (s *System) initializeMetricsProvider() error {
case "prometheus":
s.Provider = &prometheus.Provider{}
s.versionGauge = versionGauge(s.Provider)
// swagger:operation GET /metrics operations metrics
// ---
// responses:
// '200':
// description: Ok.
s.RegisterHandler("/metrics", promhttp.Handler(), s.options.TLS.Enabled)
return nil

Expand All @@ -146,11 +151,43 @@ func (s *System) initializeMetricsProvider() error {
}

func (s *System) initializeLoggingHandler() {
// swagger:operation GET /logspec operations logspecget
// ---
// summary: Retrieves the active logging spec for a peer or orderer.
// responses:
// '200':
// description: Ok.

// swagger:operation PUT /logspec operations logspecput
// ---
// summary: Updates the active logging spec for a peer or orderer.
//
// parameters:
// - name: payload
// in: formData
// type: string
// description: The payload must consist of a single attribute named spec.
// required: true
// responses:
// '204':
// description: No content.
// '400':
// description: Bad request.
// consumes:
// - multipart/form-data
s.RegisterHandler("/logspec", httpadmin.NewSpecHandler(), s.options.TLS.Enabled)
}

func (s *System) initializeHealthCheckHandler() {
s.healthHandler = healthz.NewHealthHandler()
// swagger:operation GET /healthz operations healthz
// ---
// summary: Retrieves all registered health checkers for the process.
// responses:
// '200':
// description: Ok.
// '503':
// description: Service unavailable.
s.RegisterHandler("/healthz", s.healthHandler, false)
}

Expand All @@ -159,6 +196,12 @@ func (s *System) initializeVersionInfoHandler() {
CommitSHA: metadata.CommitSHA,
Version: metadata.Version,
}
// swagger:operation GET /version operations version
// ---
// summary: Returns the orderer or peer version and the commit SHA on which the release was created.
// responses:
// '200':
// description: Ok.
s.RegisterHandler("/version", versionInfo, false)
}

Expand Down
3 changes: 2 additions & 1 deletion gotools.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
# SPDX-License-Identifier: Apache-2.0

GOTOOLS = counterfeiter ginkgo gocov gocov-xml goimports golint misspell mockery protoc-gen-go
GOTOOLS = counterfeiter ginkgo gocov gocov-xml goimports golint misspell mockery protoc-gen-go swagger
BUILD_DIR ?= build
GOTOOLS_BINDIR ?= $(shell go env GOPATH)/bin

Expand All @@ -17,6 +17,7 @@ go.fqp.golint := golang.org/x/lint/golint
go.fqp.misspell := github.com/client9/misspell/cmd/misspell
go.fqp.mockery := github.com/vektra/mockery/cmd/mockery
go.fqp.protoc-gen-go := github.com/golang/protobuf/protoc-gen-go
go.fqp.swagger := github.com/go-swagger/go-swagger/cmd/swagger

.PHONY: gotools-install
gotools-install: $(patsubst %,$(GOTOOLS_BINDIR)/%, $(GOTOOLS))
Expand Down
96 changes: 96 additions & 0 deletions orderer/common/channelparticipation/restapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,109 @@ func NewHTTPHandler(config localconfig.ChannelParticipation, registrar ChannelMa
router: mux.NewRouter(),
}

// swagger:operation GET /v1/participation/channels/{channelID} channels listChannel
// ---
// summary: Returns detailed channel information for a specific channel Ordering Service Node (OSN) has joined.
// parameters:
// - name: channelID
// in: path
// description: Channel ID
// required: true
// type: string
// responses:
// '200':
// description: Successfully retrieved channel.
// schema:
// "$ref": "#/definitions/channelInfo"
// headers:
// Content-Type:
// description: The media type of the resource
// type: string
// Cache-Control:
// description: The directives for caching responses
// type: string

handler.router.HandleFunc(urlWithChannelIDKey, handler.serveListOne).Methods(http.MethodGet)

// swagger:operation DELETE /v1/participation/channels/{channelID} channels removeChannel
// ---
// summary: Removes an Ordering Service Node (OSN) from a channel.
// parameters:
// - name: channelID
// in: path
// description: Channel ID
// required: true
// type: string
// responses:
// '204':
// description: Successfully removed channel.
// '400':
// description: Bad request.
// '404':
// description: The channel does not exist.
// '405':
// description: The system channel exists, removal is not allowed.
// '409':
// description: The channel is pending removal.

handler.router.HandleFunc(urlWithChannelIDKey, handler.serveRemove).Methods(http.MethodDelete)
handler.router.HandleFunc(urlWithChannelIDKey, handler.serveNotAllowed)

// swagger:operation GET /v1/participation/channels channels listChannels
// ---
// summary: Returns the complete list of channels an Ordering Service Node (OSN) has joined.
// responses:
// '200':
// description: Successfully retrieved channels.
// schema:
// "$ref": "#/definitions/channelList"
// headers:
// Content-Type:
// description: The media type of the resource
// type: string
// Cache-Control:
// description: The directives for caching responses
// type: string

handler.router.HandleFunc(URLBaseV1Channels, handler.serveListAll).Methods(http.MethodGet)

// swagger:operation POST /v1/participation/channels channels joinChannel
// ---
// summary: Joins an Ordering Service Node (OSN) to a channel.
// description: If a channel does not yet exist, it will be created.
// parameters:
// - name: configBlock
// in: formData
// type: string
// required: true
// responses:
// '201':
// description: Successfully joined channel.
// schema:
// "$ref": "#/definitions/channelInfo"
// headers:
// Content-Type:
// description: The media type of the resource
// type: string
// Location:
// description: The URL to redirect a page to
// type: string
// '400':
// description: Cannot join channel.
// '403':
// description: The client is trying to join the system-channel that does not exist, but application channels exist.
// '405':
// description: |
// The client is trying to join an app-channel, but the system channel exists.
// The client is trying to join an app-channel that exists, but the system channel does not.
// The client is trying to join the system-channel, and it exists.
// '409':
// description: The client is trying to join a channel that is currently being removed.
// '500':
// description: Removal of channel failed.
// consumes:
// - multipart/form-data

handler.router.HandleFunc(URLBaseV1Channels, handler.serveJoin).Methods(http.MethodPost).HeadersRegexp(
"Content-Type", "multipart/form-data*")
handler.router.HandleFunc(URLBaseV1Channels, handler.serveBadContentType).Methods(http.MethodPost)
Expand Down
2 changes: 2 additions & 0 deletions orderer/common/types/channelinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type ErrorResponse struct {

// ChannelList carries the response to an HTTP request to List all the channels.
// This is marshaled into the body of the HTTP response.
// swagger:model channelList
type ChannelList struct {
// The system channel info, nil if it doesn't exist.
SystemChannel *ChannelInfoShort `json:"systemChannel"`
Expand Down Expand Up @@ -65,6 +66,7 @@ const (

// ChannelInfo carries the response to an HTTP request to List a single channel.
// This is marshaled into the body of the HTTP response.
// swagger:model channelInfo
type ChannelInfo struct {
// The channel name.
Name string `json:"name"`
Expand Down
40 changes: 40 additions & 0 deletions scripts/swagger.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash -e

# Copyright IBM Corp All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0

fabric_dir="$(cd "$(dirname "$0")/.." && pwd)"
swagger_tags="${fabric_dir}/swagger/tags.json"
swagger_doc="${fabric_dir}/swagger/swagger-fabric.json"

check_spec() {
swagger_doc_check="${fabric_dir}/swagger/swagger-fabric-check.json"
swagger generate spec -o "$swagger_doc_check" --scan-models --exclude-deps --input "$swagger_tags"
if [ -n "$(diff "$swagger_doc_check" "$swagger_doc")" ]; then
echo "The Fabric swagger is out of date."
echo "Please run '$0 generate' to update the swagger."
rm "$swagger_doc_check"
exit 1
fi
rm "$swagger_doc_check"
}

case "$1" in
# check if the swagger is up to date with the swagger
# options in the tree
"check")
check_spec
;;

# generate the swagger
"generate")
swagger generate spec -o "$swagger_doc" --scan-models --exclude-deps --input "$swagger_tags"
;;

*)
echo "Please specify check or generate"
exit 1
;;
esac

24 changes: 24 additions & 0 deletions swagger/docs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

// Fabric API
//
// Hyperledger Fabric is an enterprise-grade permissioned distributed ledger framework for developing
// solutions and applications. Its modular and versatile design satisfies a broad range of industry use
// cases. It offers a unique approach to consensus that enables performance at scale while preserving privacy.
//
// Schemes: http, https
// Version: 2.3
// License: Copyright IBM Corp. All Rights Reserved.
//
// Consumes:
// - application/json
//
// Produces:
// - application/json
//
// swagger:meta
package docs
Loading

0 comments on commit c2fc776

Please sign in to comment.