Example #1
0
// ProcessEvent reads, validates and emits a configuration.
func (b *configuratorBehavior) ProcessEvent(event cells.Event) error {
	switch event.Topic() {
	case ReadConfigurationTopic:
		// Read configuration
		filename, ok := event.Payload().GetString(ConfigurationFilenamePayload)
		if !ok {
			logger.Errorf("cannot read configuration without filename payload")
			return nil
		}
		logger.Infof("reading configuration from %q", filename)
		cfg, err := etc.ReadFile(filename)
		if err != nil {
			return errors.Annotate(err, ErrCannotReadConfiguration, errorMessages)
		}
		// If wanted then validate it.
		if b.validate != nil {
			err = b.validate(cfg)
			if err != nil {
				return errors.Annotate(err, ErrCannotValidateConfiguration, errorMessages)
			}
		}
		// All done, emit it.
		pvs := cells.PayloadValues{
			ConfigurationPayload: cfg,
		}
		b.cell.EmitNewContext(ConfigurationTopic, pvs, event.Context())
	}
	return nil
}
Example #2
0
// receiveResponse retrieves a response from the server.
func (r *resp) receiveResponse() *response {
	// Receive first line.
	line, err := r.reader.ReadBytes('\n')
	if err != nil {
		rerr := errors.Annotate(err, ErrConnectionBroken, errorMessages, "receive after "+r.cmd)
		return &response{receivingError, 0, nil, rerr}
	}
	content := line[1 : len(line)-2]
	// First byte defines kind.
	switch line[0] {
	case '+':
		// Status response.
		return &response{statusResponse, 0, line[:len(line)-2], nil}
	case '-':
		// Error response.
		return &response{errorResponse, 0, line[:len(line)-2], nil}
	case ':':
		// Integer response.
		return &response{integerResponse, 0, content, nil}
	case '$':
		// Bulk response or null bulk response.
		count, err := strconv.Atoi(string(content))
		if err != nil {
			return &response{receivingError, 0, nil, errors.Annotate(err, ErrServerResponse, errorMessages)}
		}
		if count == -1 {
			// Null bulk response.
			return &response{nullBulkResponse, 0, nil, nil}
		}
		// Receive the bulk data.
		toRead := count + 2
		buffer := make([]byte, toRead)
		n, err := io.ReadFull(r.reader, buffer)
		if err != nil {
			return &response{receivingError, 0, nil, err}
		}
		if n < toRead {
			return &response{receivingError, 0, nil, errors.New(ErrServerResponse, errorMessages)}
		}
		return &response{bulkResponse, 0, buffer[0:count], nil}
	case '*':
		// Array reply. Check for timeout.
		length, err := strconv.Atoi(string(content))
		if err != nil {
			return &response{receivingError, 0, nil, errors.Annotate(err, ErrServerResponse, errorMessages)}
		}
		if length == -1 {
			// Timeout.
			return &response{timeoutError, 0, nil, nil}
		}
		return &response{arrayResponse, length, nil, nil}
	}
	return &response{receivingError, 0, nil, errors.New(ErrInvalidResponse, errorMessages, string(line))}
}
Example #3
0
// Read reads the SML source of the configuration from a
// reader, parses it, and returns the configuration instance.
func Read(source io.Reader) (Configuration, error) {
	builder := sml.NewKeyStringValueTreeBuilder()
	err := sml.ReadSML(source, builder)
	if err != nil {
		return nil, errors.Annotate(err, ErrIllegalSourceFormat, errorMessages)
	}
	tree, err := builder.Tree()
	if err != nil {
		return nil, errors.Annotate(err, ErrIllegalSourceFormat, errorMessages)
	}
	if err := tree.At("config").Error(); err != nil {
		return nil, errors.Annotate(err, ErrIllegalSourceFormat, errorMessages)
	}
	return &configuration{tree}, nil
}
Example #4
0
// ReadFile reads the SML source of a configuration file,
// parses it, and returns the configuration instance.
func ReadFile(filename string) (Configuration, error) {
	source, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, errors.Annotate(err, ErrCannotReadFile, errorMessages, filename)
	}
	return ReadString(string(source))
}
Example #5
0
// Post is specified on the PostResourceHandler interface.
func (h *FileUploadHandler) Post(ctx Context) (bool, error) {
	if err := ctx.Request().ParseMultipartForm(defaultMaxMemory); err != nil {
		return false, errors.Annotate(err, ErrUploadingFile, errorMessages)
	}
	for _, headers := range ctx.Request().MultipartForm.File {
		for _, header := range headers {
			logger.Infof("receiving file %q", header.Filename)
			// Open file and process it.
			if infile, err := header.Open(); err != nil {
				return false, errors.Annotate(err, ErrUploadingFile, errorMessages)
			} else if err := h.processor(ctx, header, infile); err != nil {
				return false, errors.Annotate(err, ErrUploadingFile, errorMessages)
			}
		}
	}
	return true, nil
}
Example #6
0
// DoAll implements the Set interface.
func (s *set) DoAll(f func(v interface{}) error) error {
	for v := range s.values {
		if err := f(v); err != nil {
			return errors.Annotate(err, ErrDoAll, errorMessages)
		}
	}
	return nil
}
Example #7
0
// Validate checks if the GUID is valid.
func (g *GUID) Validate() error {
	if g.IsPermaLink {
		if _, err := url.Parse(g.GUID); err != nil {
			return errors.Annotate(err, ErrParsing, errorMessages, "item GUID")
		}
	}
	return nil
}
Example #8
0
// selectDatabase selects the database.
func (r *resp) selectDatabase() error {
	err := r.sendCommand("select", r.database.index)
	if err != nil {
		return errors.Annotate(err, ErrSelectDatabase, errorMessages)
	}
	result, err := r.receiveResultSet()
	if err != nil {
		return errors.Annotate(err, ErrSelectDatabase, errorMessages)
	}
	value, err := result.ValueAt(0)
	if err != nil {
		return errors.Annotate(err, ErrSelectDatabase, errorMessages)
	}
	if !value.IsOK() {
		return errors.New(ErrSelectDatabase, errorMessages)
	}
	return nil
}
Example #9
0
// Validate checks if the source is valid.
func (s *Source) Validate() error {
	if s.Source == "" {
		return errors.New(ErrValidation, errorMessages, "item source must not be empty")
	}
	if _, err := url.Parse(s.URL); err != nil {
		return errors.Annotate(err, ErrParsing, errorMessages, "item source URL")
	}
	return nil
}
Example #10
0
// authenticate authenticates against the server if configured.
func (r *resp) authenticate() error {
	if r.database.password != "" {
		err := r.sendCommand("auth", r.database.password)
		if err != nil {
			return errors.Annotate(err, ErrAuthenticate, errorMessages)
		}
		result, err := r.receiveResultSet()
		if err != nil {
			return errors.Annotate(err, ErrAuthenticate, errorMessages)
		}
		value, err := result.ValueAt(0)
		if err != nil {
			return errors.Annotate(err, ErrAuthenticate, errorMessages)
		}
		if !value.IsOK() {
			return errors.New(ErrAuthenticate, errorMessages)
		}
	}
	return nil
}
Example #11
0
// cleanupAllProps cleans all props.
func (s *scene) cleanupAllProps() error {
	for _, box := range s.props {
		if box.cleanup != nil {
			err := box.cleanup(box.key, box.prop)
			if err != nil {
				return errors.Annotate(err, ErrCleanupFailed, errorMessages, box.key)
			}
		}
	}
	return nil
}
Example #12
0
// GetFloat64 implements the Value interface.
func (v *value) GetFloat64() (float64, error) {
	raw, err := v.Get()
	if err != nil {
		return 0.0, err
	}
	fv, err := strconv.ParseFloat(raw, 64)
	if err != nil {
		return 0.0, errors.Annotate(err, ErrInvalidFormat, errorMessages, raw)
	}
	return fv, nil
}
Example #13
0
// GetInt implements the Value interface.
func (v *value) GetInt() (int, error) {
	raw, err := v.Get()
	if err != nil {
		return 0, err
	}
	iv, err := strconv.ParseInt(raw, 10, 0)
	if err != nil {
		return 0, errors.Annotate(err, ErrInvalidFormat, errorMessages, raw)
	}
	return int(iv), nil
}
Example #14
0
// GetTime implements the Value interface.
func (v *value) GetTime() (time.Time, error) {
	raw, err := v.Get()
	if err != nil {
		return time.Time{}, err
	}
	tv, err := time.Parse(time.RFC3339, raw)
	if err != nil {
		return tv, errors.Annotate(err, ErrInvalidFormat, errorMessages, raw)
	}
	return tv, nil
}
Example #15
0
// GetBool implements the Value interface.
func (v *value) GetBool() (bool, error) {
	raw, err := v.Get()
	if err != nil {
		return false, err
	}
	bv, err := strconv.ParseBool(raw)
	if err != nil {
		return false, errors.Annotate(err, ErrInvalidFormat, errorMessages, raw)
	}
	return bv, nil
}
Example #16
0
// GetDuration implements the Value interface.
func (v *value) GetDuration() (time.Duration, error) {
	raw, err := v.Get()
	if err != nil {
		return time.Duration(0), err
	}
	dv, err := time.ParseDuration(raw)
	if err != nil {
		return dv, errors.Annotate(err, ErrInvalidFormat, errorMessages, raw)
	}
	return dv, nil
}
Example #17
0
// newCell create a new cell around a behavior.
func newCell(env *environment, id string, behavior Behavior) (*cell, error) {
	logger.Infof("cell '%s' starts", id)
	// Init cell runtime.
	c := &cell{
		env:               env,
		id:                id,
		measuringID:       identifier.Identifier("cells", env.id, "cell", id),
		behavior:          behavior,
		emitters:          newConnections(),
		subscribers:       newConnections(),
		emitTimeoutTicker: time.NewTicker(5 * time.Second),
	}
	// Set configuration.
	if bebs, ok := behavior.(BehaviorEventBufferSize); ok {
		size := bebs.EventBufferSize()
		if size < minEventBufferSize {
			size = minEventBufferSize
		}
		c.eventc = make(chan Event, size)
	} else {
		c.eventc = make(chan Event, minEventBufferSize)
	}
	if brf, ok := behavior.(BehaviorRecoveringFrequency); ok {
		number, duration := brf.RecoveringFrequency()
		if duration.Seconds()/float64(number) < 0.1 {
			number = minRecoveringNumber
			duration = minRecoveringDuration
		}
		c.recoveringNumber = number
		c.recoveringDuration = duration
	} else {
		c.recoveringNumber = minRecoveringNumber
		c.recoveringDuration = minRecoveringDuration
	}
	if bet, ok := behavior.(BehaviorEmitTimeout); ok {
		timeout := bet.EmitTimeout()
		switch {
		case timeout < minEmitTimeout:
			timeout = minEmitTimeout
		case timeout > maxEmitTimeout:
			timeout = maxEmitTimeout
		}
		c.emitTimeout = int(timeout.Seconds() / 5)
	} else {
		c.emitTimeout = int(maxEmitTimeout.Seconds() / 5)
	}
	// Init behavior.
	if err := behavior.Init(c); err != nil {
		return nil, errors.Annotate(err, ErrCellInit, errorMessages, id)
	}
	// Start backend.
	c.loop = loop.GoRecoverable(c.backendLoop, c.checkRecovering, id)
	return c, nil
}
Example #18
0
// Validate checks if the enclosure is valid.
func (e *Enclosure) Validate() error {
	if e.Length < 1 {
		return errors.New(ErrValidation, errorMessages, "item enclosure length %d is too small", e.Length)
	}
	if e.Type == "" {
		return errors.New(ErrValidation, errorMessages, "item enclosure type must not be empty")
	}
	if _, err := url.Parse(e.URL); err != nil {
		return errors.Annotate(err, ErrParsing, errorMessages, "item enclosure url")
	}
	return nil
}
Example #19
0
// NewUUIDByHex creates a UUID based on the passed hex string which has to
// have the length of 32 bytes.
func NewUUIDByHex(source string) (UUID, error) {
	uuid := UUID{}
	if len([]byte(source)) != 32 {
		return uuid, errors.New(ErrInvalidHexLength, errorMessages)
	}
	raw, err := hex.DecodeString(source)
	if err != nil {
		return uuid, errors.Annotate(err, ErrInvalidHexValue, errorMessages)
	}
	copy(uuid[:], raw)
	return uuid, nil
}
Example #20
0
// checkRecovering checks if the cell may recover after a panic. It will
// signal an error and let the cell stop working if there have been 12 recoverings
// during the last minute or the behaviors Recover() signals, that it cannot
// handle the error.
func (c *cell) checkRecovering(rs loop.Recoverings) (loop.Recoverings, error) {
	logger.Errorf("recovering cell %q after error: %v", c.id, rs.Last().Reason)
	// Check frequency.
	if rs.Frequency(c.recoveringNumber, c.recoveringDuration) {
		return nil, errors.New(ErrRecoveredTooOften, errorMessages, rs.Last().Reason)
	}
	// Try to recover.
	if err := c.behavior.Recover(rs.Last().Reason); err != nil {
		return nil, errors.Annotate(err, ErrEventRecovering, errorMessages, rs.Last().Reason)
	}
	return rs.Trim(c.recoveringNumber), nil
}
Example #21
0
// newResp establishes a connection to a Redis database
// based on the configuration of the passed database
// configuration.
func newResp(db *Database) (*resp, error) {
	// Dial the database and create the protocol instance.
	conn, err := net.DialTimeout(db.network, db.address, db.timeout)
	if err != nil {
		return nil, errors.Annotate(err, ErrConnectionEstablishing, errorMessages)
	}
	r := &resp{
		database: db,
		conn:     conn,
		reader:   bufio.NewReader(conn),
	}
	return r, nil
}
Example #22
0
// Test the annotation of errors.
func TestAnnotation(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)

	ec := 123
	messages := errors.Messages{ec: "annotated"}
	aerr := testError("wrapped")
	err := errors.Annotate(aerr, ec, messages)

	assert.ErrorMatch(err, `\[ERRORS_TEST:123\] annotated: wrapped`)
	assert.Equal(errors.Annotated(err), aerr)
	assert.True(errors.IsInvalidTypeError(errors.Annotated(aerr)))
	assert.Length(errors.Stack(err), 2)
}
Example #23
0
// FindAll implements the Set interface.
func (s *set) FindAll(f func(v interface{}) (bool, error)) ([]interface{}, error) {
	found := []interface{}{}
	for v := range s.values {
		ok, err := f(v)
		if err != nil {
			return nil, errors.Annotate(err, ErrFindAll, errorMessages)
		}
		if ok {
			found = append(found, v)
		}
	}
	return found, nil
}
Example #24
0
// FindAll implements the StringSet interface.
func (s *stringSet) FindAll(f func(v string) (bool, error)) ([]string, error) {
	found := []string{}
	for v := range s.values {
		ok, err := f(v)
		if err != nil {
			return nil, errors.Annotate(err, ErrFindAll, errorMessages)
		}
		if ok {
			found = append(found, v)
		}
	}
	return found, nil
}
Example #25
0
// sendCommand sends a command and possible arguments to the server.
func (r *resp) sendCommand(cmd string, args ...interface{}) error {
	r.cmd = cmd
	lengthPart := r.buildLengthPart(args)
	cmdPart := r.buildValuePart(cmd)
	argsPart := r.buildArgumentsPart(args)

	packet := join(lengthPart, cmdPart, argsPart)
	_, err := r.conn.Write(packet)
	if err != nil {
		return errors.Annotate(err, ErrConnectionBroken, errorMessages, "send "+r.cmd)
	}
	return nil
}
Example #26
0
// Apply implements the Configuration interface.
func (c *configuration) Apply(kvs map[string]string) (Configuration, error) {
	cc := &configuration{
		values: c.values.Copy(),
	}
	for key, value := range kvs {
		path := append([]string{"config"}, strings.Split(key, "/")...)
		_, err := cc.values.Create(path...).SetValue(value)
		if err != nil {
			return nil, errors.Annotate(err, ErrCannotApply, errorMessages)
		}
	}
	return cc, nil
}
Example #27
0
// Validate checks if the item is valid.
func (i *Item) Validate() error {
	if i.Title == "" {
		if i.Description == "" {
			return errors.New(ErrValidation, errorMessages, "item title or description must not be empty")
		}
	}
	if i.Comments != "" {
		if _, err := url.Parse(i.Comments); err != nil {
			return errors.Annotate(err, ErrParsing, errorMessages, "item comments")
		}
	}
	if i.Enclosure != nil {
		if err := i.Enclosure.Validate(); err != nil {
			return err
		}
	}
	if i.GUID != nil {
		if err := i.GUID.Validate(); err != nil {
			return err
		}
	}
	if i.Link != "" {
		if _, err := url.Parse(i.Link); err != nil {
			return errors.Annotate(err, ErrParsing, errorMessages, "item link")
		}
	}
	if i.PubDate != "" {
		if _, err := ParseTime(i.PubDate); err != nil {
			return errors.Annotate(err, ErrParsing, errorMessages, "item publcation date")
		}
	}
	if i.Source != nil {
		if err := i.Source.Validate(); err != nil {
			return err
		}
	}
	return nil
}
Example #28
0
// Validate checks if the text input is valid.
func (t *TextInput) Validate() error {
	if t.Description == "" {
		return errors.New(ErrValidation, errorMessages, "text input description must not be empty")
	}
	if _, err := url.Parse(t.Link); err != nil {
		return errors.Annotate(err, ErrParsing, errorMessages, "text input link")
	}
	if t.Name == "" {
		return errors.New(ErrValidation, errorMessages, "text input name must not be empty")
	}
	if t.Title == "" {
		return errors.New(ErrValidation, errorMessages, "text input title must not be empty")
	}
	return nil
}
Example #29
0
// TextNode implements the Builder interface.
func (tb *KeyStringValueTreeBuilder) TextNode(text string) error {
	if tb.done {
		return errors.New(ErrBuilder, errorMessages, "building is already done")
	}
	value, err := tb.tree.At(tb.stack.All()...).Value()
	if err != nil {
		return errors.Annotate(err, ErrBuilder, errorMessages)
	}
	if value != "" {
		return errors.New(ErrBuilder, errorMessages, "node has multiple values")
	}
	text = strings.TrimSpace(text)
	if text != "" {
		_, err = tb.tree.At(tb.stack.All()...).SetValue(text)
	}
	return err
}
Example #30
0
// checkRecovering checks if the cell may recover after a panic. It will
// signal an error and let the cell stop working if there have been 12 recoverings
// during the last minute or the behaviors Recover() signals, that it cannot
// handle the error.
func (c *cell) checkRecovering(rs loop.Recoverings) (loop.Recoverings, error) {
	logger.Warningf("recovering cell %q after error: %v", c.id, rs.Last().Reason)
	// Check frequency.
	if rs.Frequency(c.recoveringNumber, c.recoveringDuration) {
		err := errors.New(ErrRecoveredTooOften, errorMessages, rs.Last().Reason)
		logger.Errorf("recovering frequency of cell %q too high", c.id)
		return nil, err
	}
	// Try to recover.
	if err := c.behavior.Recover(rs.Last().Reason); err != nil {
		err := errors.Annotate(err, ErrEventRecovering, errorMessages, rs.Last().Reason)
		logger.Errorf("recovering of cell %q failed: %v", c.id, err)
		return nil, err
	}
	logger.Infof("successfully recovered cell %q", c.id)
	return rs.Trim(c.recoveringNumber), nil
}