Documentation ¶
Overview ¶
Package common contains various things common to all Romana services.
Index ¶
- Constants
- Variables
- func BuildInfo() string
- func CleanURL(url string) (string, error)
- func Environ() map[string]string
- func GetCaller() string
- func GetCaller2(up int) string
- func GetMockDbName(svc string) string
- func GetPasswd() (string, error)
- func IPv4ToInt(ip net.IP) uint64
- func In(needle string, haystack []string) bool
- func InitMap(keyValuePairs ...KeyValue) map[string]interface{}
- func IntToIPv4(ipInt uint64) net.IP
- func IsZeroValue(val interface{}) bool
- func MakeMultiError(errors []error) error
- func MkMap() map[string]interface{}
- func MkMapStr() map[string]string
- func NewError(text string, args ...interface{}) error
- func PressEnterToContinue()
- func ReadKeyFile(filename string) (*pem.Block, error)
- func String(i interface{}) string
- func ToBool(val interface{}) (bool, error)
- type Attribute
- type AuthMiddleware
- type AuthTokenMessage
- type AuthZChecker
- type Config
- type Credential
- type CredentialType
- type ExecErrorDetails
- type FindFlag
- type HttpError
- func NewError400(details interface{}) HttpError
- func NewError403() HttpError
- func NewError404(resourceType string, resourceID string) HttpError
- func NewError500(details interface{}) HttpError
- func NewErrorConflict(details interface{}) HttpError
- func NewHttpError(code int, details interface{}) HttpError
- func NewUnprocessableEntityError(details interface{}) HttpError
- type IP
- type KeyValue
- type LinkResponse
- type Links
- type MakeMessage
- type Marshaller
- type MultiError
- type NegotiatorMiddleware
- type PortUpdateMessage
- type Raw
- type RestContext
- type RestHandler
- type RestServiceInfo
- type Role
- type RomanaHandler
- type RomanaTestSuite
- type Route
- type Routes
- type Service
- type ServiceMessage
- type ServiceUtils
- type UnmarshallerMiddleware
- type UnwrappedRestHandlerInput
- type User
Constants ¶
const ( RoleAdmin = "admin" RoleService = "service" RoleTenant = "tenant" )
const ( CredentialUsernamePassword = "userPass" CredentialNone = "none" UsernameKey = "ROMANA_USERNAME" PasswordKey = "ROMANA_PASSWORD" )
const ( // Flags to store.Find operation FindFirst = "findFirst" FindLast = "findLast" FindExactlyOne = "findExactlyOne" FindAll = "findAll" )
const ( // For passing in Gorilla Mux context the unmarshalled data ContextKeyUnmarshalledMap string = "UnmarshalledMap" // For passing in Gorilla Mux context path variables ContextKeyQueryVariables string = "QueryVars" // For passing in Gorilla Mux context the original body data ContextKeyOriginalBody string = "OriginalBody" ContextKeyMarshaller string = "Marshaller" ContextKeyUser string = "User" ReadWriteTimeoutDelta = 10 // Name of the query parameter used for request token RequestTokenQueryParameter = "RequestToken" HeaderContentType = "content-type" Starting ServiceMessage = "Starting." // JSON TimeoutMessage = "{ \"error\" : \"Timed out\" }" // Empty string returned when there is a string return // but there is an error so no point in returning any // value. ErrorNoValue = "" // Path for authentication; if this is what is used // in the request we will not check the token (because // we are attempting to get a token at this point). AuthPath = "/auth" // Body provided. HookExecutableBodyArgument = "body" )
Constants
const (
DefaultTestConfigFile = "../common/testdata/romana.sample.yaml"
)
const ( // DefaultTimeout, in milliseconds. DefaultTimeout = 500 * time.Millisecond )
const ( // 422 (unprocessable entity http://www.restpatterns.org/HTTP_Status_Codes/422_-_Unprocessable_Entity) // is not in net/http yet. StatusUnprocessableEntity = 422 )
Variables ¶
var ContentTypeMarshallers map[string]Marshaller = map[string]Marshaller{
"": jsonMarshaller{},
"application/json": jsonMarshaller{},
"application/vnd.romana.v1+json": jsonMarshaller{},
"application/vnd.romana+json": jsonMarshaller{},
"application/x-www-form-urlencoded": formMarshaller{},
}
ContentTypeMarshallers maps MIME type to Marshaller instances
var SupportedContentTypes = []string{"text/plain", "application/vnd.romana.v1+json", "application/vnd.romana+json", "application/json", "application/x-www-form-urlencoded"}
List of supported content types to return in a 406 response.
var SupportedContentTypesMessage = struct { SupportedContentTypes []string `json:"supported_content_types"` }{ SupportedContentTypes, }
Above list of supported content types wrapped in a struct for converion to JSON.
Functions ¶
func Environ ¶ added in v0.8.2
Environ is similar to os.Environ() but returning environment as a map instead of an array of strings.
func GetCaller ¶ added in v1.0.0
func GetCaller() string
GetCaller returns the location information of the caller of the method that invoked GetCaller.
func GetCaller2 ¶ added in v1.0.0
GetCaller2 is similar to GetCaller but goes up the specified number of frames.
func GetMockDbName ¶ added in v1.0.0
GetMockDbName creates a DB name as follows: <SERVICE_NAME>_<Result of getUniqueMockNameComponent()>
func IsZeroValue ¶ added in v0.9.1
func IsZeroValue(val interface{}) bool
IsZeroValue checks whether the provided value is equal to the zero value for the type. Zero values would be:
- 0 for numeric types
- "" for strings
- uninitialized struct for a struct
- zero-size for a slice or a map
func MakeMultiError ¶
MakeMultiError creates a single error object out of an array of errors as follows: 1. If the array is empty or nil, nil is returned 2. If the array has exactly 1 element, that element is returned 3. Otherwise, a MultiError is returned.
func PressEnterToContinue ¶
func PressEnterToContinue()
func ReadKeyFile ¶ added in v1.0.0
ReadKeyFile reads a key from the provided file.
Types ¶
type Attribute ¶ added in v1.0.0
type Attribute struct { AttributeKey string `json:"attribute_key"` AttributeValue string `json:"attribute_value"` Id int `sql:"AUTO_INCREMENT"` }
An Attribute of a user is something that is used in the ABAC part of our AuthZ scheme. Not every role would be checked for atributes. For now, only if the user has a role of tenant, it's attribute for key "tenant" is checked against the tenant ID by tenant service.
type AuthMiddleware ¶
AuthMiddleware wrapper for auth.
func NewAuthMiddleware ¶ added in v1.0.0
func NewAuthMiddleware(service Service) (AuthMiddleware, error)
NewAuthMiddleware creates new AuthMiddleware to use. Its behavior depends on whether it is for root (in which case the public key is gotten from the config file) or another service (in which case the public key is gotten from the root).
func (AuthMiddleware) Keyfunc ¶ added in v1.0.0
func (am AuthMiddleware) Keyfunc(*jwt.Token) (interface{}, error)
Keyfunc implements jwt.Keyfunc (https://godoc.org/github.com/dgrijalva/jwt-go#Keyfunc) by returning the public key
func (AuthMiddleware) ServeHTTP ¶
func (am AuthMiddleware) ServeHTTP(writer http.ResponseWriter, request *http.Request, next http.HandlerFunc)
ServeHTTP implements the middleware contract as follows:
- If the path of request is one of the AllowedURLs, then this is a no-op. 2 Otherwise, checks token from request. If the token is not valid, returns a 403 FORBIDDEN status.
type AuthTokenMessage ¶ added in v1.0.0
AuthTokenMessage is returned by Root service upon a client's authentication. The token is generated by the root server depending on the information looked up on the user (roles and attributes) and the public key is the root server's public key to verify the token (which is signed by root's private key).
type AuthZChecker ¶ added in v1.0.0
type AuthZChecker func(ctx RestContext) bool
AuthZChecker takes a user and outputs whether the user is allowed to access a resource. If defined on a Route, it will be automatically invoked by wrapHandler(), which will provide RestContext.
type Config ¶
type Config struct { EtcdEndpoints []string EtcdPrefix string InitialTopologyFile *string Mock bool }
Config is the configuration required for a Romana client library. TODO it is here temporarily until circular imports are resolved.
type Credential ¶ added in v0.8.2
type Credential struct { Type CredentialType Username string Password string // contains filtered or unexported fields }
Container for various credentials. Currently containing Username/Password but keys, certificates, etc. can be used in the future.
func NewCredential ¶ added in v1.0.0
func NewCredential(flagSet *flag.FlagSet) *Credential
func NewCredentialCobra ¶ added in v1.0.0
func NewCredentialCobra(cmd *cli.Command) *Credential
func (*Credential) Initialize ¶ added in v1.0.0
func (c *Credential) Initialize() error
Initialize constructs appropriate Credential structure based on provided data, which includes, in the following precedence (later superseding earlier): * In case of username/password auth:
- As keys UsernameKey and PasswordKey in ~/.romana.yaml file
- As environment variables whose names are UsernameKey and PasswordKey values
- As --username and --password command-line flags. If --username flag is specified but --password flag is omitted, the user will be prompted for the password.
Notes:
- The first two precedence steps (~/.romana.yaml and environment variables) are taken care by the config module (github.com/spf13/viper)
- If flag.Parsed() is false at the time of this call, the command-line values are ignored.
func (*Credential) String ¶ added in v1.0.0
func (c *Credential) String() string
type CredentialType ¶ added in v0.8.2
type CredentialType string
Represents the type of credential (e.g., certificate, username-password, etc.)
type ExecErrorDetails ¶ added in v0.9.0
type ExecErrorDetails struct {
Error string
}
type HttpError ¶
type HttpError struct { // HTTP status code StatusCode int `json:"status_code"` Details interface{} `json:"details,omitempty"` // ResourceID specifies the relevant resource ID, if applicable ResourceID string `json:"resource_id,omitempty"` // ResourceType specifies the relevant resource type, if applicable ResourceType string `json:"resource_type,omitempty"` SeeAlso string `json:"see_also, omitempty"` }
HttpError is a structure that represents, well, an HTTP error.
func NewError400 ¶
func NewError400(details interface{}) HttpError
NewError400 creates an HttpError with 400 (http.StatusBadRequest) status code.
func NewError403 ¶ added in v1.0.0
func NewError403() HttpError
NewError403 creates a 403 FORBIDDEN message.
func NewError404 ¶
NewError404 creates a 404 NOT FOUND message.
func NewError500 ¶
func NewError500(details interface{}) HttpError
NewError500 creates an HttpError with 500 (http.StatusInternalServerError) status code.
func NewErrorConflict ¶ added in v0.9.0
func NewErrorConflict(details interface{}) HttpError
NewErrorConflict creates an HttpError with 409 (http.StatusConflict) status code.
func NewHttpError ¶ added in v0.9.0
NewError helps to construct new Error structure.
func NewUnprocessableEntityError ¶ added in v0.9.0
func NewUnprocessableEntityError(details interface{}) HttpError
NewUnprocessableEntityError creates an HttpError with 423 (StatusUnprocessableEntity) status code.
func (HttpError) StatusText ¶
StatusText returns the string value of the HttpError corresponding to the StatusCode.
type KeyValue ¶ added in v0.9.3
type KeyValue struct { Key string Value interface{} }
KeyValue represents a key-value pair (similar to Java's Map.Entry)
type LinkResponse ¶
LinkResponse structure represents the commonly occurring
{ "href" : "https://<own-addr>", "rel" : "self" }
part of the response.
type Links ¶
type Links []LinkResponse
type MakeMessage ¶
type MakeMessage func() interface{}
MakeMessage is a factory function, which should return a pointer to an instance into which we will unmarshal wire data.
type Marshaller ¶
type Marshaller interface { Marshal(v interface{}) ([]byte, error) Unmarshal(data []byte, v interface{}) error }
Marshaller is capable of marshalling and unmarshalling data to/from the wire.
type MultiError ¶
type MultiError struct {
// contains filtered or unexported fields
}
MultiError is a facility to collect multiple number of errors but present them as a single error interface. For example, GORM does not return errors at every turn. It accumulates them and returns them whenever you feel like calling GetErrors() (https://godoc.org/github.com/jinzhu/gorm#DB.GetErrors). Since this is not consistent with the rest of the code, I prefer to isolate it here and make an adapter.
func NewMultiError ¶
func NewMultiError() *MultiError
NewMultiError creates a new MultiError object to which errors can be added.
func (MultiError) Add ¶
func (me MultiError) Add(err error)
Add adds an error to the MultiError object.
func (*MultiError) Error ¶
func (m *MultiError) Error() string
Error satisfies Error method on error interface and returns a concatenated string of all error messages.
func (*MultiError) GetError ¶
func (m *MultiError) GetError() error
GetError returns nil if there are no underlying errors, the single error if there is only one, and the MultiError object if there is more than one.
func (*MultiError) GetErrors ¶ added in v0.9.0
func (m *MultiError) GetErrors() []error
GetErrors returns all errors in this MultiError object.
type NegotiatorMiddleware ¶
type NegotiatorMiddleware struct { }
func NewNegotiator ¶
func NewNegotiator() *NegotiatorMiddleware
func (NegotiatorMiddleware) ServeHTTP ¶
func (negotiator NegotiatorMiddleware) ServeHTTP(writer http.ResponseWriter, request *http.Request, next http.HandlerFunc)
type PortUpdateMessage ¶
type PortUpdateMessage struct {
Port uint64 `json:"port"`
}
Message to register with the root service the actual port a service is listening on.
type Raw ¶ added in v0.9.0
type Raw struct {
Body string
}
Raw is a type that can be returned from any service's route and the middleware will not try to marshal it.
type RestContext ¶
type RestContext struct { // Path variables as described in https://godoc.org/code.google.com/p/gorilla/mux PathVariables map[string]string // QueryVariables stores key-value-list map of query variables, see url.Values // for more details. QueryVariables url.Values // Unique identifier for a request. RequestToken string User User // Output of the hook if any run before the execution of the handler. HookOutput string }
RestContext contains the context of the REST request other than the body data that has been unmarshaled.
type RestHandler ¶
type RestHandler func(input interface{}, context RestContext) (interface{}, error)
RestHandler specifies type of a function that each Route provides. It takes (for now) an interface as input, and returns any interface. The middleware provided in this file takes care of unmarshalling the data from the wire to the input object (the type of the object created will be determined by the type of the instance provided in Consumes field of Route type, below), and of marshalling the returned object to the wire (the type of which is determined by type of the instance provided in Produces field of Route type, below).
type RestServiceInfo ¶
type RestServiceInfo struct { // Address being listened on (as host:port) Address string // Channel to communicate with the service Channel chan ServiceMessage }
RestServiceInfo describes information about a running Romana service.
func InitializeService ¶
func InitializeService(service Service, config Config) (*RestServiceInfo, error)
InitializeService initializes the service with the provided config and starts it. The channel returned allows the caller to wait for a message from the running service. Messages are of type ServiceMessage above. It can be used for launching service from tests, etc.
func ListenAndServe ¶
func ListenAndServe(svr *http.Server) (*RestServiceInfo, error)
ListenAndServe is same as http.ListenAndServe except it returns the address that will be listened on (which is useful when using arbitrary ports). See https://github.com/golang/go/blob/master/src/net/http/server.go
func RunNegroni ¶
func RunNegroni(n *negroni.Negroni, addr string) (*RestServiceInfo, error)
RunNegroni is a convenience function that runs the negroni stack as a provided HTTP server, with the following caveats:
- the Handler field of the provided serverConfig should be nil, because the Handler used will be the n Negroni object.
type RomanaHandler ¶
type RomanaHandler struct {
// contains filtered or unexported fields
}
RomanaHandler interface to comply with http.Handler
func (RomanaHandler) ServeHTTP ¶
func (romanaHandler RomanaHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request)
ServeHTTP is required by https://golang.org/pkg/net/http/#Handler
type RomanaTestSuite ¶ added in v1.0.0
type RomanaTestSuite struct {
// contains filtered or unexported fields
}
RomanaTestSuite holds state for use in testing.
func (*RomanaTestSuite) CleanUp ¶ added in v1.0.0
func (rts *RomanaTestSuite) CleanUp()
func (*RomanaTestSuite) GetMockSqliteFile ¶ added in v1.0.0
func (rts *RomanaTestSuite) GetMockSqliteFile(svc string) string
type Route ¶
type Route struct { // REST method Method string // Pattern (see http://www.gorillatoolkit.org/pkg/mux) Pattern string // Handler (see documentation above) Handler RestHandler // This should return a POINTER to an instance which // this route expects as an input. MakeMessage MakeMessage // Whether this route is using a request token. If true, the // request token will be parsed out of the request and made // available in RestContext. It can then // used by the handler to achieve idempotence. UseRequestToken bool AuthZChecker AuthZChecker }
Route determines an action taken on a URL pattern/HTTP method. Each service can define a route See routes.go and handlers.go in root package for a demonstration of use
type Service ¶
type Service interface { Initialize(clientConfig Config) error // Returns the routes that this service works with Routes() Routes // Name returns the name of this service. Name() string // GetAddr returns the host/port the service is listening on. GetAddress() string }
Service is the interface that services implement.
type ServiceUtils ¶
type ServiceUtils struct { // ResourceIdToStatus is a maps request ID // to status. A request ID can be a RequestToken if required, // or a resource ID. In general the idea is that this is used // in conjunction with RequestToken. // See also // - Route.UseRequestToken // - RestContext.RequestToken RequestIdToStatus map[string]interface{} // RequestIdToTimestamp maps request ID (for more information // on what that is see RequestIdToStatus) to the timestamp // of the original request. It will later be used for things // such as possible expiration, etc., but for now it's just a // placeholder. RequestIdToTimestamp map[string]int64 }
ServiceUtils represents functionality common to various services. One example of such functionality is asynchronous processing -- a service can accept a request for creation of an object and return a 202 ACCEPTED, creating an entry that can be queried for status.
func (ServiceUtils) AddStatus ¶
func (s ServiceUtils) AddStatus(requestId string, value interface{})
AddStatus adds a status of a request
type UnmarshallerMiddleware ¶
type UnmarshallerMiddleware struct { }
func NewUnmarshaller ¶
func NewUnmarshaller() *UnmarshallerMiddleware
func (UnmarshallerMiddleware) ServeHTTP ¶
func (m UnmarshallerMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)
Unmarshals request body if needed. If not acceptable, returns an http.StatusNotAcceptable and this ends this request's lifecycle.
type UnwrappedRestHandlerInput ¶
type UnwrappedRestHandlerInput struct { ResponseWriter http.ResponseWriter Request *http.Request }
UnwrappedRestHandlerInput is used to pass in http.Request and http.ResponseWriter, should some service like unfettered access directly to them. In such a case, the service's RestHandler's input will be of this type; and the return value will be ignored.
type User ¶ added in v1.0.0
type User struct { UserId int `sql:"AUTO_INCREMENT" json:"user_id" gorm:"primary_key"` jwt.StandardClaims `json:"claims"` Username string `json:"username,omitempty"` Password string `json:"password,omitempty"` Roles []Role `gorm:"many2many:user_roles;ForeignKey:user_id"` Attributes []Attribute `gorm:"many2many:user_attributes;ForeignKey:user_id"` }
User has multiple roles and multiple attributes.
var DefaultAdminUser User
DefaultAdminUser is a dummy user having admin role. It is used when authentication is off.