// ControlWorkSpec makes changes to a work spec that are not directly // reflected in the work spec definition. This allows work specs to // be paused or to stop generating new continuous jobs. // ControlWorkSpecOptions has a complete listing of what can be done. func (jobs *JobServer) ControlWorkSpec(workSpecName string, options map[string]interface{}) (bool, string, error) { var ( cwsOptions ControlWorkSpecOptions decoder *mapstructure.Decoder err error metadata mapstructure.Metadata workSpec coordinate.WorkSpec wsMeta coordinate.WorkSpecMeta ) workSpec, err = jobs.Namespace.WorkSpec(workSpecName) if err == nil { // We care a lot about "false" vs. not present for // these things. Manually create the decoder. config := mapstructure.DecoderConfig{ Result: &cwsOptions, Metadata: &metadata, } decoder, err = mapstructure.NewDecoder(&config) } if err == nil { err = decoder.Decode(options) } // Get the existing metadata, then change it based on what // we got provided if err == nil { wsMeta, err = workSpec.Meta(false) } if err == nil { for _, key := range metadata.Keys { switch key { case "Continuous": wsMeta.Continuous = cwsOptions.Continuous case "Status": wsMeta.Paused = cwsOptions.Status == Paused case "Weight": wsMeta.Weight = cwsOptions.Weight case "Interval": wsMeta.Interval = time.Duration(cwsOptions.Interval) * time.Second case "MaxRunning": wsMeta.MaxRunning = cwsOptions.MaxRunning } } } if err == nil { err = workSpec.SetMeta(wsMeta) } return err == nil, "", err }
func (spec *workSpec) SetMeta(meta coordinate.WorkSpecMeta) error { return spec.do(func() error { // Preserve immutable fields (taking advantage of meta pass-by-value) meta.CanBeContinuous = spec.meta.CanBeContinuous meta.NextWorkSpecName = spec.meta.NextWorkSpecName meta.Runtime = spec.meta.Runtime // If this cannot be continuous, force-clear that flag if !meta.CanBeContinuous { meta.Continuous = false } spec.meta = meta return nil }) }
// TestMetaContinuous specifically checks that you cannot enable the // "continuous" flag on non-continuous work specs. func TestMetaContinuous(t *testing.T) { var ( err error namespace coordinate.Namespace spec coordinate.WorkSpec meta coordinate.WorkSpecMeta ) namespace, err = Coordinate.Namespace("TestMetaContinuous") if !assert.NoError(t, err) { return } defer namespace.Destroy() spec, err = namespace.SetWorkSpec(map[string]interface{}{ "name": "spec", "min_gb": 1, }) if !assert.NoError(t, err) { return } meta, err = spec.Meta(false) if assert.NoError(t, err) { assert.False(t, meta.Continuous) assert.False(t, meta.CanBeContinuous) } meta.Continuous = true err = spec.SetMeta(meta) assert.NoError(t, err) meta, err = spec.Meta(false) if assert.NoError(t, err) { // Cannot set the "continuous" flag assert.False(t, meta.Continuous) assert.False(t, meta.CanBeContinuous) } }