diff --git a/cmd/resource/builder.go b/cmd/resource/builder.go new file mode 100644 index 00000000..85e81628 --- /dev/null +++ b/cmd/resource/builder.go @@ -0,0 +1,83 @@ +package resource + +import ( + "io" + "io/fs" + + "github.com/siyul-park/uniflow/pkg/scheme" +) + +type ( + Builder struct { + scheme *scheme.Scheme + namespace string + fsys fs.FS + filename string + } +) + +func NewBuilder() *Builder { + return &Builder{} +} + +func (b *Builder) Scheme(scheme *scheme.Scheme) *Builder { + b.scheme = scheme + return b +} + +func (b *Builder) Namespace(namespace string) *Builder { + b.namespace = namespace + return b +} + +func (b *Builder) FS(fsys fs.FS) *Builder { + b.fsys = fsys + return b +} + +func (b *Builder) Filename(filename string) *Builder { + b.filename = filename + return b +} + +func (b *Builder) Build() ([]scheme.Spec, error) { + if b.fsys == nil || b.filename == "" { + return nil, nil + } + file, err := b.fsys.Open(b.filename) + if err != nil { + return nil, err + } + defer file.Close() + + data, err := io.ReadAll(file) + if err != nil { + return nil, err + } + + var raws []map[string]any + if err := UnmarshalYAMLOrJSON(data, &raws); err != nil { + var e map[string]any + if err := UnmarshalYAMLOrJSON(data, &e); err != nil { + return nil, err + } else { + raws = []map[string]any{e} + } + } + + codec := NewSpecCodec(SpecCodecOptions{ + Scheme: b.scheme, + Namespace: b.namespace, + }) + + var specs []scheme.Spec + for _, raw := range raws { + if spec, err := codec.Decode(raw); err != nil { + return nil, err + } else { + specs = append(specs, spec) + } + } + + return specs, nil +} diff --git a/cmd/resource/builder_test.go b/cmd/resource/builder_test.go new file mode 100644 index 00000000..55de0d80 --- /dev/null +++ b/cmd/resource/builder_test.go @@ -0,0 +1,50 @@ +package resource + +import ( + "encoding/json" + "testing" + "testing/fstest" + + "github.com/go-faker/faker/v4" + "github.com/oklog/ulid/v2" + "github.com/siyul-park/uniflow/pkg/node" + "github.com/siyul-park/uniflow/pkg/scheme" + "github.com/stretchr/testify/assert" +) + +func TestBuilder_Build(t *testing.T) { + s := scheme.New() + fsys := make(fstest.MapFS) + + filename := "spec.json" + kind := faker.Word() + + spec := &scheme.SpecMeta{ + ID: ulid.Make(), + Kind: kind, + Namespace: scheme.NamespaceDefault, + } + + codec := scheme.CodecFunc(func(spec scheme.Spec) (node.Node, error) { + return node.NewOneToOneNode(node.OneToOneNodeConfig{ID: spec.GetID()}), nil + }) + + s.AddKnownType(kind, &scheme.SpecMeta{}) + s.AddCodec(kind, codec) + + data, _ := json.Marshal(spec) + + fsys[filename] = &fstest.MapFile{ + Data: data, + } + + builder := NewBuilder(). + Scheme(s). + Namespace(scheme.NamespaceDefault). + FS(fsys). + Filename(filename) + + specs, err := builder.Build() + assert.NoError(t, err) + assert.Len(t, specs, 1) +} diff --git a/cmd/uniflow/apply/cmd.go b/cmd/uniflow/apply/cmd.go index 8a18041f..fbcd2c90 100644 --- a/cmd/uniflow/apply/cmd.go +++ b/cmd/uniflow/apply/cmd.go @@ -1,7 +1,6 @@ package apply import ( - "io" "io/fs" "github.com/oklog/ulid/v2" @@ -50,41 +49,17 @@ func NewCmd(config Config) *cobra.Command { return err } - file, err := fsys.Open(fl) - if err != nil { - return err - } - defer func() { _ = file.Close() }() + b := resource.NewBuilder(). + Scheme(sc). + Namespace(ns). + FS(fsys). + Filename(fl) - data, err := io.ReadAll(file) + specs, err := b.Build() if err != nil { return err } - var raws []map[string]any - if err := resource.UnmarshalYAMLOrJSON(data, &raws); err != nil { - var e map[string]any - if err := resource.UnmarshalYAMLOrJSON(data, &e); err != nil { - return err - } else { - raws = []map[string]any{e} - } - } - - codec := resource.NewSpecCodec(resource.SpecCodecOptions{ - Scheme: sc, - Namespace: ns, - }) - - var specs []scheme.Spec - for _, raw := range raws { - if spec, err := codec.Decode(raw); err != nil { - return err - } else { - specs = append(specs, spec) - } - } - for _, spec := range specs { if spec.GetID() == (ulid.ULID{}) { if spec.GetName() != "" { diff --git a/cmd/uniflow/start/cmd.go b/cmd/uniflow/start/cmd.go index 948d1118..ed58fd2f 100644 --- a/cmd/uniflow/start/cmd.go +++ b/cmd/uniflow/start/cmd.go @@ -1,7 +1,6 @@ package start import ( - "io" "io/fs" "os" "os/signal" @@ -67,41 +66,17 @@ func NewCmd(config Config) *cobra.Command { }); err != nil { return err } else if len(specs) == 0 { - file, err := fsys.Open(boot) - if err != nil { - return err - } - defer func() { _ = file.Close() }() + b := resource.NewBuilder(). + Scheme(sc). + Namespace(ns). + FS(fsys). + Filename(boot) - data, err := io.ReadAll(file) + specs, err := b.Build() if err != nil { return err } - var raws []map[string]any - if err := resource.UnmarshalYAMLOrJSON(data, &raws); err != nil { - var e map[string]any - if err := resource.UnmarshalYAMLOrJSON(data, &e); err != nil { - return err - } else { - raws = []map[string]any{e} - } - } - - codec := resource.NewSpecCodec(resource.SpecCodecOptions{ - Scheme: sc, - Namespace: ns, - }) - - var specs []scheme.Spec - for _, raw := range raws { - if spec, err := codec.Decode(raw); err != nil { - return err - } else { - specs = append(specs, spec) - } - } - if _, err := st.InsertMany(ctx, specs); err != nil { return err } diff --git a/pkg/scheme/unstructured.go b/pkg/scheme/unstructured.go index 4d85743d..efc8eb3f 100644 --- a/pkg/scheme/unstructured.go +++ b/pkg/scheme/unstructured.go @@ -8,7 +8,6 @@ import ( ) type ( - // Unstructured is an Spec that is not marshaled for structuring. Unstructured struct { doc *primitive.Map @@ -73,7 +72,6 @@ func (u *Unstructured) GetNamespace() string { var val string _ = u.Get(KeyNamespace, &val) return val - } // SetNamespace sets the Namespace of the Unstructured.