github.com/sentienttechnologies/studio-go-runner@v0.0.0-20201118202441-6d21f2ced8ee/internal/runner/envelope.go (about)

     1  // Copyright 2020 (c) Cognizant Digital Business, Evolutionary AI. All rights reserved. Issued under the Apache 2.0 License.
     2  
     3  package runner
     4  
     5  import (
     6  	"encoding/json"
     7  
     8  	"github.com/go-stack/stack"
     9  	"github.com/jjeffery/kv"
    10  )
    11  
    12  // This file contains the implementation of an envelop message that will be used to
    13  // add the chrome for holding StudioML requests and their respective signature attachment
    14  // and encryption wrappers.
    15  
    16  type OpenExperiment struct {
    17  	Status    string `json:"status"`
    18  	PythonVer string `json:"pthonver"`
    19  }
    20  
    21  // Message contains any clear text fields and either an an encrypted payload or clear text
    22  // payloads as a Request.
    23  type Message struct {
    24  	Experiment         OpenExperiment `json:"experiment"`
    25  	TimeAdded          float64        `json:"time_added"`
    26  	ExperimentLifetime string         `json:"experiment_lifetime"`
    27  	Resource           Resource       `json:"resources_needed"`
    28  	Payload            string         `json:"payload"`
    29  	Fingerprint        string         `json:"fingerprint"`
    30  	Signature          string         `json:"signature"`
    31  }
    32  
    33  // Request marshals the requests made by studioML under which all of the other
    34  // meta data can be found
    35  type Envelope struct {
    36  	Message Message `json:"message"`
    37  }
    38  
    39  // IsEnvelop is used to test if a JSON payload is indeed present
    40  func IsEnvelope(msg []byte) (isEnvelope bool, err kv.Error) {
    41  	fields := map[string]interface{}{}
    42  	if errGo := json.Unmarshal(msg, &fields); errGo != nil {
    43  		return false, kv.Wrap(errGo).With("stack", stack.Trace().TrimRuntime())
    44  	}
    45  	// Examine the fields and see that we have a message
    46  	if _, isPresent := fields["message"]; !isPresent {
    47  		return false, kv.NewError("'message' missing").With("stack", stack.Trace().TrimRuntime())
    48  	}
    49  	message, isOK := fields["message"].(map[string]interface{})
    50  	if !isOK {
    51  		return false, kv.NewError("'message.payload' invalid").With("stack", stack.Trace().TrimRuntime())
    52  	}
    53  	if _, isPresent := message["payload"]; !isPresent {
    54  		return false, kv.NewError("'message.payload' missing").With("stack", stack.Trace().TrimRuntime())
    55  
    56  	}
    57  	return true, nil
    58  }
    59  
    60  // UnmarshalRequest takes an encoded StudioML envelope and extracts it
    61  // into go data structures used by the go runner.
    62  //
    63  func UnmarshalEnvelope(data []byte) (e *Envelope, err kv.Error) {
    64  	e = &Envelope{}
    65  	if errGo := json.Unmarshal(data, e); errGo != nil {
    66  		return nil, kv.Wrap(errGo).With("stack", stack.Trace().TrimRuntime())
    67  	}
    68  	return e, nil
    69  }
    70  
    71  // Marshal takes the go data structure used to define a StudioML experiment envelope
    72  // and serializes it as json to the byte array
    73  //
    74  func (e *Envelope) Marshal() ([]byte, error) {
    75  	return json.Marshal(e)
    76  }