package osbuild2 import ( "encoding/json" "fmt" ) // Single stage of a pipeline executing one step type Stage struct { // Well-known name in reverse domain-name notation, uniquely identifying // the stage type. Type string `json:"type"` // Stage-type specific options fully determining the operations of the Inputs Inputs `json:"inputs,omitempty"` Options StageOptions `json:"options,omitempty"` } // Collection of Inputs for a Stage type Inputs interface { isStageInputs() } // Single Input for a Stage type Input interface { isInput() } // Fields shared between all Input types (should be embedded in each instance) type inputCommon struct { Type string `json:"type"` // Origin should be either 'org.osbuild.source' or 'org.osbuild.pipeline' Origin string `json:"origin"` // References References `json:"references"` } type StageInput interface { isStageInput() } type References interface { isReferences() } // StageOptions specify the operations of a given stage-type. type StageOptions interface { isStageOptions() } type InputOptions interface { } type rawStage struct { Type string `json:"type"` Options json.RawMessage `json:"options"` Inputs json.RawMessage `json:"inputs"` } // UnmarshalJSON unmarshals JSON into a Stage object. Each type of stage has // a custom unmarshaller for its options, selected based on the stage name. func (stage *Stage) UnmarshalJSON(data []byte) error { var rawStage rawStage if err := json.Unmarshal(data, &rawStage); err != nil { return err } var options StageOptions var inputs Inputs switch rawStage.Type { case "org.osbuild.fix-bls": options = new(FixBLSStageOptions) case "org.osbuild.fstab": options = new(FSTabStageOptions) case "org.osbuild.grub2": options = new(GRUB2StageOptions) case "org.osbuild.locale": options = new(LocaleStageOptions) case "org.osbuild.selinux": options = new(SELinuxStageOptions) case "org.osbuild.hostname": options = new(HostnameStageOptions) case "org.osbuild.users": options = new(UsersStageOptions) case "org.osbuild.groups": options = new(GroupsStageOptions) case "org.osbuild.timezone": options = new(TimezoneStageOptions) case "org.osbuild.chrony": options = new(ChronyStageOptions) case "org.osbuild.keymap": options = new(KeymapStageOptions) case "org.osbuild.firewall": options = new(FirewallStageOptions) case "org.osbuild.rhsm": options = new(RHSMStageOptions) case "org.osbuild.systemd": options = new(SystemdStageOptions) case "org.osbuild.script": options = new(ScriptStageOptions) case "org.osbuild.sysconfig": options = new(SysconfigStageOptions) case "org.osbuild.kernel-cmdline": options = new(KernelCmdlineStageOptions) case "org.osbuild.rpm": options = new(RPMStageOptions) inputs = new(RPMStageInputs) case "org.osbuild.oci-archive": options = new(OCIArchiveStageOptions) inputs = new(OCIArchiveStageInputs) case "org.osbuild.ostree.commit": options = new(OSTreeCommitStageOptions) inputs = new(OSTreeCommitStageInputs) case "org.osbuild.ostree.pull": options = new(OSTreePullStageOptions) inputs = new(OSTreePullStageInputs) case "org.osbuild.ostree.init": options = new(OSTreeInitStageOptions) case "org.osbuild.ostree.preptree": options = new(OSTreePrepTreeStageOptions) default: return fmt.Errorf("unexpected stage type: %s", rawStage.Type) } if err := json.Unmarshal(rawStage.Options, options); err != nil { return err } if inputs != nil && rawStage.Inputs != nil { if err := json.Unmarshal(rawStage.Inputs, inputs); err != nil { return err } } stage.Type = rawStage.Type stage.Options = options stage.Inputs = inputs return nil }