github.com/Tri-stone/burrow@v0.25.0/deploy/def/job.go (about) 1 package def 2 3 import ( 4 "regexp" 5 6 "reflect" 7 8 "fmt" 9 10 validation "github.com/go-ozzo/ozzo-validation" 11 "github.com/hyperledger/burrow/deploy/def/rule" 12 "github.com/hyperledger/burrow/execution/evm/abi" 13 ) 14 15 //TODO: Interface all the jobs, determine if they should remain in definitions or get their own package 16 17 type Job struct { 18 // Name of the job 19 Name string `mapstructure:"name,omitempty" json:"name,omitempty" yaml:"name,omitempty" toml:"name"` 20 // Not marshalled 21 Intermediate interface{} `json:"-" yaml:"-" toml:"-"` 22 // Not marshalled 23 Result interface{} `json:"-" yaml:"-" toml:"-"` 24 // For multiple values 25 Variables []*abi.Variable `json:"-" yaml:"-" toml:"-"` 26 // Create proposal or vote for one 27 Proposal *Proposal `mapstructure:"proposal,omitempty" json:"proposal,omitempty" yaml:"proposal,omitempty" toml:"proposal"` 28 // Sets/Resets the primary account to use 29 Account *Account `mapstructure:"account,omitempty" json:"account,omitempty" yaml:"account,omitempty" toml:"account"` 30 // Set an arbitrary value 31 Set *Set `mapstructure:"set,omitempty" json:"set,omitempty" yaml:"set,omitempty" toml:"set"` 32 // Run a sequence of other deploy.yamls 33 Meta *Meta `mapstructure:"meta,omitempty" json:"meta,omitempty" yaml:"meta,omitempty" toml:"meta"` 34 // Issue a governance transaction 35 UpdateAccount *UpdateAccount `mapstructure:"update-account,omitempty" json:"update-account,omitempty" yaml:"update-account,omitempty" toml:"update-account"` 36 // Contract compile and send to the chain functions 37 Deploy *Deploy `mapstructure:"deploy,omitempty" json:"deploy,omitempty" yaml:"deploy,omitempty" toml:"deploy"` 38 // Contract compile/build 39 Build *Build `mapstructure:"build,omitempty" json:"build,omitempty" yaml:"build,omitempty" toml:"build"` 40 // Send tokens from one account to another 41 Send *Send `mapstructure:"send,omitempty" json:"send,omitempty" yaml:"send,omitempty" toml:"send"` 42 // Utilize monax:db's native name registry to register a name 43 RegisterName *RegisterName `mapstructure:"register,omitempty" json:"register,omitempty" yaml:"register,omitempty" toml:"register"` 44 // Sends a transaction which will update the permissions of an account. Must be sent from an account which 45 // has root permissions on the blockchain (as set by either the genesis.json or in a subsequence transaction) 46 Permission *Permission `mapstructure:"permission,omitempty" json:"permission,omitempty" yaml:"permission,omitempty" toml:"permission"` 47 // Sends a transaction to a contract. Will utilize monax-abi under the hood to perform all of the heavy lifting 48 Call *Call `mapstructure:"call,omitempty" json:"call,omitempty" yaml:"call,omitempty" toml:"call"` 49 // Wrapper for mintdump dump. WIP 50 DumpState *DumpState `mapstructure:"dump-state,omitempty" json:"dump-state,omitempty" yaml:"dump-state,omitempty" toml:"dump-state"` 51 // Wrapper for mintdum restore. WIP 52 RestoreState *RestoreState `mapstructure:"restore-state,omitempty" json:"restore-state,omitempty" yaml:"restore-state,omitempty" toml:"restore-state"` 53 // Sends a "simulated call,omitempty" to a contract. Predominantly used for accessor functions ("Getters,omitempty" within contracts) 54 QueryContract *QueryContract `mapstructure:"query-contract,omitempty" json:"query-contract,omitempty" yaml:"query-contract,omitempty" toml:"query-contract"` 55 // Queries information from an account. 56 QueryAccount *QueryAccount `mapstructure:"query-account,omitempty" json:"query-account,omitempty" yaml:"query-account,omitempty" toml:"query-account"` 57 // Queries information about a name registered with monax:db's native name registry 58 QueryName *QueryName `mapstructure:"query-name,omitempty" json:"query-name,omitempty" yaml:"query-name,omitempty" toml:"query-name"` 59 // Queries information about the validator set 60 QueryVals *QueryVals `mapstructure:"query-vals,omitempty" json:"query-vals,omitempty" yaml:"query-vals,omitempty" toml:"query-vals"` 61 // Makes and assertion (useful for testing purposes) 62 Assert *Assert `mapstructure:"assert,omitempty" json:"assert,omitempty" yaml:"assert,omitempty" toml:"assert"` 63 } 64 65 type Payload interface { 66 validation.Validatable 67 } 68 69 func (job *Job) Validate() error { 70 payloadField, err := job.PayloadField() 71 if err != nil { 72 return err 73 } 74 return validation.ValidateStruct(job, 75 validation.Field(&job.Name, validation.Required, validation.Match(regexp.MustCompile("[[:word:]]+")). 76 Error("must contain word characters; alphanumeric plus underscores/hyphens")), 77 validation.Field(&job.Result, rule.New(rule.IsOmitted, "internally reserved and should be removed")), 78 validation.Field(&job.Variables, rule.New(rule.IsOmitted, "internally reserved and should be removed")), 79 validation.Field(payloadField.Addr().Interface()), 80 ) 81 } 82 83 var payloadType = reflect.TypeOf((*Payload)(nil)).Elem() 84 85 func (job *Job) Payload() (Payload, error) { 86 field, err := job.PayloadField() 87 if err != nil { 88 return nil, err 89 } 90 return field.Interface().(Payload), nil 91 } 92 93 // Ensures only one Job payload is set and returns a pointer to that field or an error if none or multiple 94 // job payload fields are set 95 func (job *Job) PayloadField() (reflect.Value, error) { 96 rv := reflect.ValueOf(job).Elem() 97 rt := rv.Type() 98 99 payloadIndex := -1 100 for i := 0; i < rt.NumField(); i++ { 101 if rt.Field(i).Type.Implements(payloadType) && !rv.Field(i).IsNil() { 102 if payloadIndex >= 0 { 103 return reflect.Value{}, fmt.Errorf("only one Job payload field should be set, but both '%v' and '%v' are set", 104 rt.Field(payloadIndex).Name, rt.Field(i).Name) 105 } 106 payloadIndex = i 107 } 108 } 109 if payloadIndex == -1 { 110 return reflect.Value{}, fmt.Errorf("Job has no payload, please set at least one job value") 111 } 112 113 return rv.Field(payloadIndex), nil 114 }