common

package
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 12, 2017 License: Apache-2.0 Imports: 43 Imported by: 0

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

View Source
const (
	RoleAdmin   = "admin"
	RoleService = "service"
	RoleTenant  = "tenant"
)
View Source
const (
	CredentialUsernamePassword = "userPass"
	CredentialNone             = "none"

	UsernameKey = "ROMANA_USERNAME"
	PasswordKey = "ROMANA_PASSWORD"
)
View Source
const (
	RestRetryStrategyExponential = "exponential"
	RestRetryStrategyFibonacci   = "fibonacci"
)
View Source
const (
	// Flags to store.Find operation
	FindFirst      = "findFirst"
	FindLast       = "findLast"
	FindExactlyOne = "findExactlyOne"
	FindAll        = "findAll"
)
View Source
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

View Source
const (
	PolicyDirectionIngress = "ingress"
	PolicyDirectionEgress  = "egress"
)
View Source
const (
	MySQLUniqueConstraintErrorCode = 1062
	StoreTypeMysql                 = "mysql"
	StoreTypeSqlite3               = "sqlite3"
	StoreTypeEtcd                  = "etcd"
)
View Source
const (
	DefaultTestConfigFile = "../common/testdata/romana.sample.yaml"
)
View Source
const (
	// 422 (unprocessable entity http://www.restpatterns.org/HTTP_Status_Codes/422_-_Unprocessable_Entity)
	// is not in net/http yet.
	StatusUnprocessableEntity = 422
)

Variables

View Source
var (
	IDRingOverflowError          = NewError("No more available IDs")
	IDRingCannotReclaimZeroError = NewError("Cannot reclaim ID 0")
)
View Source
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

View Source
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.

View Source
var SupportedContentTypesMessage = struct {
	SupportedContentTypes []string `json:"supported_content_types"`
}{
	SupportedContentTypes,
}

Above list of supported content types wrapped in a struct for converion to JSON.

View Source
var SupportedStoreTypes []string

Functions

func BuildInfo

func BuildInfo() string

BuildInfo return build revision and time string.

func CleanURL

func CleanURL(url string) (string, error)

CleanURL is similar to path.Clean() but to work on URLs

func DbToHttpError

func DbToHttpError(err error) error

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

func Environ() map[string]string

Environ is similar to os.Environ() but returning environment as a map instead of an array of strings.

func ExpectHttpError

func ExpectHttpError(c *check.C, err error, code int)

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

func GetCaller2(up int) string

GetCaller2 is similar to GetCaller but goes up the specified number of frames.

func GetDbErrors

func GetDbErrors(db *gorm.DB) error

GetDbErrors creates MultiError on error from DB.

func GetMockDbName

func GetMockDbName(svc string) string

GetMockDbName creates a DB name as follows: <SERVICE_NAME>_<Result of getUniqueMockNameComponent()>

func GetPasswd

func GetPasswd() (string, error)

GetPasswd gets password from stdin.

func IPv4ToInt

func IPv4ToInt(ip net.IP) uint64

func In

func In(needle string, haystack []string) bool

In returns true if needle is found in haystack.

func InitMap

func InitMap(keyValuePairs ...KeyValue) map[string]interface{}

func IntToIPv4

func IntToIPv4(ipInt uint64) net.IP

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

func MakeMultiError(errors []error) error

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 MkMap

func MkMap() map[string]interface{}

func MkMapStr

func MkMapStr() map[string]string

func NewError

func NewError(text string, args ...interface{}) error

NewError constructs an error by formatting text with arguments.

func PressEnterToContinue

func PressEnterToContinue()

func ReadKeyFile

func ReadKeyFile(filename string) (*pem.Block, error)

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 String

func String(i interface{}) string

func ToBool

func ToBool(val interface{}) (bool, error)

ToBool is a convenience function that's like ParseBool but allows also "on"/"off" values.

func WriteConfig

func WriteConfig(config Config, fname string) error

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

func (api Api) GetHostPort() string

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

type AuthMiddleware struct {
	PublicKey   *rsa.PublicKey
	AllowedURLs []string
}

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:

  1. 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

type AuthTokenMessage struct {
	Token     string `json:"token"`
	PublicKey []byte `json:"public_key"`
}

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) Init

func (cs *CliState) Init() error

Init calls flag.Parse() and, for now, sets up the credentials.

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

func ReadConfig(fname string) (Config, error)

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:

  1. As keys UsernameKey and PasswordKey in ~/.romana.yaml file
  2. As environment variables whose names are UsernameKey and PasswordKey values
  3. 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:

  1. The first two precedence steps (~/.romana.yaml and environment variables) are taken care by the config module (github.com/spf13/viper)
  2. 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.

