diff --git a/models/blueprint.go b/models/blueprint.go index adced10e5fd..413bb9aa27e 100644 --- a/models/blueprint.go +++ b/models/blueprint.go @@ -22,20 +22,21 @@ import ( "github.com/apache/incubator-devlake/models/common" "github.com/apache/incubator-devlake/plugins/core" - "gorm.io/datatypes" ) -const BLUEPRINT_MODE_NORMAL = "NORMAL" -const BLUEPRINT_MODE_ADVANCED = "ADVANCED" +const ( + BLUEPRINT_MODE_NORMAL = "NORMAL" + BLUEPRINT_MODE_ADVANCED = "ADVANCED" +) type Blueprint struct { - Name string `json:"name" validate:"required"` - Mode string `json:"mode" gorm:"varchar(20)" validate:"required,oneof=NORMAL ADVANCED"` - Plan datatypes.JSON `json:"plan"` - Enable bool `json:"enable"` - CronConfig string `json:"cronConfig"` - IsManual bool `json:"isManual"` - Settings datatypes.JSON `json:"settings"` + Name string `json:"name" validate:"required"` + Mode string `json:"mode" gorm:"varchar(20)" validate:"required,oneof=NORMAL ADVANCED"` + Plan json.RawMessage `json:"plan"` + Enable bool `json:"enable"` + CronConfig string `json:"cronConfig"` + IsManual bool `json:"isManual"` + Settings json.RawMessage `json:"settings"` common.Model } @@ -50,10 +51,10 @@ type BlueprintSettings struct { // UnmarshalPlan unmarshals Plan in JSON to strong-typed core.PipelinePlan func (bp *Blueprint) UnmarshalPlan() (core.PipelinePlan, error) { - var plan core.PipelinePlan - err := json.Unmarshal(bp.Plan, &plan) - if err != nil { - return nil, err - } - return plan, nil + var plan core.PipelinePlan + err := json.Unmarshal(bp.Plan, &plan) + if err != nil { + return nil, err + } + return plan, nil } diff --git a/plugins/helper/iso8601time.go b/plugins/helper/iso8601time.go index 6232eb8311d..5b02e9c93cb 100644 --- a/plugins/helper/iso8601time.go +++ b/plugins/helper/iso8601time.go @@ -19,12 +19,9 @@ package helper import ( "fmt" - "reflect" "regexp" "strings" "time" - - "github.com/mitchellh/mapstructure" ) /* @@ -134,46 +131,3 @@ func Iso8601TimeToTime(iso8601Time *Iso8601Time) *time.Time { t := iso8601Time.ToTime() return &t } - -// DecodeMapStruct with time.Time and Iso8601Time support -func DecodeMapStruct(input map[string]interface{}, result interface{}) error { - decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ - Metadata: nil, - DecodeHook: mapstructure.ComposeDecodeHookFunc( - func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { - if t != reflect.TypeOf(Iso8601Time{}) && t != reflect.TypeOf(time.Time{}) { - return data, nil - } - - var tt time.Time - var err error - - switch f.Kind() { - case reflect.String: - tt, err = ConvertStringToTime(data.(string)) - case reflect.Float64: - tt = time.Unix(0, int64(data.(float64))*int64(time.Millisecond)) - case reflect.Int64: - tt = time.Unix(0, data.(int64)*int64(time.Millisecond)) - } - if err != nil { - return data, nil - } - - if t == reflect.TypeOf(Iso8601Time{}) { - return Iso8601Time{time: tt}, nil - } - return tt, nil - }, - ), - Result: result, - }) - if err != nil { - return err - } - - if err := decoder.Decode(input); err != nil { - return err - } - return err -} diff --git a/plugins/helper/mapstructure.go b/plugins/helper/mapstructure.go new file mode 100644 index 00000000000..17e74df4ea3 --- /dev/null +++ b/plugins/helper/mapstructure.go @@ -0,0 +1,76 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package helper + +import ( + "encoding/json" + "reflect" + "time" + + "github.com/mitchellh/mapstructure" +) + +// DecodeMapStruct with time.Time and Iso8601Time support +func DecodeMapStruct(input map[string]interface{}, result interface{}) error { + decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + ZeroFields: true, + DecodeHook: mapstructure.ComposeDecodeHookFunc( + func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if data == nil { + return nil, nil + } + if t == reflect.TypeOf(json.RawMessage{}) { + return json.Marshal(data) + } + + if t != reflect.TypeOf(Iso8601Time{}) && t != reflect.TypeOf(time.Time{}) { + return data, nil + } + + var tt time.Time + var err error + + switch f.Kind() { + case reflect.String: + tt, err = ConvertStringToTime(data.(string)) + case reflect.Float64: + tt = time.Unix(0, int64(data.(float64))*int64(time.Millisecond)) + case reflect.Int64: + tt = time.Unix(0, data.(int64)*int64(time.Millisecond)) + } + if err != nil { + return data, nil + } + + if t == reflect.TypeOf(Iso8601Time{}) { + return Iso8601Time{time: tt}, nil + } + return tt, nil + }, + ), + Result: result, + }) + if err != nil { + return err + } + + if err := decoder.Decode(input); err != nil { + return err + } + return err +} diff --git a/plugins/helper/mapstructure_test.go b/plugins/helper/mapstructure_test.go new file mode 100644 index 00000000000..34ab85e3bd3 --- /dev/null +++ b/plugins/helper/mapstructure_test.go @@ -0,0 +1,58 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package helper + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +type DecodeMapStructJson struct { + Id int + Settings json.RawMessage + Plan json.RawMessage + Existing json.RawMessage +} + +func TestDecodeMapStructJsonRawMessage(t *testing.T) { + input := map[string]interface{}{ + "id": 100, + "settings": map[string]interface{}{ + "version": "1.0.0", + }, + } + + decoded := &DecodeMapStructJson{ + Settings: json.RawMessage(`{"version": "1.0.101"}`), + Existing: json.RawMessage(`{"hello", "world"}`), + } + err := DecodeMapStruct(input, decoded) + fmt.Println(string(decoded.Settings)) + assert.Nil(t, err) + assert.Equal(t, decoded.Id, 100) + assert.Nil(t, decoded.Plan) + assert.NotNil(t, decoded.Settings) + settings := make(map[string]string) + err = json.Unmarshal(decoded.Settings, &settings) + assert.Nil(t, err) + assert.Equal(t, settings["version"], "1.0.0") + assert.Equal(t, decoded.Existing, json.RawMessage(`{"hello", "world"}`)) +} diff --git a/scripts/pm/framework/blueprint-create.sh b/scripts/pm/framework/blueprint-create.sh new file mode 100755 index 00000000000..be6cabcd43a --- /dev/null +++ b/scripts/pm/framework/blueprint-create.sh @@ -0,0 +1,65 @@ +#!/bin/sh +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +. "$(dirname $0)/../vars/active-vars.sh" + +curl -sv $LAKE_ENDPOINT/blueprints -H "Content-Type: application/json" --data @- <