Documentation ¶
Overview ¶
Package common contains various things common to all Romana services.
Contains general routines and definitions for a generic back-end storage (currently geared towards RDBMS but not necessarily limited to that).
Index ¶
- Constants
- Variables
- func BuildInfo() string
- func CleanURL(url string) (string, error)
- func DbToHttpError(err error) error
- func Environ() map[string]string
- func ExpectHttpError(c *check.C, err error, code int)
- func GetCaller() string
- func GetCaller2(up int) string
- func GetDbErrors(db *gorm.DB) error
- 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 SimpleOverwriteSchema(svc Service, rootURL string, cred *Credential) error
- func SqlNullStringUuid() sql.NullString
- func String(i interface{}) string
- func ToBool(val interface{}) (bool, error)
- func WriteConfig(config Config, fname string) error
- type Api
- type Attribute
- type AuthMiddleware
- type AuthTokenMessage
- type AuthZChecker
- type CliState
- type CommonConfig
- type Config
- type Credential
- type CredentialType
- type Datacenter
- type Endpoint
- type ExecErrorDetails
- type FindFlag
- type Hook
- type Host
- 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 IDRing
- type IP
- type IPAMEndpoint
- type IPtablesRule
- type IndexResponse
- type KeyValue
- type LinkResponse
- type Links
- type MakeMessage
- type Marshaller
- type MultiError
- type NegotiatorMiddleware
- type Policy
- type PortRange
- type PortUpdateMessage
- type Range
- type Raw
- type RestClient
- func (rc *RestClient) Authenticate() error
- func (rc *RestClient) Delete(url string, data interface{}, result interface{}) error
- func (rc *RestClient) Find(entity interface{}, flag FindFlag) error
- func (rc *RestClient) Get(url string, result interface{}) error
- func (rc *RestClient) GetPublicKey() (*rsa.PublicKey, error)
- func (rc *RestClient) GetServiceConfig(name string) (*ServiceConfig, error)
- func (rc *RestClient) GetServiceUrl(name string) (string, error)
- func (rc *RestClient) GetStatusCode() int
- func (rc *RestClient) ListHosts() ([]Host, error)
- func (rc *RestClient) NewUrl(dest string) error
- func (rc *RestClient) Post(url string, data interface{}, result interface{}) error
- func (rc *RestClient) Put(url string, data interface{}, result interface{}) error
- type RestClientConfig
- type RestContext
- type RestHandler
- type RestServiceInfo
- func InitializeService(service Service, config ServiceConfig, cred *Credential) (*RestServiceInfo, error)
- func ListenAndServe(svr *http.Server) (*RestServiceInfo, error)
- func RunNegroni(n *negroni.Negroni, addr string, timeout time.Duration) (*RestServiceInfo, error)
- func SimpleStartService(svc Service, rootURL string, cred *Credential) (*RestServiceInfo, error)
- type Role
- type RomanaHandler
- type RomanaIngress
- type RomanaTestSuite
- type RootIndexResponse
- type Route
- type Routes
- type Rule
- type Rules
- type Segment
- type Service
- type ServiceConfig
- type ServiceMessage
- type ServiceResponse
- type ServiceStore
- type ServiceUtils
- type Store
- type StoreConfig
- type Tag
- type Tenant
- 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 ( RestRetryStrategyExponential = "exponential" RestRetryStrategyFibonacci = "fibonacci" )
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" // DefaultRestTimeout, in milliseconds. DefaultRestTimeout = 500 DefaultRestRetryStrategy = "fibonacci" DefaultRestRetries = 3 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" // Max port number for TCP/UDP. MaxPortNumber = 65535 MaxIcmpType = 255 // Wildcard Wildcard = "any" // Name of main Romana service ServiceNameRoot = "root" ServiceNameTest = "test" FullConfigKey = "fullConfig" )
Constants
const ( PolicyDirectionIngress = "ingress" PolicyDirectionEgress = "egress" )
const ( MySQLUniqueConstraintErrorCode = 1062 StoreTypeMysql = "mysql" StoreTypeSqlite3 = "sqlite3" StoreTypeEtcd = "etcd" )
const (
DefaultTestConfigFile = "../common/testdata/romana.sample.yaml"
)
const ( // 422 (unprocessable entity http://www.restpatterns.org/HTTP_Status_Codes/422_-_Unprocessable_Entity) // is not in net/http yet. StatusUnprocessableEntity = 422 )
Variables ¶
var ( IDRingOverflowError = NewError("No more available IDs") IDRingCannotReclaimZeroError = NewError("Cannot reclaim ID 0") )
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.
var SupportedStoreTypes []string
Functions ¶
func DbToHttpError ¶
DbToHttpError produces an appropriate HttpError given an error, if it can (for example, producing a 409 CONFLICT in case of a unique or primary key constraint violation). If it cannot, it returns the original error.
func Environ ¶
Environ is similar to os.Environ() but returning environment as a map instead of an array of strings.
func ExpectHttpError ¶
ExpectHttp fails if the error is not an HttpError with a specified status code.
func GetCaller ¶
func GetCaller() string
GetCaller returns the location information of the caller of the method that invoked GetCaller.
func GetCaller2 ¶
GetCaller2 is similar to GetCaller but goes up the specified number of frames.
func GetDbErrors ¶
GetDbErrors creates MultiError on error from DB.
func GetMockDbName ¶
GetMockDbName creates a DB name as follows: <SERVICE_NAME>_<Result of getUniqueMockNameComponent()>
func IsZeroValue ¶
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 ¶
ReadKeyFile reads a key from the provided file.
func SimpleOverwriteSchema ¶
func SimpleOverwriteSchema(svc Service, rootURL string, cred *Credential) error
SimpleOverwriteSchema is intended to be used from tests, it provides a shortcut for the overwriteSchema functionality.
func SqlNullStringUuid ¶
func SqlNullStringUuid() sql.NullString
func ToBool ¶
ToBool is a convenience function that's like ParseBool but allows also "on"/"off" values.
func WriteConfig ¶
WriteConfig writes config from file to structure
Types ¶
type Api ¶
type Api struct { // Host to listen on. Host string `yaml:"host" json:"host"` // Port to listen on. Port uint64 `yaml:"port" json:"port"` // Root service URL RootServiceUrl string `json:"root_service_url,omitempty" yaml:"root_service_url,omitempty"` // Rest timeout in milliseconds (if omitted, defaults to DefaultRestTimeout) RestTimeoutMillis int64 `yaml:"rest_timeout_millis,omitempty" json:"rest_timeout_millis,omitempty"` RestRetries int `yaml:"rest_retries,omitempty" json:"rest_retries,omitempty"` RestRetryStrategy string `yaml:"rest_retry_strategy,omitempty" yaml:"rest_retry_strategy,json"` // Location of the public key. AuthPublic string `yaml:"auth_public" json:"auth_public"` RestTestMode bool `yaml:"rest_test_mode,omitempty" json:"rest_test_mode,omitempty"` Hooks []Hook }
Api part of service configuration (host/port).
func (Api) GetHostPort ¶
type Attribute ¶
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 ¶
func NewAuthMiddleware(service Service, config ServiceConfig, client *RestClient) (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 ¶
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 ¶
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 ¶
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 CliState ¶
type CliState struct { CreateSchema *bool OverwriteSchema *bool RootURL *string ConfigFile *string // contains filtered or unexported fields }
CliState represents the state needed for starting of various services. This is here to avoid copy-pasting common command-line argument information, configuration, credentials, etc.
func NewCliState ¶
func NewCliState() *CliState
NewCliState creates a new CliState with initial fields
func (*CliState) StartService ¶
func (c *CliState) StartService(svc Service) (*RestServiceInfo, error)
StartService calls Init() and starts the provided service (or, does what is required by command-line arguments, such as printing usage info or version).
type CommonConfig ¶
type CommonConfig struct { Api *Api `yaml:"api" json:"api"` // Credential is convenient to store here but it is not part of the // configuration that is passed around in JSON. Credential *Credential `yaml:"-" json:"-"` PublicKey []byte `yaml:"-" json:"-"` }
CommonConfig stores configuration that is common to all services. For things such as API information (host/port), DB, etc.
type Config ¶
type Config struct {
Services map[string]ServiceConfig
}
Config provides the main configuration object
func ReadConfig ¶
ReadConfig parses the configuration file provided and returns ReadConfig reads config from file to structure
type Credential ¶
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 ¶
func NewCredential(flagSet *flag.FlagSet) *Credential
func NewCredentialCobra ¶
func NewCredentialCobra(cmd *cli.Command) *Credential
func (*Credential) Initialize ¶
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 ¶
func (c *Credential) String() string
type CredentialType ¶
type CredentialType string
Represents the type of credential (e.g., certificate, username-password, etc.)
type Datacenter ¶
type Datacenter struct { Id uint64 `json:"id" sql:"AUTO_INCREMENT"` IpVersion uint `json:"ip_version,omitempty"` // We don't need to store this, but calculate and pass around Prefix uint64 `json:"prefix,omitempty"` Cidr string `json:"cidr,omitempty"` PrefixBits uint `json:"prefix_bits"` PortBits uint `json:"port_bits"` TenantBits uint `json:"tenant_bits"` SegmentBits uint `json:"segment_bits"` // We don't need to store this, but calculate and pass around EndpointBits uint `json:"endpoint_bits"` EndpointSpaceBits uint `json:"endpoint_space_bits"` Name string `json:"name,omitempty"` }
Datacenter represents the configuration of a datacenter.
func (Datacenter) String ¶
func (dc Datacenter) String() string
type Endpoint ¶
type Endpoint struct { Peer string `json:"peer,omitempty"` Cidr string `json:"cidr,omitempty"` Dest string `json:"dest,omitempty"` TenantID uint64 `json:"tenant_id,omitempty"` TenantName string `json:"tenant,omitempty"` TenantExternalID string `json:"tenant_external_id,omitempty"` TenantNetworkID *uint64 `json:"tenant_network_id,omitempty"` SegmentID uint64 `json:"segment_id,omitempty"` SegmentName string `json:"segment,omitempty"` SegmentExternalID string `json:"segment_external_id,omitempty"` SegmentNetworkID *uint64 `json:"segment_network_id,omitempty"` }
Endpoint represents an endpoint - that is, something that has an IP address and routes to/from. It can be a container, a Kubernetes POD, a VM, etc.
type ExecErrorDetails ¶
type ExecErrorDetails struct {
Error string
}
type Hook ¶
type Hook struct { // Executable to run Executable string `json:"executable"` // Pattern to match in common.Route Pattern string `json:"pattern"` // HTTP method to match Method string `json:"method"` // Whether to run before or after the handler for the pattern/method // pair is invoked When string `json:"when"` // Where to write output (if omitted, will be just logged) Output string `json:"output"` }
Hook defines an executable to run before or after any Route handler execution.
type Host ¶
type Host struct { ID uint64 `sql:"AUTO_INCREMENT" json:"id,omitempty"` Name string `json:"name,omitempty"` Ip string `json:"ip,omitempty" sql:"unique"` RomanaIp string `json:"romana_ip,omitempty" sql:"unique"` AgentPort uint64 `json:"agent_port,omitempty"` Links Links `json:"links,omitempty" sql:"-"` }
Host is a structure representing information about the host.
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 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 ¶
func NewErrorConflict(details interface{}) HttpError
NewErrorConflict creates an HttpError with 409 (http.StatusConflict) status code.
func NewHttpError ¶
NewError helps to construct new Error structure.
func NewUnprocessableEntityError ¶
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 IDRing ¶
type IDRing struct { // Ranges is an ordered set of ranges from which we allocate IDs. // Initially this should include a single Range, // from 1 to MaxUint64. // When this is nil, it means that we have exhausted the entire // range from 1 to MaxInt, and, unless an ID is reclaimed, no more // IDs can be given out. // TODO this implementation is probably better (memory-wise) for a lot of allocations, with few // reclaimed IDs, as is often the case. But if there are intended to be relatively // few allocations and lots of reuse, a faster (less memory-efficient, which doesn't matter // at small sizes) would be better. Thus it may make sense to extract // an interface and split implementation into 2: intended for mostly allocations and few // reclamations, and intended for few allocations with a lot of reclamations. Ranges []Range // contains filtered or unexported fields }
idRing is responsible for allocating first available ID. Initially the available range is from 1 to math.MaxUint64. As IDs are allocated, the range shrinks. IDs can be returned to the ring. An instance of this SHOULD NOT be created directly, use NewIDRing() to create it.
func DecodeIDRing ¶
DecodeIDRing decodes IDRing object from the byte array.
func NewIDRing ¶
func NewIDRing() IDRing
NewIDRing constructs a new IDRing instance with a single range, from 1 to MaxInt, and initialized mutex.
func (*IDRing) GetID ¶
GetID returns the first available ID, starting with 1. It will return an IDRingOverflowError if no more IDs can be returned.
type IPAMEndpoint ¶
type IPAMEndpoint struct { Ip string `json:"ip,omitempty"` TenantID string `json:"tenant_id,omitempty"` SegmentID string `json:"segment_id,omitempty"` HostId string `json:"host_id,omitempty"` Name string `json:"name,omitempty"` RequestToken sql.NullString `json:"request_token" sql:"unique"` // Ordinal number of this Endpoint in the host/tenant combination NetworkID uint64 `json:"-"` // Calculated effective network ID of this Endpoint -- // taking into account stride (endpoint space bits) // and alignment thereof. This is used in IP calculation. EffectiveNetworkID uint64 `json:"-"` // Whether it is in use (for purposes of reclaiming) InUse bool Id uint64 `sql:"AUTO_INCREMENT" json:"-"` }
IPAMEndpoint represents an endpoint (a VM, a Kubernetes Pod, etc.) that is to get an IP address.
type IPtablesRule ¶
IPtablesRule represents a single iptables rule managed by the agent. TODO Originally defined in pkg/util/firewall, redefined here only to support new way of schema creation. WARNING. This might get out of sync with original definition. Stas.
type IndexResponse ¶
Response to /
type KeyValue ¶
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 ¶
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 Policy ¶
type Policy struct { // Direction is one of common.PolicyDirectionIngress or common.PolicyDirectionIngress, // otherwise common.Validate will return an error. Direction string `json:"direction,omitempty" romana:"desc:Direction is one of 'ingress' or egress'."` // Description is human-redable description of the policy. Description string `json:"description,omitempty"` // Name is human-readable name for this policy. Name string `json:"name" romana:"desc:Name is human-readable name for this policy."` // ID is Romana-generated unique (within Romana deployment) ID of this policy, // to be used in REST requests. It will be ignored when set by user. ID uint64 `json:"id,omitempty" sql:"AUTO_INCREMENT"` // ExternalID is an optional identifier of this policy in an external system working // with Romana in this deployment (e.g., Open Stack). ExternalID string `json:"external_id,omitempty"` // Datacenter describes a Romana deployment. Datacenter *Datacenter `json:"datacenter,omitempty"` AppliedTo []Endpoint `json:"applied_to,omitempty"` Ingress []RomanaIngress `json:"ingress,omitempty"` }
Policy describes Romana network security policy. For examples, see: 1. https://github.com/romana/core/blob/master/policy/policy.sample.json 2. https://github.com/romana/core/blob/master/policy/policy.example.agent.json
func (*Policy) Validate ¶
Validate validates the policy and returns an Unprocessable Entity (422) HttpError if the policy is invalid. The following would lead to errors if they are not specified elsewhere: 1. Rules must be specified. TODO As a reference I'm using https://docs.google.com/spreadsheets/d/1vN-EnZqJnIp8krY1cRf6VzRPkO9_KNYLW0QOfw2k1Mo/edit which we'll remove from this comment once finalized. This also mutates the policy to ensure the following:
- If only one of Name, External ID is specified, then the unspecified field is populated from the specified one.
TODO mutation is probably a bad idea for a method called Validate(); however, this behavior is probably a good idea, as it is a sort of DWIM. Maybe keep behavior, rename this to ValidateAndNormalize()?
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 Range ¶
Range represents a range of uint64s that can be used as sequential IDs. The range is inclusive.
type Raw ¶
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 RestClient ¶
type RestClient struct {
// contains filtered or unexported fields
}
Rest Client for the Romana services. Incorporates facilities to deal with various REST requests.
func NewRestClient ¶
func NewRestClient(config RestClientConfig) (*RestClient, error)
NewRestClient creates a new Romana REST client. It provides convenience methods to make REST calls. When configured with a root URL pointing to Romana root service, it provides some common functionality useful for Romana services (such as ListHosts, GetServiceConfig, etc.) If the root URL does not point to the Romana service, the generic REST operations still work, but Romana-specific functionality does not.
func (*RestClient) Authenticate ¶
func (rc *RestClient) Authenticate() error
Authenticate sends credential information to the Root's authentication URL and stores the token received.
func (*RestClient) Delete ¶
func (rc *RestClient) Delete(url string, data interface{}, result interface{}) error
Delete applies DELETE method to the specified URL, putting the result into the provided interface
func (*RestClient) Find ¶
func (rc *RestClient) Find(entity interface{}, flag FindFlag) error
Find is a convenience function, which queries the appropriate service and retrieves one entity based on provided structure, and puts the results into the same structure. The provided argument, entity, should be a pointer to the desired structure, e.g., &common.Host{}.
func (*RestClient) Get ¶
func (rc *RestClient) Get(url string, result interface{}) error
Get applies GET method to the specified URL, putting the result into the provided interface
func (*RestClient) GetPublicKey ¶
func (rc *RestClient) GetPublicKey() (*rsa.PublicKey, error)
GetPublicKey retrieves public key of root service used ot check auth tokens.
func (*RestClient) GetServiceConfig ¶
func (rc *RestClient) GetServiceConfig(name string) (*ServiceConfig, error)
GetServiceConfig retrieves configuration for the given service from the root service.
func (*RestClient) GetServiceUrl ¶
func (rc *RestClient) GetServiceUrl(name string) (string, error)
GetServiceUrl is a convenience function, which, given the root service URL and name of desired service, returns the URL of that service.
func (*RestClient) GetStatusCode ¶
func (rc *RestClient) GetStatusCode() int
GetStatusCode returns status code of last executed request. As stated above, it is not recommended to share RestClient between goroutines. 0 is returned if no previous requests have been yet made, or if the most recent request resulted in some error that was not a 4xx or 5xx HTTP error.
func (*RestClient) ListHosts ¶
func (rc *RestClient) ListHosts() ([]Host, error)
ListHost queries the Topology service in order to return a list of currently configured hosts in a Romana cluster.
func (*RestClient) NewUrl ¶
func (rc *RestClient) NewUrl(dest string) error
NewUrl sets the client's new URL (yes, it mutates) to dest. If dest is a relative URL then it will be based on the previous value of the URL that the RestClient had.
func (*RestClient) Post ¶
func (rc *RestClient) Post(url string, data interface{}, result interface{}) error
Post applies POST method to the specified URL, putting the result into the provided interface
func (*RestClient) Put ¶
func (rc *RestClient) Put(url string, data interface{}, result interface{}) error
Put applies PUT method to the specified URL, putting the result into the provided interface
type RestClientConfig ¶
type RestClientConfig struct { TimeoutMillis int64 Retries int RetryStrategy string Credential *Credential TestMode bool RootURL string }
RestClientConfig holds configuration for the Romana RESTful client.
func GetDefaultRestClientConfig ¶
func GetDefaultRestClientConfig(rootURL string, cred *Credential) RestClientConfig
GetDefaultRestClientConfig gets a RestClientConfig with specified rootURL and other values set to their defaults, such as DefaultRestTimeout, DefaultRestRetries.
func GetRestClientConfig ¶
func GetRestClientConfig(config ServiceConfig, cred *Credential) RestClientConfig
GetRestClientConfig returns a RestClientConfig based on a ServiceConfig. That is, the information provided in the service configuration is used for the client configuration.
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 ServiceConfig, cred *Credential) (*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 ¶
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.
func SimpleStartService ¶
func SimpleStartService(svc Service, rootURL string, cred *Credential) (*RestServiceInfo, error)
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 RomanaIngress ¶
type RomanaTestSuite ¶
type RomanaTestSuite struct { ConfigFile string Config Config // contains filtered or unexported fields }
RomanaTestSuite holds state for use in testing.
func (*RomanaTestSuite) CleanUp ¶
func (rts *RomanaTestSuite) CleanUp()
func (*RomanaTestSuite) GetMockSqliteFile ¶
func (rts *RomanaTestSuite) GetMockSqliteFile(svc string) string
func (*RomanaTestSuite) MockConfig ¶
func (rts *RomanaTestSuite) MockConfig(romanaConfigFile string) error
MockConfig will take the config file specified and mock things up, by:
- Replacing all ports with 0 (making the services use ephemeral ports)
- Replacing all database instance names with the result of GetMockDbName and write it out to /tmp/romana.yaml
type RootIndexResponse ¶
type RootIndexResponse struct { ServiceName string `json:"service_name"` Links Links `json:"links"` Services []ServiceResponse `json:"services"` }
RootIndexResponse represents a response from the / path specific for root service only.
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 Hook *Hook 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 Routes ¶
type Routes []Route
Routes provided by each service.
func CreateFindRoutes ¶
CreateFindRoutes creates Routes for a find functionality given the provided entities. Four routes are created: 1. /findOne/<entityName>s, which will return a single structure (or an error if more than one entry is found, 2. /findFirst/<entityName>s, which will return the first entity (in order of their creation). 3. /findLast/<entityName>s -- similar to above. 4. /findAll/<entityName>s Routes will return a 404 if no entries found. Here "entities" *must* be a pointer to an array of entities to find (for example, it has to be &[]Tenant{}, not Tenant{}), which will then create /findOne/tenants (returning Tenant structure} and /findAll/tenants (returning []Tenant array) routes.
type Rule ¶
type Rule struct { Protocol string `json:"protocol,omitempty"` Ports []uint `json:"ports,omitempty"` PortRanges []PortRange `json:"port_ranges,omitempty"` // IcmpType only applies if Protocol value is ICMP and // is mutually exclusive with Ports or PortRanges IcmpType uint `json:"icmp_type,omitempty"` IcmpCode uint `json:"icmp_code,omitempty"` IsStateful bool `json:"is_stateful,omitempty"` }
Rule describes a rule of the policy. The following requirements apply (the policy would not be validated otherwise): 1. Protocol must be specified. 2. Protocol must be one of those validated by isValidProto(). 3. Ports cannot be negative or greater than 65535. 4. If Protocol specified is "icmp", Ports and PortRanges fields should be blank. 5. If Protocol specified is not "icmp", Icmptype and IcmpCode should be unspecified.
type Segment ¶
type Segment struct { ID uint64 `sql:"AUTO_INCREMENT" json:"id,omitempty"` ExternalID string `sql:"not null" json:"external_id,omitempty" gorm:"COLUMN:external_id"` TenantID uint64 `gorm:"COLUMN:tenant_id" json:"tenant_id,omitempty"` Name string `json:"name,omitempty"` NetworkID uint64 `json:"network_id,omitempty"` }
Segment is a subdivision of tenant.
type Service ¶
type Service interface { // SetConfig sets the configuration, validating it if needed // and returning an error if not valid. SetConfig(config ServiceConfig) error // Initializes the service (mostly for error reporting, could be a no-op) Initialize(client *RestClient) error // Returns the routes that this service works with Routes() Routes // Name returns the name of this service. Name() string CreateSchema(overwrite bool) error }
Service is the interface that microservices implement.
type ServiceConfig ¶
type ServiceConfig struct { Common CommonConfig `json:"common" yaml:"common"` // TODO I really dislike this name, but there // should be some common part that's applicable // to all services, and something service-specific // that we in common do not need to know about. ServiceSpecific map[string]interface{} `json:"config" yaml:"config,omitempty"` }
ServiceConfig contains common configuration for each service and also a section for service-specific configuration. This may be an overkill but if we have a type system, we should use it instead of just dictionaries.
func GetTestServiceConfig ¶
func GetTestServiceConfig() *ServiceConfig
GetTestServiceConfig builds up configuration for test services that is enough for not erroring out, because real services expect it.
type ServiceResponse ¶
Service information
type ServiceStore ¶
type ServiceStore interface { // Entities returns list of entities (DB tables) this store is managing. Entities() []interface{} // CreateSchemaPostProcess runs whatever required post-processing after // schema creation (perhaps initializing DB with some initial or sample data). CreateSchemaPostProcess() error }
ServiceStore interface is what each service's store needs to 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 Store ¶
type Store interface { // SetConfig sets the configuration SetConfig(StoreConfig) error // Connect connects to the store Connect() error // Create the schema, dropping existing one if the force flag is specified CreateSchema(bool) error // Find finds entries in the store based on the query string. The meaning of the // flags is as follows: // 1. FindFirst - the first entity (as ordered by primary key) is returned. // 2. FindLast - tha last entity is returned // 3. FindExactlyOne - it is expected that only one result is to be found -- // multiple results will yield an errror. // 4. FindAll - returns all. // Here "entities" *must* be a pointer to an array // of entities to find (for example, it has to be &[]Tenant{}, not Tenant{}). Find(query url.Values, entities interface{}, flag FindFlag) (interface{}, error) AddHost(dc Datacenter, host *Host) error DeleteHost(hostID uint64) error GetHost(hostID uint64) (Host, error) ListHosts() ([]Host, error) }
Store defines generic store interface that can be used by any service for persistence.
type StoreConfig ¶
type StoreConfig struct { // TODO to accommodate distributed stores, this should be changed to // []Address. For now we'll just use single one. Host string Port uint64 Username string Password string // Database doubles as: // - File name for sqlite // - Prefix for etcd Database string // Database type (one of SupportedStoreTypes) Type string }
StoreConfig stores information needed for a connection to backing store. It is just a typed collection of all possible required parameters, a superset of them.
func MakeStoreConfig ¶
func MakeStoreConfig(configMap map[string]interface{}) (StoreConfig, error)
MakeStoreConfig creates StoreConfig object from a map.
func (StoreConfig) String ¶
func (sc StoreConfig) String() string
type Tag ¶
Metadata attached to entities for various external environments like Open Stack / Kubernetes
type Tenant ¶
type Tenant struct { ID uint64 `sql:"AUTO_INCREMENT" json:"id,omitempty"` // ExternalID is an ID of this tenant in a system that is integrated // with Romana: e.g., OpenStack. ExternalID string `sql:"not null" json:"external_id,omitempty" gorm:"COLUMN:external_id"` Name string `json:"name,omitempty"` Segments []Segment `json:"segments,omitempty"` NetworkID uint64 `json:"network_id,omitempty"` }
Tenant represents a tenant, a top-level entity.
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 ¶
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.