Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions translator/common_fields.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2022 Red Hat, Inc.
//
// Licensed 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 translator

import (
"fmt"

"github.com/coreos/go-semver/semver"
)

type commonFields struct {
Variant string `yaml:"variant"`
Version semver.Version `yaml:"version"`
}

func (c *commonFields) UnmarshalYAML(unmarshal func(interface{}) error) error {
type plain commonFields
var raw plain

if err := unmarshal(&raw); err != nil {
return err
}

if raw.Variant == "" {
return fmt.Errorf("variant cannot be empty")
}

*c = commonFields(raw)
return nil
}

func (c *commonFields) asKey() string {
return fmt.Sprintf("%s+%s", c.Variant, c.Version.String())
}

func newCF(variant, version string) (commonFields, error) {
if variant == "" {
return commonFields{}, fmt.Errorf("variant cannot be empty")
}

v, err := semver.NewVersion(version)
if err != nil {
return commonFields{}, fmt.Errorf("invalid version: %w", err)
}

return commonFields{
Variant: variant,
Version: *v,
}, nil
}
23 changes: 23 additions & 0 deletions translator/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2022 Red Hat, Inc.
//
// Licensed 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 translator

import (
"github.com/coreos/butane/config/common"
"github.com/coreos/vcontext/report"
)

type Translator interface {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is an interface but i think it needs to be expanded.

So im pretty sure what we are hitting a cycle on is validation, and you can see that the translate has already been inverted but we need to do the same for validate I believe.

We might need more then just validate tho.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok for validate too, I think the rest will come as I implement it. It's hard to plan that much in advance 😅

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100% agree'd. I think after we add validate and metadata we should be good atleast to start

TranslateBytes(input []byte, options common.TranslateBytesOptions) ([]byte, report.Report, error)
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually we prob, want a new type that is used in translator

Metadata

with "variant, version,ignition version, description, and maybe isexperimental"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good, one of my first idea was to re-use

type commonFields struct {
	Variant string         `yaml:"variant"`
	Version semver.Version `yaml:"version"`
}

as the key to the registry, I guess it can/should be the base for the new Metadata type 👍

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah that would make sense. Yeah its basically the building block of what we need.

54 changes: 54 additions & 0 deletions translator/registery.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2022 Red Hat, Inc.
//
// Licensed 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 translator

import (
"fmt"

"github.com/coreos/butane/config/common"
"github.com/coreos/vcontext/report"
"gopkg.in/yaml.v3"
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking we would have

a set(register), get, list, then maybe we could add metadata to the interface.

I.e a Translator would have metadata that would be used to lookup the translator/validator you want.

var TranslatorRegistry = &Registry{
translators: make(map[string]Translator),
}

type Registry struct {
translators map[string]Translator
}

func (r *Registry) RegisterTranslator(variant, version string, trans Translator) {
cf, err := newCF(variant, version)
if err != nil {
panic(fmt.Sprintf("tried to register a translator with an invalid key (%s+%s)", variant, version))
}
if _, ok := r.translators[cf.asKey()]; ok {
panic(fmt.Sprintf("tried to reregister existing translator (%s+%s)", variant, version))
}
r.translators[cf.asKey()] = trans
}

func (r *Registry) TranslateBytes(input []byte, options common.TranslateBytesOptions) ([]byte, report.Report, error) {
// first determine version; this will ignore most fields
cf := commonFields{}
if err := yaml.Unmarshal(input, &cf); err != nil {
return nil, report.Report{}, common.ErrUnmarshal{
Detail: err.Error(),
}
}

translator := r.translators[cf.asKey()]
return translator.TranslateBytes(input, options)
}