diff --git a/cmd/load.go b/cmd/load.go index e50c42b..f32f991 100644 --- a/cmd/load.go +++ b/cmd/load.go @@ -92,10 +92,12 @@ func loadCommand(cmd *cobra.Command, args []string) (err error) { for x, xx := range setup.AllSettings() { if reflect.ValueOf(x).Kind() != reflect.Map { + x = strings.Replace(x, "_", "-", -1) vmDefs[name].Set(x, xx) } } for x, xx := range def.(map[string]interface{}) { + x = strings.Replace(x, "_", "-", -1) vmDefs[name].Set(x, xx) } vmDefs[name].Set("name", name) diff --git a/cmd/run.go b/cmd/run.go index 4bd1d59..981f49a 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -189,7 +189,16 @@ func vmBootstrap(args *viper.Viper) (vm *server.VMInfo, err error) { vm.Ethernet = append(vm.Ethernet, server.NetworkInterface{Type: server.Raw}) - err = vm.ValidateCloudConfig(args.GetString("cloud_config")) + fuzeCfgs := viperStringSliceBugWorkaround( + args.GetStringSlice("ignition-fuze-config")) + + if args.GetString("cloud-config") != "" && len(fuzeCfgs) != 0 { + err = fmt.Errorf("you can either use cloud-config or " + + "ignition-fuze-config") + return + } + err = vm.ValidateUserProvidedConfigs( + args.GetString("cloud-config"), fuzeCfgs) if err != nil { return } @@ -209,8 +218,11 @@ func runFlagsDefaults(setFlag *pflag.FlagSet) { setFlag.IntP("memory", "m", 1024, "VM's RAM, in MB, per instance (1024 < memory < 8192)") setFlag.IntP("cpus", "N", 1, "VM number of virtual CPUs") - setFlag.StringP("cloud_config", "L", "", + setFlag.StringP("cloud-config", "L", "", "cloud-config file location (either an URL or a local path)") + setFlag.StringSliceP("ignition-fuze-config", "I", nil, + "ignition fuze drop-ins file(s) location "+ + "(either an URL or a local path)") setFlag.StringP("sshkey", "k", "", "VM's default ssh key") setFlag.StringP("root", "r", "", "append a (persistent) root volume to VM") setFlag.BoolP("format-root", "F", false, @@ -230,6 +242,11 @@ func runFlagsDefaults(setFlag *pflag.FlagSet) { setFlag.MarkHidden("tap") setFlag.MarkHidden("extra") setFlag.MarkHidden("boot") + setFlag.SetNormalizeFunc(wordSepNormalizeFunc) +} + +func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName { + return pflag.NormalizedName(strings.Replace(name, "_", "-", -1)) } func init() { diff --git a/components/common/assets/assets_vfsdata.go b/components/common/assets/assets_vfsdata.go index 89839db..c82ca67 100644 --- a/components/common/assets/assets_vfsdata.go +++ b/components/common/assets/assets_vfsdata.go @@ -49,7 +49,7 @@ var Assets = func() http.FileSystem { }, "/target/coreos": &vfsgen۰DirInfo{ name: "coreos", - modTime: mustUnmarshalTextTime("2016-10-19T18:17:50Z"), + modTime: mustUnmarshalTextTime("2016-11-13T21:13:12Z"), }, "/target/coreos/CoreOSkey.public": &vfsgen۰CompressedFileInfo{ name: "CoreOSkey.public", @@ -60,10 +60,10 @@ var Assets = func() http.FileSystem { }, "/target/coreos/corectl.ignition.yaml": &vfsgen۰CompressedFileInfo{ name: "corectl.ignition.yaml", - modTime: mustUnmarshalTextTime("2016-10-19T18:17:50Z"), - uncompressedSize: 4258, + modTime: mustUnmarshalTextTime("2016-11-14T12:39:33Z"), + uncompressedSize: 4637, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xcc\x56\x6d\x6f\xe3\x36\x12\xfe\xee\x5f\x31\xa7\x06\x68\x8b\x8b\xac\xa4\xf5\xb6\x07\x17\x2a\xe0\x24\xde\xc6\xb8\xc4\x0e\x6c\x27\xfd\x90\xdb\x33\x18\x71\x6c\xf1\x42\x91\x3a\x72\x14\xc7\xab\xfa\xbf\x1f\xa8\x17\x4b\x79\x71\x91\xc3\x06\xd8\x0a\x08\x22\x0f\x67\x46\xcf\x3c\xf3\xc2\xf9\x26\x92\x3a\xe3\x7e\xa4\xd5\x52\xac\x3a\x1d\xdf\xf7\x3b\x79\x0e\x62\x09\x42\x71\x7c\x04\x6f\x36\x3b\x1f\x64\x14\x6b\x23\x3e\x23\xff\x27\x6e\xac\x07\xdb\x6d\x27\x65\xd6\xae\x79\xbf\x03\x90\x59\x34\xd6\xbd\x00\xf8\xa0\x58\x82\x7d\x88\xb4\xc1\x42\x00\x60\x6d\xbc\x60\x3b\xf3\xc5\x3d\x6e\x2a\x5d\xf7\xe4\x39\x18\xa6\x56\x08\x07\x28\x31\x41\x45\xd0\x0f\xa1\xfb\xe2\x83\xee\x7b\xb5\x89\x0f\x79\x5e\x6b\xb7\xc4\x79\x8e\x8a\x6f\xb7\x9d\xfa\xbf\x25\x6d\xd8\x0a\xdd\xa7\xca\x60\xba\x33\xa4\x2c\x9d\x6a\x4d\xa5\x37\x2e\xec\xfd\x0e\x35\xc7\x07\x11\x61\x1f\x02\x8e\x0f\xc1\x03\x67\x95\xdb\xb5\x48\x71\x41\xec\x4e\x62\x1f\xc8\x64\x75\x48\x29\x33\x24\x48\x68\xd5\x8a\xc4\x07\xc9\xee\x50\xf6\x61\x3a\x99\xcc\x3b\x00\x4b\x21\xd1\x6e\x2c\x61\xf2\x8c\x1a\xa3\x35\x55\x56\x89\xce\x14\x35\x2e\x6a\x10\x5e\x8d\xe2\xd8\xdb\x9d\x2d\xb5\x49\x18\xf5\xc1\xc3\x47\xea\x35\xe2\xc8\x20\x23\x6c\x5c\x14\x8a\xd1\x53\xb4\xee\xd1\xe9\x33\xb8\x25\x22\xcf\xbf\x70\x70\xbd\x82\x24\x94\x16\x0b\xa2\xae\xd0\x58\x61\x09\x15\x35\x6c\x7d\x71\x38\x8e\xee\xe0\x6e\xe3\x17\x2c\x05\xf5\x57\xf7\x04\x57\x27\xb1\xfa\xae\xf3\xe9\x43\xca\x28\xee\x43\x10\xeb\x04\x03\x57\x5f\xc1\x9d\x50\xc1\x52\x28\xee\x8b\xb4\xd7\xb5\x71\xa7\xc4\xc0\xb1\x0f\x47\x3f\x7f\xf8\x50\xfc\x6c\x60\xb7\x90\xba\x7a\xad\x61\x0a\xde\x87\x0f\x47\x47\xc5\xaf\x95\xd1\x59\xfa\xda\x41\xa4\x95\x63\x63\x47\x9f\x50\x52\x28\xec\xc3\x1f\xbb\x08\xbe\xf9\x5b\x81\xa6\x02\xe1\x9e\xd1\xc7\xc1\xe9\x30\xf4\x0e\xf2\xe3\x6d\x13\xe8\xc7\xd1\x45\x21\xfb\xa1\x25\xbb\x19\x4c\x47\x83\x93\x52\xfe\x63\x4b\xbe\x8e\x85\x44\xb8\x05\xff\x33\x78\x07\xb9\x48\xb7\x1e\x7c\xfa\x05\xb8\x6e\xa5\x50\xa4\xe1\xc1\x77\x22\x05\xbf\x07\xbe\x06\xc6\xb9\x01\x1b\xeb\xb5\x63\xde\xd9\x14\x10\xb6\x1e\xd8\x48\xa7\x08\x2b\xa9\xef\x98\x84\x3f\xe0\x5f\x4f\x8a\x60\xc5\xd6\xf7\xf0\x6d\x6e\x53\x29\x08\xbe\x3b\xe8\x1d\x82\xce\xe8\x10\xbc\xc0\xfb\xfe\x17\x48\x8d\x50\xe4\x04\xb7\xc7\x9f\xb6\xdf\x7e\xdf\x32\xb4\x12\x31\x85\xee\x71\x93\x6d\xad\x9a\x82\xc3\x28\xd6\x35\xea\x9d\xd0\x22\x07\x5f\x80\x8f\xe0\x05\xff\x3e\xc8\xeb\xb8\xb7\x61\xc0\x3d\xa7\xec\xc8\x69\xa9\xd7\x3e\x1a\xbd\x8a\x85\x5f\x7f\x7d\xa2\xbd\x2b\x0c\xa4\x28\xd0\x98\xf8\x06\x25\x32\x8b\xed\x72\xf8\xa9\xd7\x7b\x7b\x39\xec\x29\x86\xb7\x96\xc2\xe8\x2c\x74\xd5\x19\x91\x6c\x52\x3c\x9c\xce\x46\x93\xf1\x62\x74\x16\xe6\x79\xf7\xb4\x3c\xbd\x71\x5d\xa6\x55\x6b\x84\x8d\x07\x97\xc3\xd0\x73\xc7\x93\x19\xe8\x07\x34\x90\xb0\x68\x32\x83\x84\x71\x04\x2b\x92\x54\x62\x43\xcf\xf9\xe4\x72\xb8\xb8\x9e\x5e\x84\x5e\x4c\x94\xda\x7e\x10\xac\x04\xc5\xd9\x5d\x37\xd2\x49\x30\x8f\x71\x8c\xeb\xb1\x6b\x2b\x19\x54\x68\x1a\xd3\x93\xeb\xdf\x16\xd3\xe1\xd5\x64\x3a\xff\xbf\x1c\x04\xc2\xda\x0c\x6d\xe0\x75\x3a\x0a\x69\xad\xcd\x7d\x39\xfd\x95\xa0\xaa\x43\xcb\x89\xd0\x3b\xf2\x91\xe2\xa3\x6e\xa5\xf4\x94\xb6\x1d\x51\xb7\x97\x8c\xa2\xf8\x53\x13\x3c\x4b\x30\x74\x76\xf5\xf9\xb8\x34\x6f\x34\xce\xce\x4f\xaf\xc2\x0d\xda\x46\x30\x9e\x39\x3e\x2b\x45\xfe\x1b\x23\x5c\xb3\x4d\x8b\xd0\x33\x9d\x30\xa1\x6c\x5b\xe9\x4c\xd9\x9d\xc2\xad\xf3\xd8\xf8\xbf\xb6\x58\x1b\x14\xd3\xb3\x53\x56\xca\xeb\x41\x66\x29\x67\x84\x3e\xaa\x95\x50\xd8\xb5\x68\xdc\xac\x2b\x5c\xa1\x2a\xef\x8b\x25\x93\x45\x11\xd6\x16\x52\x47\xf7\x36\x11\x14\xf3\x37\xa9\x57\xa4\xfb\x16\xc9\x8f\xb5\x25\x27\x7d\xd5\x70\x37\xe9\x5f\xe1\xf8\x5a\x09\x6a\x11\x88\x36\x32\xa2\xb8\x09\xc2\x19\x92\x85\xf3\xca\x6f\xad\x3e\x2b\xdd\x37\x16\xf3\x4d\x8a\xa1\x56\x68\xe3\xdd\x90\x07\x98\xa2\x23\x69\xb0\x24\x34\xc3\x47\x41\x4f\x52\x32\x23\xa6\x38\x33\x7c\x92\x51\x9a\x51\xf8\x1f\x9d\x19\xc5\xe4\xdf\x23\xad\xac\x96\xcd\x7c\x18\x3e\x62\x34\x23\x66\x28\x0c\x32\x6b\x8a\xd1\x59\xc7\x18\x91\x84\x76\xcc\x90\xe7\xdd\x1a\x67\x93\xb9\x91\xb2\xc4\xa4\x6c\x90\xfe\xce\x14\x21\x3f\xd9\x84\x77\xcc\x8a\xa8\x4b\xcc\xac\x90\x5a\x74\x5a\xa4\xa1\x7a\x78\x5f\x02\xb3\xd4\x96\x53\x07\xd5\x83\x30\x5a\xb9\x8d\xa4\xc5\xd2\x7f\x33\x61\xd0\x86\x65\x15\x55\xdb\x55\x03\xac\x6a\x45\x5c\x6a\x83\x7f\xa6\xf3\x55\x92\xb2\xf7\x8e\x05\xd7\xa1\x2f\x82\x86\xd3\xc9\x74\x38\x99\x2d\xae\xa6\xa3\x9b\xc1\x7c\xb8\x18\x5d\xdd\xf4\xde\xd3\xed\xf5\xc9\xc5\xe8\xb4\xed\xf5\x65\xfe\x2b\xba\x5d\x05\xec\x21\xb3\xae\x84\x34\xd6\x0a\x7d\x07\xe5\x1d\xab\x61\x8e\x52\xda\xba\x67\x39\x50\xcc\xc8\x0d\xef\x58\x28\x84\x95\x26\xc8\xd2\x57\x0a\xe3\x65\x49\xba\xa7\xc8\xe1\xeb\x87\x5f\xb5\x41\xa3\xcc\x48\xf0\x2f\x2c\x34\x57\x18\x1f\x2a\x9e\x6a\xe1\xf6\xf0\x20\x15\x6a\xf5\xa6\xec\x3c\x0f\xac\xce\x8b\x1b\xd2\x1f\x67\x2e\x2f\x5c\x98\x2b\x46\xf1\xd0\x46\x2c\x45\xbe\xdd\x76\x8b\xc5\xb2\x58\x0b\x8b\x3d\x3e\x66\x06\xf9\x79\xa9\x58\x8d\x84\x67\xd9\x2b\x97\xd9\xea\x2c\x61\xf6\xbe\x7d\x52\x6d\x96\x6f\xc8\xf0\x2e\x55\x26\x8d\x7c\x4b\x8c\xf8\x9e\x6c\xed\x3b\xbf\xbd\x74\xc8\x5b\x53\x2a\x66\x54\x6f\x07\xbc\xeb\x5e\xb4\xed\x4a\x1d\x31\xd9\x7f\x11\x7e\xeb\x1e\xfb\x3d\x46\x83\xe1\x9f\x69\x4c\xca\xfd\x3e\x34\xeb\x43\x66\x37\x2a\x3a\x54\xda\xdd\x37\x87\x4a\x33\x12\x09\x1e\x1a\x2b\x3e\x63\xf8\xe3\x0f\x3f\xff\xf4\x8f\xc3\x75\xf3\xfe\xb4\x8e\xd4\xb2\xa9\x93\xb9\x48\x50\x67\x34\xc3\x28\x3c\x3e\x7a\x87\xae\xd3\x19\x11\x1a\x77\xac\x30\x22\xf1\x20\x68\xe3\x47\x31\x46\xf7\xef\xd8\x84\xa7\xce\x5f\xd9\x7b\x37\x97\xc0\x22\xca\x98\x94\x1b\x88\x99\x05\x56\x2c\x89\x40\x31\x16\x7f\x25\x1a\x58\x6b\x23\xf9\xcb\x6c\xef\x99\x10\x4d\xba\xf7\x2a\xfc\x35\x1a\xb4\xbd\xe0\xd7\xbb\x9d\x61\xeb\x6e\xb9\xdf\xb9\x75\xb7\xa2\x75\xff\xaa\xb7\xd2\x92\xa9\x55\x70\x39\x18\x8d\xe7\x83\xd1\x78\x38\x9d\x7d\xc1\x68\x18\x6b\x1a\x59\x2d\x19\x21\x7f\x4b\x25\xbd\xc2\xee\xff\x02\x00\x00\xff\xff\xbf\x0c\x71\xbd\xa2\x10\x00\x00"), + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xcc\x57\x6d\x6f\xe3\x36\x12\xfe\xee\x5f\x31\xa7\x0b\xd0\x16\x17\x59\x49\x9b\x6d\x0f\x2e\x54\xc0\x9b\xf5\x36\xc6\x25\x76\x60\x3b\xe9\x87\xdc\x9e\xc1\x88\x63\x8b\x17\x8a\xd4\x91\x23\x7b\x1d\xd5\xff\xfd\x40\xbd\x58\x4a\x62\x2f\xb2\x68\x80\x56\x40\x10\x79\x38\x1c\x3e\xf3\xcc\x0b\x47\xbe\xef\x77\xf2\x1c\xc4\x02\x84\xe2\xf8\x19\xbc\xe9\xf4\xa2\x9f\x51\xac\x8d\x78\x44\xfe\x2f\xdc\x58\x0f\xb6\xdb\x4e\xca\xac\x5d\xf3\x5e\x07\x20\xb3\x68\xac\x7b\x01\xf0\x41\xb1\x04\x7b\x10\x69\x83\x85\x00\xc0\xda\x78\xce\x76\xdb\xe7\x0f\xb8\xa9\x74\xdd\x93\xe7\x60\x98\x5a\x22\x1c\xa1\xc4\x04\x15\x41\x2f\x84\xee\x8b\x03\xc1\xdf\x6e\x77\x7b\x7c\xc8\xf3\x5a\xbd\x25\xce\x73\x54\x7c\xbb\xed\xd4\xff\x3b\x79\xee\x3b\x27\xba\x37\x16\xcd\xb5\xd1\x2b\xc1\x91\x7f\xcc\x1e\xf1\x5c\xab\x85\x58\x96\x36\xc5\x52\x09\x12\x5a\x39\x44\x51\x21\x2f\xb1\xb1\x34\x45\xc5\xf7\xe1\x64\xc7\x47\xf7\x05\xc8\x2f\x99\x6d\xa0\x5a\x9d\x99\x08\x7b\x0e\x72\xf7\x5c\x1b\x8c\x48\xf2\x81\xe2\xa9\x16\x0e\x7c\x50\x9f\x1f\x94\x07\x06\x79\x7e\xc4\xf6\xfa\x04\xa8\xb8\x63\xbd\x63\x49\x1b\xb6\x44\x07\xad\x0c\x52\x77\x8a\x94\xa5\x13\xad\x09\x8a\x9d\x5c\xd8\x87\x5d\x34\x38\xae\x84\x3b\x3e\xe0\xb8\x0a\x56\x9c\x55\x96\xd7\x22\xc5\x39\xb1\x7b\x89\x3d\x20\x93\xd5\xa1\x4a\x99\xa1\x02\x4e\x2b\x42\x3e\x48\x76\x8f\xb2\x07\x93\xf1\x78\xd6\x01\x58\x08\x89\x76\x63\x09\x93\x67\x21\x37\x5a\x53\xb5\x2b\xd1\x99\xa2\xc6\x44\x0d\xc2\xab\x51\x9c\x7a\xbb\xb5\x85\x36\x09\xa3\x1e\x78\xf8\x99\xce\x1a\x71\x64\x90\x11\x36\x26\x0a\xc5\xe8\x29\x5a\xf7\xe8\xf4\x19\xdc\x12\x91\xe7\x5f\x3a\xb8\x5e\x41\x12\x4a\x8b\x05\x51\xd7\x68\xac\xb0\x84\x8a\x1a\xb6\xfe\xb0\x3b\x8e\xee\xe0\x7e\xe3\x17\x2c\x05\xf5\xa9\x07\x9c\xab\xe3\x59\x9d\xeb\x6c\xfa\x90\x32\x8a\x7b\x10\xc4\x3a\xc1\xc0\xd5\x4d\x70\x2f\x54\xb0\x10\x8a\xfb\x22\x3d\xeb\xda\xb8\x53\x62\xe0\xd8\x83\x93\x9f\xde\xbd\x2b\x7e\x36\xb0\x5b\x48\x5d\x1d\xd6\x30\x05\xef\xc1\xbb\x93\x93\xe2\xd7\xd2\xe8\x2c\xdd\xb7\x10\x69\xe5\xd8\xd8\xd1\x27\x94\x14\x0a\x7b\xf0\xfb\xce\x83\xbf\xff\xad\x40\x53\x81\x70\xcf\xf0\x63\xff\x7c\x10\x7a\x47\xf9\xe9\xb6\x71\xf4\xe3\xf0\xb2\x90\x7d\xdf\x92\xdd\xf6\x27\xc3\xfe\xfb\x52\xfe\x43\x4b\xbe\x8e\x85\x44\xb8\x03\xff\x11\xbc\xa3\x5c\xa4\x5b\x0f\x3e\xfd\x0c\x5c\xb7\x42\x28\xd2\xf0\xe8\x5b\x91\x82\x7f\x06\xbe\x06\xc6\xb9\x01\x1b\xeb\xb5\x63\xde\xed\x29\x20\x6c\x3d\xb0\x91\x4e\x11\x96\x52\xdf\x33\x09\xbf\xc3\xbf\x9f\x24\xc1\x92\xad\x1f\xe0\x9b\xdc\xa6\x52\x10\x7c\x7b\x74\x76\x0c\x3a\xa3\x63\xf0\x02\xef\xbb\x9f\x21\x35\x42\x91\x13\xdc\x9d\x7e\xda\x7e\xf3\x5d\x6b\xa3\x95\x88\x29\x74\x4f\x9b\x68\x6b\xd5\x24\x1c\x46\xb1\xae\x51\xef\x84\x16\x39\xf8\x02\x7c\x04\x2f\xf8\xcf\x51\x5e\xfb\xbd\x0d\x03\xee\x39\x65\x47\x4e\x4b\xbd\xb6\xd1\xe8\x55\x2c\xfc\xf2\xcb\x13\xed\x5d\x62\x20\x45\x81\xc6\xc4\x37\x28\x91\x59\x6c\xa7\xc3\x8f\x67\x67\xaf\x4f\x87\x03\xc9\xf0\xda\x54\x18\x7e\x08\xa3\xb2\x81\x35\x21\x1e\x4c\xa6\xc3\xf1\x68\x3e\xfc\x10\xe6\x79\xdd\xde\x6e\x5d\x95\x69\xd5\xea\x62\xa3\xfe\xd5\x20\xf4\xdc\xf2\x78\x0a\x7a\x85\x06\x12\x16\x8d\xa7\x90\x30\x8e\x60\x45\x92\x4a\x6c\xe8\xb9\x18\x5f\x0d\xe6\x37\x93\xcb\xd0\x8b\x89\x52\xdb\x0b\x82\xa5\xa0\x38\xbb\xef\x46\x3a\x09\x66\x31\x8e\x70\x3d\x72\x65\x25\x83\x0a\x4d\xb3\xf5\xfd\xcd\xaf\xf3\xc9\xe0\x7a\x3c\x99\x7d\x95\x81\x40\x58\x9b\xa1\x0d\xbc\x4e\x47\x21\xad\xb5\x79\x28\x6f\x35\x25\xa8\xaa\xd0\xb2\x23\x9c\x9d\xf8\x48\xf1\x49\xb7\x52\x7a\x4a\xdb\x8e\xa8\xbb\x2b\x46\x51\xfc\xa9\x71\x9e\x25\x18\xba\x7d\xf5\xfa\xa8\xdc\xde\x68\x7c\xb8\x38\xbf\x0e\x37\x68\x1b\xc1\x68\xea\xf8\xac\x14\xf9\xaf\x8c\x70\xcd\x36\x2d\x42\x3f\xe8\x84\x09\x65\x9d\x52\xf9\xea\x0e\xd9\xad\xdf\x39\x83\x8d\xf9\x1b\x8b\xb5\x7e\xd1\x3c\x3b\x65\xa2\xec\xf7\xb1\xa2\xc4\xb7\x48\x7e\xac\x2d\x39\x69\xd7\xa2\x71\x1d\xaf\xb0\x88\xea\xd9\xad\xb1\x87\x81\x1b\x25\xa8\xe5\x1e\xda\xc8\x88\xa2\x4f\x87\x53\x24\x0b\x17\x95\xdd\x5a\x7d\x5a\x9a\x6f\x76\xcc\x36\x29\x86\x5a\xa1\x8d\x77\x2d\x18\x60\x82\xce\x87\xfe\x82\xd0\x0c\x3e\x0b\x7a\x42\xd8\x94\x98\xe2\xcc\xf0\x71\x46\x69\x46\xe1\x7f\x75\x66\x14\x93\xff\x88\xb4\xb2\x5a\x36\xd5\x3b\xf8\x8c\xd1\x94\x98\xa1\x30\xc8\xac\x29\x1a\x5b\xed\x63\x44\x12\xda\x3e\x43\x9e\x77\x6b\x9c\x0d\xb1\x43\x65\x89\x49\xd9\x20\xfd\x8d\x29\x42\xfe\x7e\x13\xde\x33\x2b\xa2\x2e\x31\xb3\x44\x6a\xd1\x69\x91\x06\x6a\xf5\xb6\x04\x66\xa9\x2d\x7b\x02\xaa\x95\x30\x5a\xb9\x31\xa8\xc5\xd2\xff\x32\x61\xd0\x86\x65\x90\xfd\x72\xa6\x69\x80\x55\x85\x82\x0b\x6d\xf0\x4b\x3a\x7f\x4a\x50\x0e\xde\x80\xe0\xea\xe7\x85\xd3\x70\x3e\x9e\x0c\xc6\xd3\xf9\xf5\x64\x78\xdb\x9f\x0d\xe6\xc3\xeb\xdb\xb3\xb7\x34\x7b\xf3\xfe\x72\x78\xde\xb6\xfa\x32\xfe\x15\xdd\x2e\x03\x0e\x90\xf9\xbc\xb0\x12\x24\xc6\x19\xb1\x27\x39\xf1\x55\x29\x70\xad\xd3\x4c\x32\x42\xd7\x44\x63\xa1\x10\x6a\x93\x5f\x17\xba\xb7\x0f\x8f\xc9\x54\x50\x63\xa9\x7b\x6b\x41\xe6\xf9\xec\xb2\xa0\x71\x3e\x98\x5d\x9c\xb4\x38\x49\x63\xad\xd0\x77\x66\xdf\xb0\x42\x66\x28\xa5\xad\xe9\xe6\x40\x31\xa3\x1d\x53\x4b\x4d\x90\xa5\x7b\x8a\xe5\x65\x99\xba\xa7\xc8\xeb\xfd\x8b\x7f\x6a\xd3\x8a\x32\x23\xc1\xbf\xb4\xd0\x5c\xba\xed\x6f\x8a\x54\xa8\xe5\xab\x32\xf6\xb9\x63\x75\x5c\xdc\xdd\xf3\x71\xea\xe2\xc2\x85\xb9\x66\x14\x0f\x6c\xc4\x52\xe4\xdb\x6d\xb7\x18\x85\x8b\x41\xb6\xf8\xf2\x88\x99\x41\x7e\x51\x2a\x56\x6d\xf2\x59\xf4\xca\xf1\xbb\x5a\x4b\x98\x7d\x68\xaf\x54\xb3\xf0\x2b\x22\xbc\x0b\x95\x49\x23\xdf\x12\x23\x7e\x20\x5a\x87\xd6\xef\xae\x1c\xf2\x56\xe7\x8e\x19\xd5\xf3\x0c\xef\xba\x17\x6d\xbb\x52\x47\x4c\xf6\x5e\xb8\xdf\xba\x79\x7f\x8b\xd1\x60\xf8\x25\x8d\x71\xf9\x45\x12\x9a\xf5\x31\xb3\x1b\x15\x1d\x2b\x2d\x75\xf4\x70\xac\x34\x23\x91\xe0\xb1\xb1\xe2\x11\xc3\x1f\xbe\xff\xe9\xc7\x7f\x1e\xaf\x9b\xf7\xa7\x79\xa4\x16\x4d\x9e\xcc\x44\x82\x3a\xa3\x29\x46\xe1\xe9\xc9\x1b\x74\x22\x9d\x11\xa1\x71\xcb\x0a\x23\x12\x2b\x41\x1b\x3f\x8a\x31\x7a\x78\xc3\x22\x3c\x77\xf6\xca\xda\xbb\xbd\x02\x16\x51\xc6\xa4\xdc\x40\xcc\x2c\xb0\x62\xac\x05\x8a\xb1\xf8\x2b\xd1\xc0\x5a\x1b\xc9\x5f\x46\xfb\x40\x87\x68\xc2\x7d\x50\xe1\xaf\x51\xa0\xed\x4f\x92\x7a\x1a\x35\x6c\xdd\x2d\x27\x52\x37\xa0\x57\xb4\x1e\x1e\x4e\x97\x5a\x32\xb5\x0c\xae\xfa\xc3\xd1\xac\x3f\x1c\x0d\x26\xd3\x3f\xd0\x1a\x46\x9a\x86\x56\xbb\xdb\x83\xbf\x26\x93\xf6\xb0\xfb\xff\x00\x00\x00\xff\xff\x73\x7a\x32\x94\x1d\x12\x00\x00"), }, } fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{ diff --git a/components/common/assets/static/target/coreos/corectl.ignition.yaml b/components/common/assets/static/target/coreos/corectl.ignition.yaml index 5a427ee..ae0c850 100644 --- a/components/common/assets/static/target/coreos/corectl.ignition.yaml +++ b/components/common/assets/static/target/coreos/corectl.ignition.yaml @@ -4,10 +4,20 @@ passwd: users: - name: core ssh_authorized_keys: - {{ range $element := .SSHAuthorizedKeys }} + {{ range $element := .SSHAuthorizedKeys -}} - {{$element}} {{end}} {{end}} + +{{- if .UserProvidedFuzeConfigs -}} +ignition: + config: + append: + {{ range $a,$b := .UserProvidedFuzeConfigs -}} + - source: {{$.CorectldEndpoint}}/ignition/append/{{$a}} + {{end}} +{{ end }} + storage: {{ if .SetupRoot }} disks: @@ -77,7 +87,7 @@ networkd: [Network] DHCP=yes DNS={{.NetworkdGateway}} - Domains={{.NetworkdDns}} + Domains={{.DomainName}} [DHCP] UseDomains=true diff --git a/components/server/httpservices.go b/components/server/httpservices.go index e7e812a..027661b 100644 --- a/components/server/httpservices.go +++ b/components/server/httpservices.go @@ -18,9 +18,9 @@ package server import ( "bytes" "encoding/json" - "io/ioutil" "net" "net/http" + "strconv" "strings" "text/template" @@ -28,6 +28,7 @@ import ( "github.com/TheNewNormal/corectl/components/target/coreos" "github.com/coreos/fuze/config" "github.com/coreos/go-systemd/unit" + "github.com/coreos/ignition/config/types" "github.com/deis/pkg/log" "github.com/gorilla/mux" ) @@ -35,15 +36,18 @@ import ( var httpServices = mux.NewRouter() type corectlTmpl struct { - SetupRoot, PersistentRoot, SharedHomedir bool - CorectlVersion, CorectldEndpoint string - NetworkdGateway, NetworkdDns, Hostname string - SSHAuthorizedKeys []string - NFShomedirPath, NFShomedirPathEscaped string + SetupRoot, PersistentRoot, SharedHomedir bool + CorectlVersion, CorectldEndpoint string + NetworkdGateway, DomainName, Hostname string + NFShomedirPath, NFShomedirPathEscaped string + SSHAuthorizedKeys, UserProvidedFuzeConfigs []string } func httpServiceSetup() { - httpServices.HandleFunc("/{uuid}/ignition", httpInstanceIgnitionConfig) + httpServices.HandleFunc("/{uuid}/ignition/append/{id}", + httpInstanceUserProvidedIgnitionConfigs) + httpServices.HandleFunc("/{uuid}/ignition/default/config", + httpInstanceDefaultIgnitionConfig) httpServices.HandleFunc("/{uuid}/cloud-config", httpInstanceCloudConfig) httpServices.HandleFunc("/{uuid}/ping", httpInstanceCallback) httpServices.HandleFunc("/{uuid}/NotIsolated", @@ -88,13 +92,13 @@ func acceptableRequest(r *http.Request, w http.ResponseWriter) bool { func httpInstanceCloudConfig(w http.ResponseWriter, r *http.Request) { if acceptableRequest(r, w) { vm := Daemon.Active[mux.Vars(r)["uuid"]] - if vm.CloudConfig == "" || vm.CClocation != Local { + if vm.CloudConfig.Location == "" { httpError(w, http.StatusPreconditionFailed) - } else if vm.cloudConfigContents == nil { + } else if vm.CloudConfig.Contents == nil { httpError(w, http.StatusInternalServerError) } else { vars := strings.NewReplacer("__vm.Name__", vm.Name) - w.Write([]byte(vars.Replace(string(vm.cloudConfigContents)))) + w.Write([]byte(vars.Replace(string(vm.CloudConfig.Contents)))) } } } @@ -108,44 +112,38 @@ func isPortOpen(t string, target string) bool { return false } -func httpInstanceIgnitionConfig(w http.ResponseWriter, r *http.Request) { +func httpInstanceUserProvidedIgnitionConfigs(w http.ResponseWriter, + r *http.Request) { if acceptableRequest(r, w) { - var ( - rendered bytes.Buffer - vm = Daemon.Active[mux.Vars(r)["uuid"]] - setup = corectlTmpl{ - vm.FormatRoot, - vm.PersistentRoot, - vm.SharedHomedir, - Daemon.Meta.Version, - vm.endpoint(), - session.Caller.Network.Address, - LocalDomainName, - vm.Name, - []string{vm.InternalSSHkey}, - session.Caller.HomeDir, - unit.UnitNamePathEscape(session.Caller.HomeDir), - } - ) - if vm.SSHkey != "" { - setup.SSHAuthorizedKeys = append(setup.SSHAuthorizedKeys, vm.SSHkey) - } - if vm.CloudConfig != "" && vm.CClocation == Local { - vm.cloudConfigContents, _ = ioutil.ReadFile(vm.CloudConfig) + vm := Daemon.Active[mux.Vars(r)["uuid"]] + ign, err := strconv.Atoi(mux.Vars(r)["id"]) + if err != nil { + httpError(w, http.StatusPreconditionFailed) } - t, _ := template.New("").Parse(string(coreos.CoreOSIgnitionTmpl)) - if err := t.Execute(&rendered, setup); err != nil { - log.Err("==> %v", err.Error()) - httpError(w, http.StatusInternalServerError) + if len(vm.IgnitionFuzeConfigs) == 0 { + httpError(w, http.StatusPreconditionFailed) + } else if len(vm.IgnitionFuzeConfigs) < ign+1 { + httpError(w, http.StatusPreconditionFailed) + } else { + if out, err := processIgnitionTemplate(r, vm, + string(vm.IgnitionFuzeConfigs[ign].Contents)); err != nil { + log.Err("%v", err.Error()) + httpError(w, http.StatusInternalServerError) + } else { + w.Write([]byte(append(out, '\n'))) + } } - - log.Info(rendered.String()) - if cfgIn, err := config.ParseAsV2_0_0(rendered.Bytes()); err != nil { - httpError(w, http.StatusInternalServerError) - } else if i, err := json.MarshalIndent(&cfgIn, "", " "); err != nil { + } +} +func httpInstanceDefaultIgnitionConfig(w http.ResponseWriter, r *http.Request) { + if acceptableRequest(r, w) { + vm := Daemon.Active[mux.Vars(r)["uuid"]] + if out, err := processIgnitionTemplate(r, vm, + coreos.CoreOSIgnitionTmpl); err != nil { + log.Err("%v", err.Error()) httpError(w, http.StatusInternalServerError) } else { - w.Write([]byte(append(i, '\n'))) + w.Write([]byte(append(out, '\n'))) if !isLoopback(remoteIP(r.RemoteAddr)) { Daemon.DNSServer.addRecord(vm.Name, remoteIP(r.RemoteAddr)) } @@ -153,6 +151,47 @@ func httpInstanceIgnitionConfig(w http.ResponseWriter, r *http.Request) { } } +func processIgnitionTemplate(r *http.Request, vm *VMInfo, + original string) (processed []byte, err error) { + var ( + rendered bytes.Buffer + cfgIn types.Config + setup = corectlTmpl{ + vm.FormatRoot, + vm.PersistentRoot, + vm.SharedHomedir, + Daemon.Meta.Version, + vm.endpoint(), + session.Caller.Network.Address, + LocalDomainName, + vm.Name, + session.Caller.HomeDir, + unit.UnitNamePathEscape(session.Caller.HomeDir), + []string{vm.InternalSSHkey}, + []string{}, + } + ) + if vm.SSHkey != "" { + setup.SSHAuthorizedKeys = append(setup.SSHAuthorizedKeys, vm.SSHkey) + } + for _, fz := range vm.IgnitionFuzeConfigs { + setup.UserProvidedFuzeConfigs = + append(setup.UserProvidedFuzeConfigs, fz.Location) + } + t, _ := template.New("").Parse(original) + if err = t.Execute(&rendered, setup); err != nil { + return + } + + log.Info(rendered.String()) + + if cfgIn, err = config.ParseAsV2_0_0(rendered.Bytes()); err != nil { + return + } + processed, err = json.MarshalIndent(&cfgIn, "", " ") + return +} + func httpInstanceExternalConnectivity(w http.ResponseWriter, r *http.Request) { if acceptableRequest(r, w) { if isLoopback(remoteIP(r.RemoteAddr)) { diff --git a/components/server/run.go b/components/server/run.go index bc15c4d..5800800 100644 --- a/components/server/run.go +++ b/components/server/run.go @@ -21,8 +21,10 @@ import ( "crypto/x509" "encoding/pem" "fmt" + "io/ioutil" "os/exec" "sort" + "sync" "syscall" "net/http" @@ -30,7 +32,6 @@ import ( "path/filepath" "strconv" "strings" - "sync" "time" "github.com/TheNewNormal/corectl/components/host/session" @@ -46,8 +47,10 @@ type ( MacAddress, PublicIP string InternalSSHkey, InternalSSHprivate string Cpus, Memory, Pid int - SSHkey, CloudConfig, CClocation string `json:",omitempty"` - AddToHypervisor, AddToKernel string `json:",omitempty"` + SSHkey string `json:",omitempty"` + CloudConfig UserProvidedConfig `json:",omitempty"` + IgnitionFuzeConfigs []UserProvidedConfig `json:",omitempty"` + AddToHypervisor, AddToKernel string `json:",omitempty"` Ethernet []NetworkInterface Storage StorageAssets `json:",omitempty"` SharedHomedir, OfflineMode, NotIsolated bool @@ -59,7 +62,6 @@ type ( done chan struct{} exec *exec.Cmd isolationCheck, callBack sync.Once - cloudConfigContents []byte } // VMmap map[string]*VMInfo @@ -80,6 +82,10 @@ type ( StorageAssets struct { CDDrives, HardDrives map[string]StorageDevice `json:",omitempty"` } + UserProvidedConfig struct { + Location string `json:",omitempty"` + Contents []byte `json:",omitempty"` + } ) const ( @@ -194,30 +200,45 @@ func (vm *VMInfo) ValidateVolumes(volumes []string, root bool) (err error) { } // ValidateCloudConfig ... -func (vm *VMInfo) ValidateCloudConfig(config string) (err error) { - var response *http.Response - - if len(config) > 0 { - if response, err = http.Get(config); response != nil { - response.Body.Close() - } - - vm.CloudConfig = config - - if err == nil && (response.StatusCode == http.StatusOK || - response.StatusCode == http.StatusNoContent) { - vm.CClocation = Remote +func (vm *VMInfo) ValidateUserProvidedConfigs(cloudconfig string, + ignitionfuzeconfig []string) (err error) { + var cc UserProvidedConfig + if cloudconfig != "" { + if cc, err = consumeUserProvidedConfig(cloudconfig); err != nil { return } - - if vm.CloudConfig, err = filepath.Abs(config); err != nil { + vm.CloudConfig = cc + } + for _, fuze := range ignitionfuzeconfig { + if cc, err = consumeUserProvidedConfig(fuze); err != nil { return } - if _, err = os.Stat(vm.CloudConfig); err != nil { + vm.IgnitionFuzeConfigs = append(vm.IgnitionFuzeConfigs, cc) + } + return +} + +func consumeUserProvidedConfig(src string) (out UserProvidedConfig, err error) { + if out.Location, err = filepath.Abs(src); err == nil { + if _, err = os.Stat(out.Location); err == nil { + out.Contents, _ = ioutil.ReadFile(out.Location) return } - vm.CClocation = Local } + // not local ... + var response *http.Response + if response, err = http.Get(src); response != nil { + defer response.Body.Close() + } + if err == nil && (response.StatusCode == http.StatusOK || + response.StatusCode == http.StatusNoContent) { + // URL is reachable, so grab it, so that it can be fuzed + out.Location = src + out.Contents, err = ioutil.ReadAll(response.Body) + return + } + err = fmt.Errorf("%v doesn't seem to be neither a "+ + "valid/reachable URL nor a valid file path", src) return } @@ -273,16 +294,15 @@ func (vm *VMInfo) assembleBootPayload() (xArgs []string, err error) { } cmdline = fmt.Sprintf("%s corectl.hostname=%s coreos.config.url=%s", - cmdline, vm.Name, vm.endpoint()+"/ignition") + cmdline, vm.Name, vm.endpoint()+"/ignition/default/config") - if vm.CloudConfig != "" { - if vm.CClocation == Local { - cmdline = fmt.Sprintf("%s cloud-config-url=%s", - cmdline, vm.endpoint()+"/cloud-config") - } else { - cmdline = fmt.Sprintf("%s cloud-config-url=%s", - cmdline, vm.CloudConfig) - } + if vm.CloudConfig.Contents != nil { + // local file + cmdline = fmt.Sprintf("%s cloud-config-url=%s", + cmdline, vm.endpoint()+"/cloud-config") + } else if vm.CloudConfig.Location != "" { + cmdline = fmt.Sprintf("%s cloud-config-url=%s", + cmdline, vm.CloudConfig.Location) } if vm.AddToHypervisor != "" { @@ -442,14 +462,20 @@ func (vm *VMInfo) TTY() string { } func (vm *VMInfo) PrettyPrint() { - fmt.Printf("\n UUID:\t\t%v\n Name:\t\t%v\n Version:\t%v\n "+ - "Channel:\t%v\n vCPUs:\t%v\n Memory (MB):\t%v\n", + fmt.Printf("\n UUID:\t\t\t%v\n Name:\t\t\t%v\n Version:\t\t%v\n "+ + "Channel:\t\t%v\n vCPUs:\t\t%v\n Memory (MB):\t\t%v\n", vm.UUID, vm.Name, vm.Version, vm.Channel, vm.Cpus, vm.Memory) - fmt.Printf(" Pid:\t\t%v\n Uptime:\t%v\n", + fmt.Printf(" Pid:\t\t\t%v\n Uptime:\t\t%v\n", vm.Pid, humanize.Time(vm.CreationTime)) - fmt.Printf(" Sees World:\t%v\n", vm.NotIsolated) - if vm.CloudConfig != "" { - fmt.Printf(" cloud-config:\t%v\n", vm.CloudConfig) + fmt.Printf(" Sees World:\t\t%v\n", vm.NotIsolated) + if vm.CloudConfig.Location != "" { + fmt.Printf(" cloud-config:\t\t%v\n", vm.CloudConfig.Location) + } + if ign := len(vm.IgnitionFuzeConfigs); ign > 0 { + fmt.Printf(" ignition drop-ins:\n") + for _, x := range vm.IgnitionFuzeConfigs { + fmt.Printf("\t\t\t- %v\n", x.Location) + } } fmt.Println(" Network:") fmt.Printf(" eth0:\t%v\n", vm.PublicIP) diff --git a/components/target/coreos/media.go b/components/target/coreos/media.go index 51c6fa7..3aa2bc2 100644 --- a/components/target/coreos/media.go +++ b/components/target/coreos/media.go @@ -16,68 +16,68 @@ package coreos import ( - "bufio" - "fmt" - "net/http" - "strings" + "bufio" + "fmt" + "net/http" + "strings" - "github.com/blang/semver" - "github.com/deis/pkg/log" + "github.com/blang/semver" + "github.com/deis/pkg/log" ) // Version validation func Version(version string) string { - if version == defaultVersion { - return version - } - if _, err := semver.Make(version); err != nil { - log.Warn("'%s' is not in a recognizable CoreOS version format. "+ - "Using default ('%s') instead", version, defaultVersion) - return defaultVersion - } - return version + if version == defaultVersion { + return version + } + if _, err := semver.Make(version); err != nil { + log.Warn("'%s' is not in a recognizable CoreOS version format. "+ + "Using default ('%s') instead", version, defaultVersion) + return defaultVersion + } + return version } // Channel validation func Channel(name string) string { - for _, b := range Channels { - if b == name { - return b - } - } - log.Warn("'%s' is not a recognizable CoreOS image channel. "+ - "Using default ('%s')", name, defaultChannel) - return defaultChannel + for _, b := range Channels { + if b == name { + return b + } + } + log.Warn("'%s' is not a recognizable CoreOS image channel. "+ + "Using default ('%s')", name, defaultChannel) + return defaultChannel } // LatestUpstream returns for the given channel the current shipping version func LatestUpstream(channel string) (string, error) { - url := fmt.Sprintf("http://%s.release.core-os.net/"+ - "amd64-usr/current/version.txt", channel) + url := fmt.Sprintf("http://%s.release.core-os.net/"+ + "amd64-usr/current/version.txt", channel) - response, err := http.Get(url) - // if err we're probably offline - if err != nil { - return "", err - } - defer response.Body.Close() + response, err := http.Get(url) + // if err we're probably offline + if err != nil { + return "", err + } + defer response.Body.Close() - switch response.StatusCode { - case http.StatusOK, http.StatusNoContent: - default: - return "", fmt.Errorf("failed fetching %s: HTTP status: %s", - url, response.Status) - } + switch response.StatusCode { + case http.StatusOK, http.StatusNoContent: + default: + return "", fmt.Errorf("failed fetching %s: HTTP status: %s", + url, response.Status) + } - s := bufio.NewScanner(response.Body) - s.Split(bufio.ScanLines) - for s.Scan() { - line := s.Text() - if eq := strings.LastIndex(line, "COREOS_VERSION="); eq >= 0 { - if v := strings.Split(line, "=")[1]; len(v) > 0 { - return v, err - } - } - } - return "", fmt.Errorf("unable to grab 'COREOS_VERSION' from %s (!)", url) + s := bufio.NewScanner(response.Body) + s.Split(bufio.ScanLines) + for s.Scan() { + line := s.Text() + if eq := strings.LastIndex(line, "COREOS_VERSION="); eq >= 0 { + if v := strings.Split(line, "=")[1]; len(v) > 0 { + return v, err + } + } + } + return "", fmt.Errorf("unable to grab 'COREOS_VERSION' from %s (!)", url) } diff --git a/documentation/man/corectl_run.1 b/documentation/man/corectl_run.1 index 35645b2..337fbd0 100644 --- a/documentation/man/corectl_run.1 +++ b/documentation/man/corectl_run.1 @@ -24,7 +24,7 @@ Boots a new CoreOS instance CoreOS channel stream .PP -\fB\-L\fP, \fB\-\-cloud\_config\fP="" +\fB\-L\fP, \fB\-\-cloud\-config\fP="" cloud\-config file location (either an URL or a local path) .PP @@ -35,6 +35,10 @@ Boots a new CoreOS instance \fB\-F\fP, \fB\-\-format\-root\fP[=false] formats and partitions the (persistent) root volume +.PP +\fB\-I\fP, \fB\-\-ignition\-fuze\-config\fP=[] + ignition fuze drop\-ins file(s) location (either an URL or a local path) + .PP \fB\-m\fP, \fB\-\-memory\fP=1024 VM's RAM, in MB, per instance (1024 < memory < 8192) diff --git a/documentation/markdown/corectl_run.md b/documentation/markdown/corectl_run.md index f0a009d..b172dfe 100644 --- a/documentation/markdown/corectl_run.md +++ b/documentation/markdown/corectl_run.md @@ -14,19 +14,20 @@ corectl run ### Options ``` - -c, --channel string CoreOS channel stream (default "alpha") - -L, --cloud_config string cloud-config file location (either an URL or a local path) - -N, --cpus int VM number of virtual CPUs (default 1) - -F, --format-root formats and partitions the (persistent) root volume - -m, --memory int VM's RAM, in MB, per instance (1024 < memory < 8192) (default 1024) - -n, --name string names the VM (default is VM's UUID) - -o, --offline doesn't go online to check for newer images than the locally available ones unless there is none available. - -r, --root string append a (persistent) root volume to VM - -H, --shared-homedir mounts (via NFS) host's homedir inside VM - -k, --sshkey string VM's default ssh key - -u, --uuid string VM's UUID (default "random") - -v, --version string CoreOS version (default "latest") - -p, --volume stringSlice append disk volumes to VM + -c, --channel string CoreOS channel stream (default "alpha") + -L, --cloud-config string cloud-config file location (either an URL or a local path) + -N, --cpus int VM number of virtual CPUs (default 1) + -F, --format-root formats and partitions the (persistent) root volume + -I, --ignition-fuze-config stringSlice ignition fuze drop-ins file(s) location (either an URL or a local path) + -m, --memory int VM's RAM, in MB, per instance (1024 < memory < 8192) (default 1024) + -n, --name string names the VM (default is VM's UUID) + -o, --offline doesn't go online to check for newer images than the locally available ones unless there is none available. + -r, --root string append a (persistent) root volume to VM + -H, --shared-homedir mounts (via NFS) host's homedir inside VM + -k, --sshkey string VM's default ssh key + -u, --uuid string VM's UUID (default "random") + -v, --version string CoreOS version (default "latest") + -p, --volume stringSlice append disk volumes to VM ``` ### Options inherited from parent commands diff --git a/examples/ignition/demo1.yaml b/examples/ignition/demo1.yaml new file mode 100644 index 0000000..513ea5f --- /dev/null +++ b/examples/ignition/demo1.yaml @@ -0,0 +1,15 @@ +--- +systemd: + units: + - name: sample-service-1.service + enable: true + contents: | + [Unit] + Description=sample service I + [Service] + Type=oneshot + RemainAfterExit=yes + StandardOutput=journal+console + ExecStart=/usr/bin/ping -c1 localhost + [Install] + RequiredBy=setEnv.service diff --git a/examples/ignition/demo2.yaml b/examples/ignition/demo2.yaml new file mode 100644 index 0000000..324c0f4 --- /dev/null +++ b/examples/ignition/demo2.yaml @@ -0,0 +1,17 @@ +--- +systemd: + units: + - name: sample-service-2.service + enable: true + contents: | + [Unit] + Description=sample service II (@{{.Hostname}}.{{.DomainName}}) + After=phone-home.service + Requires=phone-home.service + [Service] + Type=oneshot + RemainAfterExit=yes + StandardOutput=journal+console + ExecStart=/usr/bin/ping -c1 {{.Hostname}}.{{.DomainName}} + [Install] + RequiredBy=phone-home.service