diff --git a/builder/builder.go b/builder/builder.go index 8760be0..7b57fd1 100644 --- a/builder/builder.go +++ b/builder/builder.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Intel Corporation +// +// 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 builder import ( @@ -210,6 +224,10 @@ func (b *Builder) UpdateRepo(ver string, allbundles bool) { // FIXME: Maybe use Go's tar or compress packages to do this _, err = exec.Command("tar", "-xzf", repo, "-C", "clr-bundles/").Output() + if err != nil { + helpers.PrintError(err) + os.Exit(1) + } bundles := b.Bundledir if _, err := os.Stat(bundles); os.IsNotExist(err) { clrbundles := "clr-bundles/clr-bundles-" + ver + "/bundles/" @@ -266,7 +284,7 @@ func (b *Builder) AddBundles(bundles []string, force bool, allbundles bool, git // Check if mix bundles dir exists if _, err := os.Stat(bundledir); os.IsNotExist(err) { - helpers.PrintError(errors.New("Mix bundles directory does not exist. Run mixer init-mix.")) + helpers.PrintError(errors.New("Mix bundles directory does not exist. Run mixer init-mix")) os.Exit(1) } @@ -380,7 +398,7 @@ func (b *Builder) InitMix(clearver string, mixver string, all bool, upstreamurl return nil } -// UpdatMixVer automatically bumps the mixversion file +10 to prepare for the next build +// UpdateMixVer automatically bumps the mixversion file +10 to prepare for the next build // without requiring user intervention. This makes the flow slightly more automatable. func (b *Builder) UpdateMixVer() { mixver, _ := strconv.Atoi(b.Mixver) @@ -506,16 +524,16 @@ func (b *Builder) setVersion(publish bool) { if b.Upstreamurl != "" { fmt.Println("Saving the upstream version URL " + b.Upstreamurl) - upstream_url := b.Statedir + "/www/" + b.Mixver + "/upstream_url" - err = ioutil.WriteFile(upstream_url, []byte(b.Upstreamurl), 0644) + upstreamurl := b.Statedir + "/www/" + b.Mixver + "/upstreamurl" + err = ioutil.WriteFile(upstreamurl, []byte(b.Upstreamurl), 0644) if err != nil { helpers.PrintError(err) os.Exit(1) } } fmt.Println("Saving the upstream version " + b.Clearver) - upstream_ver := b.Statedir + "/www/" + b.Mixver + "/upstream_ver" - err = ioutil.WriteFile(upstream_ver, []byte(b.Clearver), 0644) + upstreamver := b.Statedir + "/www/" + b.Mixver + "/upstreamver" + err = ioutil.WriteFile(upstreamver, []byte(b.Clearver), 0644) if err != nil { helpers.PrintError(err) os.Exit(1) @@ -591,6 +609,10 @@ func (b *Builder) BuildUpdate(prefixflag string, minvflag int, formatflag string // Step 4: hardlink relevant dirs _, err = exec.Command("hardlink", "-f", b.Statedir+"/image/"+b.Mixver+"/").Output() + if err != nil { + helpers.PrintError(err) + os.Exit(1) + } // Step 5: update the latest version b.setVersion(publishflag) @@ -600,7 +622,7 @@ func (b *Builder) BuildUpdate(prefixflag string, minvflag int, formatflag string // BuildImage will now proceed to build the full image with the previously // validated configuration. -func (b *Builder) BuildImage(format string, template string) { +func (b *Builder) BuildImage(format string, template string) error { // If the user did not pass in a format, default to builder.conf if format == "" { format = b.Format @@ -615,9 +637,7 @@ func (b *Builder) BuildImage(format string, template string) { wd, _ := os.Getwd() tempStage, err := ioutil.TempDir(wd, "ister-swupd-client-") if err != nil { - // TODO: This should return a proper error and the caller deals with printing. - helpers.PrintError(err) - return + return err } defer os.RemoveAll(tempStage) @@ -626,11 +646,7 @@ func (b *Builder) BuildImage(format string, template string) { imagecmd.Stdout = os.Stdout imagecmd.Stderr = os.Stderr - err = imagecmd.Run() - if err != nil { - helpers.PrintError(err) - fmt.Println("Failed to create image, check /var/log/ister") - } + return imagecmd.Run() } // AddRPMList copies rpms into the repodir and calls createrepo_c on it to diff --git a/helpers/helpers.go b/helpers/helpers.go index e0184ef..706bb44 100644 --- a/helpers/helpers.go +++ b/helpers/helpers.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Intel Corporation +// +// 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 helpers import ( @@ -233,5 +247,5 @@ func CheckRPM(rpm string) error { if strings.Contains(string(output), "RPM v") { return nil } - return fmt.Errorf("ERROR: %s is not valid!", rpm) + return fmt.Errorf("ERROR: %s is not valid", rpm) } diff --git a/mixer/cmd/build.go b/mixer/cmd/build.go new file mode 100644 index 0000000..5d6c131 --- /dev/null +++ b/mixer/cmd/build.go @@ -0,0 +1,169 @@ +// Copyright © 2017 Intel Corporation +// +// 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 cmd + +import ( + "fmt" + "io/ioutil" + "os" + + "github.com/clearlinux/mixer-tools/builder" + "github.com/clearlinux/mixer-tools/helpers" + "github.com/pkg/errors" + + "github.com/spf13/cobra" +) + +type buildCmdFlags struct { + format string + increment bool + minVersion int + noSigning bool + prefix string + noPublish bool + keepChroot bool + template string +} + +var buildFlags buildCmdFlags + +// buildCmd represents the base build command when called without any subcommands +var buildCmd = &cobra.Command{ + Use: "build", + Short: "Build various pieces of OS content", +} + +func buildChroots(builder *builder.Builder, signflag bool) error { + // Create the signing and validation key/cert + if _, err := os.Stat(builder.Cert); os.IsNotExist(err) { + fmt.Println("Generating certificate for signature validation...") + privkey, err := helpers.CreateKeyPair() + if err != nil { + return errors.Wrap(err, "Error generating OpenSSL keypair") + } + template := helpers.CreateCertTemplate() + + err = builder.BuildChroots(template, privkey, signflag) + if err != nil { + return errors.Wrap(err, "Error building chroots") + } + } else { + err := builder.BuildChroots(nil, nil, true) + if err != nil { + return errors.Wrap(err, "Error building chroots") + } + } + return nil +} + +var buildChrootsCmd = &cobra.Command{ + Use: "chroots", + Short: "Build the chroots for your mix", + Long: `Build the chroots for your mix`, + RunE: func(cmd *cobra.Command, args []string) error { + b := builder.NewFromConfig(config) + return buildChroots(b, buildFlags.noSigning) + }, +} + +var buildUpdateCmd = &cobra.Command{ + Use: "update", + Short: "Build the update content for your mix", + Long: `Build the update content for your mix`, + RunE: func(cmd *cobra.Command, args []string) error { + b := builder.NewFromConfig(config) + err := b.BuildUpdate(buildFlags.prefix, buildFlags.minVersion, buildFlags.format, buildFlags.noSigning, !buildFlags.noPublish, buildFlags.keepChroot) + if err != nil { + return errors.Wrap(err, "Error building update") + } + + if buildFlags.increment { + b.UpdateMixVer() + } + return nil + }, +} + +var buildAllCmd = &cobra.Command{ + Use: "all", + Short: "Build all content for mix with default options", + Long: `Build all content for mix with default options`, + RunE: func(cmd *cobra.Command, args []string) error { + b := builder.NewFromConfig(config) + rpms, err := ioutil.ReadDir(b.Rpmdir) + if err == nil { + b.AddRPMList(rpms) + } + err = buildChroots(b, buildFlags.noSigning) + if err != nil { + return errors.Wrap(err, "Error building chroots") + } + err = b.BuildUpdate(buildFlags.prefix, buildFlags.minVersion, buildFlags.format, buildFlags.noSigning, !buildFlags.noPublish, buildFlags.keepChroot) + if err != nil { + return errors.Wrap(err, "Error building update") + } + + b.UpdateMixVer() + return nil + }, +} + +var buildImageCmd = &cobra.Command{ + Use: "image", + Short: "Build an image from the mix content", + Long: `Build an image from the mix content`, + RunE: func(cmd *cobra.Command, args []string) error { + b := builder.NewFromConfig(config) + err := b.BuildImage(buildFlags.format, buildFlags.template) + if err != nil { + return errors.Wrap(err, "Error building image") + } + return nil + }, +} + +func setUpdateFlags(cmd *cobra.Command) { + cmd.Flags().StringVar(&buildFlags.format, "format", "", "Supply format to use") + cmd.Flags().BoolVar(&buildFlags.increment, "increment", false, "Automatically increment the mixversion post build") + cmd.Flags().IntVar(&buildFlags.minVersion, "minversion", 0, "Supply minversion to build update with") + cmd.Flags().BoolVar(&buildFlags.noSigning, "no-signing", false, "Do not generate a certificate and do not sign the Manifest.MoM") + cmd.Flags().StringVar(&buildFlags.prefix, "prefix", "", "Supply prefix for where the swupd binaries live") + cmd.Flags().BoolVar(&buildFlags.noPublish, "no-publish", false, "Do not update the latest version after update") + cmd.Flags().BoolVar(&buildFlags.keepChroot, "keep-chroots", false, "Keep individual chroots created and not just consolidated 'full'") +} + +var buildCmds = []*cobra.Command{ + buildChrootsCmd, + buildUpdateCmd, + buildAllCmd, + buildImageCmd, +} + +func init() { + for _, cmd := range buildCmds { + buildCmd.AddCommand(cmd) + cmd.Flags().StringVarP(&config, "config", "c", "", "Builder config to use") + } + + RootCmd.AddCommand(buildCmd) + + buildChrootsCmd.Flags().BoolVar(&buildFlags.noSigning, "no-signing", false, "Do not generate a certificate to sign the Manifest.MoM") + + buildImageCmd.Flags().StringVar(&buildFlags.format, "format", "", "Supply the format used for the Mix") + buildImageCmd.Flags().StringVar(&buildFlags.template, "template", "", "Path to template file to use") + + setUpdateFlags(buildUpdateCmd) + setUpdateFlags(buildAllCmd) +} diff --git a/mixer/cmd/bundles.go b/mixer/cmd/bundles.go new file mode 100644 index 0000000..7754568 --- /dev/null +++ b/mixer/cmd/bundles.go @@ -0,0 +1,81 @@ +// Copyright © 2017 Intel Corporation +// +// 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 cmd + +import ( + "fmt" + "strings" + + "github.com/clearlinux/mixer-tools/builder" + + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +type bundleCmdFlags struct { + all bool + force bool + git bool +} + +var bundleFlags bundleCmdFlags + +var addBundlesCmd = &cobra.Command{ + Use: "add-bundles [bundle list]", + Short: "Add clr-bundles to your mix", + Long: `Add clr-bundles to your mix`, + RunE: func(cmd *cobra.Command, args []string) error { + if bundleFlags.all == false { + if len(args) <= 0 { + return errors.New("add-bundles requires at least 1 argument if --all is not passed") + } + } + bundles := strings.Split(args[0], ",") + b := builder.NewFromConfig(config) + // TODO change this to return (int, error) + numadded := b.AddBundles(bundles, bundleFlags.force, bundleFlags.all, bundleFlags.git) + fmt.Println(numadded, " bundles were added") + return nil + }, +} + +var getBundlesCmd = &cobra.Command{ + Use: "get-bundles", + Short: "Get the clr-bundles from upstream", + Long: `Get the clr-bundles from upstream`, + RunE: func(cmd *cobra.Command, args []string) error { + b := builder.NewFromConfig(config) + fmt.Println("Getting clr-bundles for version " + b.Clearver) + // TODO change this to return an error + b.UpdateRepo(b.Clearver, false) + return nil + }, +} + +var bundlesCmds = []*cobra.Command{ + addBundlesCmd, + getBundlesCmd, +} + +func init() { + for _, cmd := range bundlesCmds { + RootCmd.AddCommand(cmd) + cmd.Flags().StringVarP(&config, "config", "c", "", "Builder config to use") + } + + addBundlesCmd.Flags().BoolVar(&bundleFlags.force, "force", false, "Override bundles that already exist") + addBundlesCmd.Flags().BoolVar(&bundleFlags.all, "all", false, "Add all bundles from CLR; takes precedence over -bundles") + addBundlesCmd.Flags().BoolVar(&bundleFlags.git, "git", false, "Automatically apply new git commit") +} diff --git a/mixer/cmd/root.go b/mixer/cmd/root.go new file mode 100644 index 0000000..44de572 --- /dev/null +++ b/mixer/cmd/root.go @@ -0,0 +1,97 @@ +// Copyright © 2017 Intel Corporation +// +// 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 cmd + +import ( + "fmt" + "os" + "os/exec" + "strconv" + + "github.com/clearlinux/mixer-tools/builder" + + "github.com/spf13/cobra" +) + +var config string + +// RootCmd represents the base command when called without any subcommands +var RootCmd = &cobra.Command{ + Use: "mixer", + Long: `Mixer is a tool used to compose OS update content and images.`, +} + +type initCmdFlags struct { + all bool + clearver int + mixver int + upstreamurl string +} + +var initFlags initCmdFlags + +var initCmd = &cobra.Command{ + Use: "init-mix", + Short: "Initialize the mixer and workspace", + Long: `Initialize the mixer and workspace`, + RunE: func(cmd *cobra.Command, args []string) error { + b := builder.New() + b.LoadBuilderConf(config) + b.ReadBuilderConf() + return b.InitMix(strconv.Itoa(initFlags.clearver), strconv.Itoa(initFlags.mixver), initFlags.all, initFlags.upstreamurl) + }, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + if err := RootCmd.Execute(); err != nil { + fmt.Fprintf(os.Stderr, "Mixer Error: %s\n", err) + os.Exit(1) + } +} + +func checkDeps() error { + deps := []string{ + "createrepo_c", + "git", + "hardlink", + "m4", + "openssl", + "parallel", + "rpm", + "yum", + } + for _, dep := range deps { + if _, err := exec.LookPath(dep); err != nil { + return fmt.Errorf("failed to find program %q: %v", dep, err) + } + } + return nil +} + +func init() { + if err := checkDeps(); err != nil { + fmt.Fprintf(os.Stderr, "Error: %s\n", err) + } + + RootCmd.AddCommand(initCmd) + + initCmd.Flags().BoolVar(&initFlags.all, "all", false, "Create a mix with all Clear bundles included") + initCmd.Flags().IntVar(&initFlags.clearver, "clearver", 1, "Supply the Clear version to compose the mix from") + initCmd.Flags().IntVar(&initFlags.mixver, "mixver", 0, "Supply the Mix version to build") + initCmd.Flags().StringVar(&config, "config", "", "Supply a specific builder.conf to use for mixing") + initCmd.Flags().StringVar(&initFlags.upstreamurl, "upstreamurl", "https://download.clearlinux.org", "Supply an upstream URL to use for mixing") +} diff --git a/mixer/cmd/rpms.go b/mixer/cmd/rpms.go new file mode 100644 index 0000000..f55f9a3 --- /dev/null +++ b/mixer/cmd/rpms.go @@ -0,0 +1,51 @@ +// Copyright © 2017 Intel Corporation +// +// 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 cmd + +import ( + "io/ioutil" + + "github.com/clearlinux/mixer-tools/builder" + + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +var addRPMCmd = &cobra.Command{ + Use: "add-rpms", + Short: "Add rpms to local yum repository", + Long: `Add rpms to local yum repository`, + RunE: func(cmd *cobra.Command, args []string) error { + b := builder.NewFromConfig(config) + rpms, err := ioutil.ReadDir(b.Rpmdir) + if err != nil { + return errors.Wrapf(err, "Error cannot read %s\n", b.Rpmdir) + } + // TODO return error to check from AddRPMList + b.AddRPMList(rpms) + return nil + }, +} + +var rpmCmds = []*cobra.Command{ + addRPMCmd, +} + +func init() { + for _, cmd := range rpmCmds { + RootCmd.AddCommand(cmd) + cmd.Flags().StringVarP(&config, "config", "c", "", "Builder config to use") + } +} diff --git a/mixer/main.go b/mixer/main.go index 02649dd..220db6f 100644 --- a/mixer/main.go +++ b/mixer/main.go @@ -1,272 +1,31 @@ +// Copyright © 2017 Intel Corporation +// +// 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 main import ( - "flag" "fmt" - "io/ioutil" "os" - "os/exec" - "strconv" - "strings" - "github.com/clearlinux/mixer-tools/builder" - "github.com/clearlinux/mixer-tools/helpers" + "github.com/clearlinux/mixer-tools/mixer/cmd" ) const Version = "3.2.1" -type Command struct { - Name string - Description string - Run func(args []string) -} - -var commands []*Command - -func init() { - commands = []*Command{ - {"build-all", "Build all content for mix with default options", cmdBuildAll}, - {"build-chroots", "Build chroots for the mix", cmdBuildChroots}, - {"build-update", "Build all update content for the mix", cmdBuildUpdate}, - {"build-image", "Build an image from the mix content", cmdBuildImage}, - {"add-rpms", "Add rpms to local yum repository", cmdAddRPMs}, - {"get-bundles", "Get the clr-bundles from upstream", cmdGetBundles}, - {"add-bundles", "Add clr-bundles to your mix", cmdAddBundles}, - {"init-mix", "Initialize the mixer and workspace", cmdInitMix}, - {"help", "Show help options", cmdHelp}, - } -} - -func PrintMainHelp() { - fmt.Printf("usage: mixer [args]\n") - for _, cmd := range commands { - fmt.Printf("\t%-20s\t%s\n", cmd.Name, cmd.Description) - } -} - -func CheckDeps() error { - deps := []string{ - "createrepo_c", - "git", - "hardlink", - "m4", - "openssl", - "parallel", - "rpm", - "yum", - } - for _, dep := range deps { - if _, err := exec.LookPath(dep); err != nil { - return fmt.Errorf("failed to find program %q: %v\n", dep, err) - } - } - return nil -} - func main() { fmt.Printf("Mixer %s\n", Version) os.Setenv("LD_PRELOAD", "/usr/lib64/nosync/nosync.so") - if len(os.Args) == 1 { - PrintMainHelp() - return - } - - var cmd *Command - name := os.Args[1] - if name == "-h" { - name = "help" - } - if name != "version" && name != "help" { - err := CheckDeps() - if err != nil { - fmt.Fprintf(os.Stderr, "ERROR: %v\n", err) - os.Exit(1) - } - } - - for _, c := range commands { - if c.Name == name { - cmd = c - } - } - - if cmd == nil { - fmt.Printf("%q is not a valid command.\n", name) - os.Exit(-1) - } - - args := os.Args[2:] - cmd.Run(args) -} - -type UpdateVars struct { - Format string - Increment bool - MinVersion int - NoSigning bool - Prefix string - NoPublish bool - KeepChroot bool -} - -func setupUpdateFlags(v *UpdateVars, fs *flag.FlagSet) { - fs.StringVar(&v.Format, "format", "", "Supply format to use") - fs.BoolVar(&v.Increment, "increment", false, "Automatically increment the mixversion post build") - fs.IntVar(&v.MinVersion, "minversion", 0, "Supply minversion to build update with") - fs.BoolVar(&v.NoSigning, "no-signing", false, "Do not generate a certificate and do not sign the Manifest.MoM") - fs.StringVar(&v.Prefix, "prefix", "", "Supply prefix for where the swupd binaries live") - fs.BoolVar(&v.NoPublish, "no-publish", false, "Do not update the latest version after update") - fs.BoolVar(&v.KeepChroot, "keep-chroots", false, "Keep individual chroots created and not just consolidated 'full'") -} - -func cmdBuildAll(args []string) { - fs := flag.NewFlagSet("build-all", flag.ExitOnError) - config := fs.String("config", "", "Supply a specific builder.conf to use for mixing") - - v := &UpdateVars{} - setupUpdateFlags(v, fs) - - fs.Parse(args) - - b := builder.NewFromConfig(*config) - rpms, err := ioutil.ReadDir(b.Rpmdir) - if err == nil { - b.AddRPMList(rpms) - } - BuildChroots(b, v.NoSigning) - err = b.BuildUpdate(v.Prefix, v.MinVersion, v.Format, v.NoSigning, !v.NoPublish, v.KeepChroot) - if err != nil { - os.Exit(-1) - } - - b.UpdateMixVer() -} - -func cmdBuildChroots(args []string) { - fs := flag.NewFlagSet("build-chroots", flag.ExitOnError) - config := fs.String("config", "", "Supply a specific builder.conf to use for mixing") - noSigning := fs.Bool("no-signing", false, "Do not generate a certificate to sign the Manifest.MoM") - - fs.Parse(args) - - b := builder.NewFromConfig(*config) - BuildChroots(b, *noSigning) -} - -func cmdBuildUpdate(args []string) { - fs := flag.NewFlagSet("build-update", flag.ExitOnError) - config := fs.String("config", "", "Supply a specific builder.conf to use for mixing") - - v := &UpdateVars{} - setupUpdateFlags(v, fs) - - fs.Parse(args) - - b := builder.NewFromConfig(*config) - err := b.BuildUpdate(v.Prefix, v.MinVersion, v.Format, v.NoSigning, !v.NoPublish, v.KeepChroot) - if err != nil { - os.Exit(-1) - } - - if v.Increment { - b.UpdateMixVer() - } -} - -func cmdBuildImage(args []string) { - imagecmd := flag.NewFlagSet("build-image", flag.ExitOnError) - imageformat := imagecmd.String("format", "", "Supply the format used for the Mix") - conf := imagecmd.String("config", "", "Supply a specific builder.conf to use for mixing") - imagetemplate := imagecmd.String("template", "", "Path to tempalte file to use") - - imagecmd.Parse(args) - - b := builder.NewFromConfig(*conf) - b.BuildImage(*imageformat, *imagetemplate) -} - -func cmdAddRPMs(args []string) { - flags := flag.NewFlagSet("add-rpms", flag.ExitOnError) - conf := flags.String("config", "", "Supply a specific builder.conf to use for mixing") - flags.Parse(args) - - b := builder.NewFromConfig(*conf) - rpms, err := ioutil.ReadDir(b.Rpmdir) - if err != nil { - fmt.Printf("ERROR: cannot read %s\n", b.Rpmdir) - } - b.AddRPMList(rpms) -} - -func cmdGetBundles(args []string) { - bundlescmd := flag.NewFlagSet("get-bundles", flag.ExitOnError) - bundleconf := bundlescmd.String("config", "", "Supply a specific builder.conf to use for mixing") - bundlescmd.Parse(args) - b := builder.NewFromConfig(*bundleconf) - fmt.Println("Getting clr-bundles for version " + b.Clearver) - b.UpdateRepo(b.Clearver, false) -} - -func cmdAddBundles(args []string) { - flags := flag.NewFlagSet("add-bundles", flag.ExitOnError) - bundlesarg := flags.String("bundles", "", "Comma-separated list of bundles to add") - force := flags.Bool("force", false, "Override bundles that already exist") - all := flags.Bool("all", false, "Add all bundles from CLR; takes precedence over -bundles") - git := flags.Bool("git", false, "Automatically apply new git commit") - conf := flags.String("config", "", "Supply a specific builder.conf to use for mixing") - flags.Parse(args) - - var bundles []string - if !*all { - if len(*bundlesarg) == 0 { - flags.Usage() - os.Exit(1) - } else { - bundles = strings.Split(*bundlesarg, ",") - } - } - - b := builder.NewFromConfig(*conf) - b.AddBundles(bundles, *force, *all, *git) -} - -func cmdInitMix(args []string) { - initcmd := flag.NewFlagSet("init-mix", flag.ExitOnError) - allflag := initcmd.Bool("all", false, "Create a mix with all Clear bundles included") - clearflag := initcmd.Int("clearver", 1, "Supply the Clear version to compose the mix from") - mixflag := initcmd.Int("mixver", 0, "Supply the Mix version to build") - initconf := initcmd.String("config", "", "Supply a specific builder.conf to use for mixing") - upstreamurl := initcmd.String("upstreamurl", "https://download.clearlinux.org", "Supply an upstream URL to use for mixing") - initcmd.Parse(args) - b := builder.New() - b.LoadBuilderConf(*initconf) - b.ReadBuilderConf() - b.InitMix(strconv.Itoa(*clearflag), strconv.Itoa(*mixflag), *allflag, *upstreamurl) -} - -func cmdHelp(args []string) { - PrintMainHelp() -} - -func BuildChroots(builder *builder.Builder, signflag bool) { - // Create the signing and validation key/cert - if _, err := os.Stat(builder.Cert); os.IsNotExist(err) { - fmt.Println("Generating certificate for signature validation...") - privkey, err := helpers.CreateKeyPair() - if err != nil { - os.Exit(1) - } - template := helpers.CreateCertTemplate() - - err = builder.BuildChroots(template, privkey, signflag) - if err != nil { - os.Exit(-1) - } - } else { - err := builder.BuildChroots(nil, nil, true) - if err != nil { - os.Exit(-1) - } - } + cmd.Execute() }