Skip to content

Commit

Permalink
Handle type conversion errors (#258)
Browse files Browse the repository at this point in the history
* Handle type conversion error in state providers

* Fix potential conversion error
  • Loading branch information
RemindD authored May 16, 2024
1 parent 2c2ff89 commit 8a839b9
Show file tree
Hide file tree
Showing 26 changed files with 177 additions and 76 deletions.
5 changes: 3 additions & 2 deletions api/pkg/apis/v1alpha1/managers/reference/reference-manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"time"

"github.com/eclipse-symphony/symphony/api/pkg/apis/v1alpha1/model"
"github.com/eclipse-symphony/symphony/api/pkg/apis/v1alpha1/utils"
"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2"
"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2/contexts"
"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2/managers"
Expand Down Expand Up @@ -320,14 +321,14 @@ func getParameterMap(data []byte, skill string, alias string) (map[string]string
if err == nil {
coll := params.(map[string]interface{})
for k, p := range coll {
dict[k] = p.(string)
dict[k] = utils.FormatAsString(p)
}
}
params, err = jsonpath.JsonPathLookup(obj, "$.spec.parameters")
if err == nil {
coll := params.(map[string]interface{})
for k, p := range coll {
dict[k] = p.(string)
dict[k] = utils.FormatAsString(p)
}
}
if skill != "" && alias != "" {
Expand Down
28 changes: 16 additions & 12 deletions api/pkg/apis/v1alpha1/managers/stage/stage-manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (t *TaskResult) GetError() error {

if t.Outputs["__status"] != v1alpha2.OK {
if v, ok := t.Outputs["__error"]; ok {
return v1alpha2.NewCOAError(nil, v.(string), t.Outputs["__status"].(v1alpha2.State))
return v1alpha2.NewCOAError(nil, utils.FormatAsString(v), t.Outputs["__status"].(v1alpha2.State))
} else {
return fmt.Errorf("stage returned unsuccessful status without an error")
}
Expand Down Expand Up @@ -207,9 +207,10 @@ func (s *StageManager) ResumeStage(status model.ActivationStatus, cam model.Camp
if err != nil {
return nil, err
}

sVal := ""
if val != nil {
sVal = val.(string)
sVal = utils.FormatAsString(val)
}
if sVal != "" {
if _, ok := cam.Stages[sVal]; ok {
Expand All @@ -218,6 +219,7 @@ func (s *StageManager) ResumeStage(status model.ActivationStatus, cam model.Camp
return nil, fmt.Errorf("stage %s is not found", sVal)
}
}

}
if nextStage != "" {
activationData := &v1alpha2.ActivationData{
Expand Down Expand Up @@ -431,17 +433,17 @@ func (s *StageManager) HandleTriggerEvent(ctx context.Context, campaign model.Ca
log.Errorf(" M (Stage): failed to evaluate context: %v", err)
return status, activationData
}
if _, ok := val.([]string); ok {
sites = val.([]string)
} else if _, ok := val.([]interface{}); ok {
for _, v := range val.([]interface{}) {
sites = append(sites, v.(string))
if valStringList, ok := val.([]string); ok {
sites = valStringList
} else if valList, ok := val.([]interface{}); ok {
for _, v := range valList {
sites = append(sites, utils.FormatAsString(v))
}
} else if _, ok := val.(string); ok {
sites = append(sites, val.(string))
} else if valString, ok := val.(string); ok {
sites = append(sites, valString)
} else {
status.Status = v1alpha2.InternalError
status.StatusMessage = v1alpha2.InternalError.String()
status.Status = v1alpha2.BadConfig
status.StatusMessage = v1alpha2.BadConfig.String()
status.ErrorMessage = fmt.Sprintf("invalid context %s", currentStage.Contexts)
status.IsActive = false
log.Errorf(" M (Stage): invalid context: %v", currentStage.Contexts)
Expand Down Expand Up @@ -686,10 +688,12 @@ func (s *StageManager) HandleTriggerEvent(ctx context.Context, campaign model.Ca
log.Errorf(" M (Stage): failed to evaluate stage selector: %v", err)
return status, activationData
}

sVal := ""
if val != nil {
sVal = val.(string)
sVal = utils.FormatAsString(val)
}

if sVal != "" {
if nextStage, ok := campaign.Stages[sVal]; ok {
if !delayedExit || nextStage.HandleErrors {
Expand Down
2 changes: 1 addition & 1 deletion api/pkg/apis/v1alpha1/managers/staging/staging-manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (s *StagingManager) Poll() []error {
log.Errorf(" M (Staging): Failed to poll: %s", err.Error())
return []error{err}
}
siteId := site.(string)
siteId := utils.FormatAsString(site)
var catalogs []model.CatalogState
catalogs, err = utils.GetCatalogs(
ctx,
Expand Down
9 changes: 8 additions & 1 deletion api/pkg/apis/v1alpha1/managers/target/target-manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ package target
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"sync"

"github.com/eclipse-symphony/symphony/api/pkg/apis/v1alpha1/model"
"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2"
"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2/contexts"
"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2/managers"
"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2/providers"
Expand Down Expand Up @@ -132,7 +134,12 @@ func (s *TargetManager) Poll() []error {
if i, ok := device.Object.Spec.Properties["ip"]; ok {
ip = i
}
name := device.Object.Metadata["name"].(string)
name, ok := device.Object.Metadata["name"].(string)
if !ok || name == "" {
err := v1alpha2.NewCOAError(nil, fmt.Sprintf("device name is not valid: %v", device.Object.Metadata["name"]), v1alpha2.InternalError)
errors = append(errors, err)
continue
}
namespace, ok := device.Object.Metadata["namespace"].(string)
if !ok {
namespace = "default"
Expand Down
2 changes: 1 addition & 1 deletion api/pkg/apis/v1alpha1/managers/trails/trails-manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (s *TrailsManager) Init(context *contexts.VendorContext, config managers.Ma
s.LedgerProviders = make([]ledger.ILedgerProvider, 0)
for _, provider := range providers {
if p, ok := provider.(ledger.ILedgerProvider); ok {
s.LedgerProviders = append(s.LedgerProviders, p.(ledger.ILedgerProvider))
s.LedgerProviders = append(s.LedgerProviders, p)
}
}
return nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,11 @@ func (m *CatalogConfigProvider) unwindOverrides(override string, field string, n
return "", err
}
if v, ok := catalog.Spec.Properties[field]; ok {
return v.(string), nil
if vstring, ok := v.(string); ok {
return vstring, nil
} else {
return "", v1alpha2.NewCOAError(nil, fmt.Sprintf("field '%s' doesn't has a valid value in configuration'%s'", field, override), v1alpha2.BadConfig)
}
}
if catalog.Spec.ParentName != "" {
return m.unwindOverrides(catalog.Spec.ParentName, field, namespace)
Expand Down
7 changes: 6 additions & 1 deletion api/pkg/apis/v1alpha1/providers/stage/counter/counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"strings"
"sync"

"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2"
"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2/contexts"
"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2/observability"
observ_utils "github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2/observability/utils"
Expand Down Expand Up @@ -75,7 +76,11 @@ func (i *CounterStageProvider) Process(ctx context.Context, mgrContext contexts.
outputs := make(map[string]interface{})
selfState := make(map[string]interface{})
if state, ok := inputs["__state"]; ok {
selfState = state.(map[string]interface{})
selfState, ok = state.(map[string]interface{})
if !ok {
err = v1alpha2.NewCOAError(nil, "input state is not a valid map[string]interface{}", v1alpha2.BadRequest)
return outputs, false, err
}
}

for k, v := range inputs {
Expand Down
10 changes: 7 additions & 3 deletions api/pkg/apis/v1alpha1/providers/stage/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,15 @@ func (i *ListStageProvider) Process(ctx context.Context, mgrContext contexts.Man

outputs := make(map[string]interface{})

objectType := inputs["objectType"].(string)
objectType, ok := inputs["objectType"].(string)
if !ok {
err = v1alpha2.NewCOAError(nil, fmt.Sprintf("objectType is not a valid string: %v", inputs["objectType"]), v1alpha2.BadRequest)
return nil, false, err
}
namesOnly := false
if v, ok := inputs["namesOnly"]; ok {
if v.(bool) {
namesOnly = v.(bool)
if vbool, ok := v.(bool); ok {
namesOnly = vbool
}
}
objectNamespace := stage.GetNamespace(inputs)
Expand Down
15 changes: 12 additions & 3 deletions api/pkg/apis/v1alpha1/providers/stage/materialize/materialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,22 @@ func (i *MaterializeStageProvider) Process(ctx context.Context, mgrContext conte
mLog.Info(" P (Materialize Processor): processing inputs")
outputs := make(map[string]interface{})

objects := inputs["names"].([]interface{})
objects, ok := inputs["names"].([]interface{})
if !ok {
err = v1alpha2.NewCOAError(nil, "input names is not a valid list", v1alpha2.BadRequest)
return outputs, false, err
}
prefixedNames := make([]string, len(objects))
for i, object := range objects {
objString, ok := object.(string)
if !ok {
err = v1alpha2.NewCOAError(nil, fmt.Sprintf("input name is not a valid string: %v", objects), v1alpha2.BadRequest)
return outputs, false, err
}
if s, ok := inputs["__origin"]; ok {
prefixedNames[i] = fmt.Sprintf("%s-%s", s, object.(string))
prefixedNames[i] = fmt.Sprintf("%s-%s", s, objString)
} else {
prefixedNames[i] = object.(string)
prefixedNames[i] = objString
}
}
namespace := stage.GetNamespace(inputs)
Expand Down
10 changes: 9 additions & 1 deletion api/pkg/apis/v1alpha1/providers/stage/remote/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package remote
import (
"context"
"encoding/json"
"fmt"
"sync"

"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2"
Expand Down Expand Up @@ -86,9 +87,16 @@ func (i *RemoteStageProvider) Process(ctx context.Context, mgrContext contexts.M
return nil, false, err
}

siteString, ok := v.(string)
if !ok {
err = v1alpha2.NewCOAError(nil, fmt.Sprintf("site name is not a valid string: %v", v), v1alpha2.BadRequest)
log.Errorf(" P (Remote Processor): %v", err)
return nil, false, err
}

err = mgrContext.Publish("remote", v1alpha2.Event{
Metadata: map[string]string{
"site": v.(string),
"site": siteString,
"objectType": "task",
"origin": mgrContext.SiteInfo.SiteId,
},
Expand Down
12 changes: 10 additions & 2 deletions api/pkg/apis/v1alpha1/providers/stage/wait/wait.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,16 @@ func (i *WaitStageProvider) Process(ctx context.Context, mgrContext contexts.Man
log.Info(" P (Wait Processor): processing inputs")
outputs := make(map[string]interface{})

objectType := inputs["objectType"].(string)
objects := inputs["names"].([]interface{})
objectType, ok := inputs["objectType"].(string)
if !ok {
err = v1alpha2.NewCOAError(nil, fmt.Sprintf("objectType is not a valid string: %v", inputs["objectType"]), v1alpha2.BadRequest)
return nil, false, err
}
objects, ok := inputs["names"].([]interface{})
if !ok {
err = v1alpha2.NewCOAError(nil, "input names is not a valid list", v1alpha2.BadRequest)
return outputs, false, err
}
prefixedNames := make([]string, len(objects))
if inputs["__origin"] == nil || inputs["__origin"] == "" {
for i, object := range objects {
Expand Down
31 changes: 18 additions & 13 deletions api/pkg/apis/v1alpha1/providers/states/k8s/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,20 +262,25 @@ func (s *K8sStateProvider) Upsert(ctx context.Context, entry states.UpsertReques
}
}
if v, ok := dict["status"]; ok {
status := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": group + "/" + version,
"kind": "Status",
"metadata": map[string]interface{}{
"name": entry.Value.ID,
if vMap, ok := v.(map[string]interface{}); ok {
status := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": group + "/" + version,
"kind": "Status",
"metadata": map[string]interface{}{
"name": entry.Value.ID,
},
"status": vMap,
},
"status": v.(map[string]interface{}),
},
}
status.SetResourceVersion(item.GetResourceVersion())
_, err = s.DynamicClient.Resource(resourceId).Namespace(namespace).UpdateStatus(ctx, status, v1.UpdateOptions{})
if err != nil {
sLog.Errorf(" P (K8s State): failed to update object status: %v", err)
}
status.SetResourceVersion(item.GetResourceVersion())
_, err = s.DynamicClient.Resource(resourceId).Namespace(namespace).UpdateStatus(ctx, status, v1.UpdateOptions{})
if err != nil {
sLog.Errorf(" P (K8s State): failed to update object status: %v", err)
return "", err
}
} else {
err = v1alpha2.NewCOAError(nil, "status field is not a valid map[string]interface{}", v1alpha2.BadRequest)
return "", err
}
}
Expand Down
5 changes: 3 additions & 2 deletions api/pkg/apis/v1alpha1/providers/target/adb/adb.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"strings"

"github.com/eclipse-symphony/symphony/api/pkg/apis/v1alpha1/model"
"github.com/eclipse-symphony/symphony/api/pkg/apis/v1alpha1/utils"
"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2"
"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2/contexts"
"github.com/eclipse-symphony/symphony/coa/pkg/apis/v1alpha2/observability"
Expand Down Expand Up @@ -159,7 +160,7 @@ func (i *AdbProvider) Apply(ctx context.Context, deployment model.DeploymentSpec
if !isDryRun {
params := make([]string, 0)
params = append(params, "install")
params = append(params, p.(string))
params = append(params, utils.FormatAsString(p))
cmd := exec.Command("adb", params...)
err = cmd.Run()
if err != nil {
Expand All @@ -182,7 +183,7 @@ func (i *AdbProvider) Apply(ctx context.Context, deployment model.DeploymentSpec
if p, ok := component.Properties[model.AppPackage]; ok && p != "" {
params := make([]string, 0)
params = append(params, "uninstall")
params = append(params, p.(string))
params = append(params, utils.FormatAsString(p))

cmd := exec.Command("adb", params...)
err = cmd.Run()
Expand Down
24 changes: 15 additions & 9 deletions api/pkg/apis/v1alpha1/providers/target/azure/iotedge/iotedge.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,13 @@ func toComponent(hubTwin ModuleTwin, twin ModuleTwin, name string, module Module
}

if v, ok := hubTwin.Properties.Desired["routes"]; ok {
routes := v.(map[string]interface{})
routes, ok := v.(map[string]interface{})
if !ok {
err := v1alpha2.NewCOAError(nil, "hubTwin.Properties.Desired['routes'] is not a valid map", v1alpha2.BadRequest)
return component, err
}
for k, iv := range routes {
def := iv.(string)
def := utils.FormatAsString(iv)
if strings.Contains(def, "modules/"+twin.ModuleId+"/") { //TODO: this check is not necessarily safe
reducedRoute, _ := reduceKey(k, name)
reducedDef, _ := replaceKey(def, name)
Expand All @@ -390,7 +394,7 @@ func toComponent(hubTwin ModuleTwin, twin ModuleTwin, name string, module Module

component.Properties["container.restartPolicy"] = module.RestartPolicy
if module.Version != nil {
component.Properties["container.version"] = module.Version.(string)
component.Properties["container.version"] = utils.FormatAsString(module.Version)
}
component.Properties["container.type"] = module.Type
if v, ok := module.Settings["createOptions"]; ok {
Expand Down Expand Up @@ -706,9 +710,10 @@ func updateDeployment(deployment *IoTEdgeDeployment, name string, modules map[st
rd := deployment.ModulesContent["$edgeHub"].DesiredProperties["routes"].(map[string]string)

if v, ok := hubRef.Properties.Desired["routes"]; ok {
routes := v.(map[string]interface{})
for ik, iv := range routes {
rd[ik] = iv.(string)
if routes, ok := v.(map[string]interface{}); ok {
for ik, iv := range routes {
rd[ik] = utils.FormatAsString(iv)
}
}
}

Expand Down Expand Up @@ -756,9 +761,10 @@ func reduceDeployment(deployment *IoTEdgeDeployment, name string, modules map[st
rd := deployment.ModulesContent["$edgeHub"].DesiredProperties["routes"].(map[string]string)

if v, ok := hubRef.Properties.Desired["routes"]; ok {
routes := v.(map[string]interface{})
for ik, iv := range routes {
rd[ik] = iv.(string)
if routes, ok := v.(map[string]interface{}); ok {
for ik, iv := range routes {
rd[ik] = utils.FormatAsString(iv)
}
}
}

Expand Down
Loading

0 comments on commit 8a839b9

Please sign in to comment.