func (Endpoint) String

func (e Endpoint) String() string

type ExecErrorDetails

type ExecErrorDetails struct {
	Error string
}

type FindFlag

type FindFlag 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 NewError403

func NewError403() HttpError

NewError403 creates a 403 FORBIDDEN message.

func NewError404

func NewError404(resourceType string, resourceID string) HttpError

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

func NewHttpError(code int, details interface{}) HttpError

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) Error

func (httpErr HttpError) Error() string

String returns formatted HTTP error for human consumption.

func (HttpError) StatusText

func (err HttpError) StatusText() string

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

func DecodeIDRing(data []byte) (IDRing, error)

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) Encode

func (ir IDRing) Encode() ([]byte, error)

Encode encodes the IDRing into an array of bytes.

func (*IDRing) GetID

func (idRing *IDRing) GetID() (uint64, error)

GetID returns the first available ID, starting with 1. It will return an IDRingOverflowError if no more IDs can be returned.

func (*IDRing) ReclaimID

func (idRing *IDRing) ReclaimID(id uint64) error

ReclaimID returns the provided ID into the pool, so it can be returned again upon some future call to GetID.

func (IDRing) String

func (ir IDRing) String() string

String returns a human-readable representation of the ring.

type IP

type IP struct {
	// contains filtered or unexported fields
}

func MakeIPv4

func MakeIPv4(a, b, c, d byte) IP

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

type IPtablesRule struct {
	ID    uint64 `sql:"AUTO_INCREMENT"`
	Body  string
	State string
}

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

type IndexResponse struct {
	ServiceName string `json:"service_name"`
	Links       Links  `json:"links"`
}

Response to /

type KeyValue

type KeyValue struct {
	Key   string
	Value interface{}
}

KeyValue represents a key-value pair (similar to Java's Map.Entry)

func KV

func KV(key string, value interface{}) KeyValue

KV is a convenience function to create a KeyValue value.

type LinkResponse

type LinkResponse struct {
	Href string `json:"href,omitempty"`
	Rel  string `json:"rel,omitempty"`
}

LinkResponse structure represents the commonly occurring

{
       "href" : "https://<own-addr>",
       "rel"  : "self"
 }

part of the response.

type Links []LinkResponse

func (Links) FindByRel

func (links Links) FindByRel(rel string) string

FindByRel finds the path (href) for a link based on its rel value. This is because in the REST message links are organized as an array of structures containing href and rel, but, of course, in actual usage it is easier to be used as a map.

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) String

func (p Policy) String() string

func (*Policy) Validate

func (p *Policy) Validate() error

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:

  1. 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 PortRange

type PortRange [2]uint

func (PortRange) String

func (p PortRange) String() string

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

type Range struct {
	Min uint64
	Max uint64
}

Range represents a range of uint64s that can be used as sequential IDs. The range is inclusive.

func (Range) String

func (irr Range) String() string

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

func RunNegroni(n *negroni.Negroni, addr string, timeout time.Duration) (*RestServiceInfo, error)

RunNegroni is a convenience function that runs the negroni stack as a provided HTTP server, with the following caveats:

  1. 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 Role

type Role struct {
	Name string `json:"name"`
	Id   int    `sql:"AUTO_INCREMENT"`
}

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 RomanaIngress struct {
	Peers []Endpoint `json:"peers,omitempty"`
	Rules []Rule     `json:"rules,omitempty"`
}

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:

  1. Replacing all ports with 0 (making the services use ephemeral ports)
  2. 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

func CreateFindRoutes(entities interface{}, store Store) Routes

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.

func (Rule) String

func (r Rule) String() string

type Rules

type Rules []Rule

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 ServiceMessage

type ServiceMessage string

Type definitions

type ServiceResponse

type ServiceResponse struct {
	Name  string `json:"name"`
	Links Links  `json:"links"`
}

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

func (ServiceUtils) GetStatus

func (s ServiceUtils) GetStatus(resourceType string, requestId string) (interface{}, error)

GetStatus gets the status of the request or returns an common.HttpError (404) if not found.

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

type Tag struct {
	Key   string `json:"key,omitempty"`
	Value string `json:"value,omitempty"`
}

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

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.

Directories

Path Synopsis
log
Package store provides routines for backing storage, currently supporting libkv and RDBMS-based backends.
Package store provides routines for backing storage, currently supporting libkv and RDBMS-based backends.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL