Repository: osbuild/osbuild-composer
Pull request #140 (2019-12-04 00:56:02)

Produce correct .toml files

larskarlitski: > Shouldn't we `omitempty` them?

Good point. Fixed and added a comment why we're not setting `omitempty` for json. Thanks!
larskarlitski: Forgot updating the test, which assumed empty arrays there. Pushed a fix.

Patch:
diff --git a/internal/blueprint/blueprint.go b/internal/blueprint/blueprint.go
index 1aecccbdd..2b3b39054 100644
--- a/internal/blueprint/blueprint.go
+++ b/internal/blueprint/blueprint.go
@@ -3,32 +3,35 @@ package blueprint
 
 // A Blueprint is a high-level description of an image.
 type Blueprint struct {
-	Name           string          `json:"name"`
-	Description    string          `json:"description"`
-	Version        string          `json:"version,omitempty"`
-	Packages       []Package       `json:"packages"`
-	Modules        []Package       `json:"modules"`
-	Groups         []Group         `json:"groups"`
-	Customizations *Customizations `json:"customizations,omitempty"`
+	Name        string    `json:"name" toml:"name"`
+	Description string    `json:"description" toml:"description"`
+	Version     string    `json:"version,omitempty" toml:"version,omitempty"`
+	Packages    []Package `json:"packages" toml:"packages"`
+
+	// skip "omitempty" for json, because cockpit-composer chokes when the keys are missing
+	Modules []Package `json:"modules" toml:"modules,omitempty"`
+	Groups  []Group   `json:"groups" toml:"groups,omitempty"`
+
+	Customizations *Customizations `json:"customizations,omitempty" toml:"customizations,omitempty"`
 }
 
 type Change struct {
-	Commit    string    `json:"commit"`
-	Message   string    `json:"message"`
-	Revision  *string   `json:"revision"`
-	Timestamp string    `json:"timestamp"`
-	Blueprint Blueprint `json:"-"`
+	Commit    string    `json:"commit" toml:"commit"`
+	Message   string    `json:"message" toml:"message"`
+	Revision  *string   `json:"revision" toml:"revision"`
+	Timestamp string    `json:"timestamp" toml:"timestamp"`
+	Blueprint Blueprint `json:"-" toml:"-"`
 }
 
 // A Package specifies an RPM package.
 type Package struct {
-	Name    string `json:"name"`
-	Version string `json:"version,omitempty"`
+	Name    string `json:"name" toml:"name"`
+	Version string `json:"version,omitempty" toml:"version,omitempty"`
 }
 
 // A group specifies an package group.
 type Group struct {
-	Name string `json:"name"`
+	Name string `json:"name" toml:"name"`
 }
 
 // packages, modules, and groups all resolve to rpm packages right now. This
diff --git a/internal/blueprint/customizations.go b/internal/blueprint/customizations.go
index 5d20d49be..d5ccedd4b 100644
--- a/internal/blueprint/customizations.go
+++ b/internal/blueprint/customizations.go
@@ -1,66 +1,66 @@
 package blueprint
 
 type Customizations struct {
-	Hostname *string                `json:"hostname,omitempty"`
-	Kernel   *KernelCustomization   `json:"kernel,omitempty"`
-	SSHKey   []SSHKeyCustomization  `json:"sshkey,omitempty"`
-	User     []UserCustomization    `json:"user,omitempty"`
-	Group    []GroupCustomization   `json:"group,omitempty"`
-	Timezone *TimezoneCustomization `json:"timezone,omitempty"`
-	Locale   *LocaleCustomization   `json:"locale,omitempty"`
-	Firewall *FirewallCustomization `json:"firewall,omitempty"`
-	Services *ServicesCustomization `json:"services,omitempty"`
+	Hostname *string                `json:"hostname,omitempty" toml:"hostname,omitempty"`
+	Kernel   *KernelCustomization   `json:"kernel,omitempty" toml:"kernel,omitempty"`
+	SSHKey   []SSHKeyCustomization  `json:"sshkey,omitempty" toml:"sshkey,omitempty"`
+	User     []UserCustomization    `json:"user,omitempty" toml:"user,omitempty"`
+	Group    []GroupCustomization   `json:"group,omitempty" toml:"group,omitempty"`
+	Timezone *TimezoneCustomization `json:"timezone,omitempty" toml:"timezone,omitempty"`
+	Locale   *LocaleCustomization   `json:"locale,omitempty" toml:"locale,omitempty"`
+	Firewall *FirewallCustomization `json:"firewall,omitempty" toml:"firewall,omitempty"`
+	Services *ServicesCustomization `json:"services,omitempty" toml:"services,omitempty"`
 }
 
 type KernelCustomization struct {
-	Append string `json:"append"`
+	Append string `json:"append" toml:"append"`
 }
 
 type SSHKeyCustomization struct {
-	User string `json:"user"`
-	Key  string `json:"key"`
+	User string `json:"user" toml:"user"`
+	Key  string `json:"key" toml:"key"`
 }
 
 type UserCustomization struct {
-	Name        string   `json:"name"`
-	Description *string  `json:"description,omitempty"`
-	Password    *string  `json:"password,omitempty"`
-	Key         *string  `json:"key,omitempty"`
-	Home        *string  `json:"home,omitempty"`
-	Shell       *string  `json:"shell,omitempty"`
-	Groups      []string `json:"groups,omitempty"`
-	UID         *int     `json:"uid,omitempty"`
-	GID         *int     `json:"gid,omitempty"`
+	Name        string   `json:"name" toml:"name"`
+	Description *string  `json:"description,omitempty" toml:"description,omitempty"`
+	Password    *string  `json:"password,omitempty" toml:"password,omitempty"`
+	Key         *string  `json:"key,omitempty" toml:"key,omitempty"`
+	Home        *string  `json:"home,omitempty" toml:"home,omitempty"`
+	Shell       *string  `json:"shell,omitempty" toml:"shell,omitempty"`
+	Groups      []string `json:"groups,omitempty" toml:"groups,omitempty"`
+	UID         *int     `json:"uid,omitempty" toml:"uid,omitempty"`
+	GID         *int     `json:"gid,omitempty" toml:"gid,omitempty"`
 }
 
 type GroupCustomization struct {
-	Name string `json:"name"`
-	GID  *int   `json:"gid,omitempty"`
+	Name string `json:"name" toml:"name"`
+	GID  *int   `json:"gid,omitempty" toml:"gid,omitempty"`
 }
 
 type TimezoneCustomization struct {
-	Timezone   *string  `json:"timezone,omitempty"`
-	NTPServers []string `json:"ntpservers,omitempty"`
+	Timezone   *string  `json:"timezone,omitempty" toml:"timezone,omitempty"`
+	NTPServers []string `json:"ntpservers,omitempty" toml:"ntpservers,omitempty"`
 }
 
 type LocaleCustomization struct {
-	Languages []string `json:"languages,omitempty"`
-	Keyboard  *string  `json:"keyboard,omitempty"`
+	Languages []string `json:"languages,omitempty" toml:"languages,omitempty"`
+	Keyboard  *string  `json:"keyboard,omitempty" toml:"keyboard,omitempty"`
 }
 
 type FirewallCustomization struct {
-	Ports    []string                       `json:"ports,omitempty"`
-	Services *FirewallServicesCustomization `json:"services,omitempty"`
+	Ports    []string                       `json:"ports,omitempty" toml:"ports,omitempty"`
+	Services *FirewallServicesCustomization `json:"services,omitempty" toml:"services,omitempty"`
 }
 
 type FirewallServicesCustomization struct {
-	Enabled  []string `json:"enabled,omitempty"`
-	Disabled []string `json:"disabled,omitempty"`
+	Enabled  []string `json:"enabled,omitempty" toml:"enabled,omitempty"`
+	Disabled []string `json:"disabled,omitempty" toml:"disabled,omitempty"`
 }
 
 type ServicesCustomization struct {
-	Enabled  []string `json:"enabled,omitempty"`
-	Disabled []string `json:"disabled,omitempty"`
+	Enabled  []string `json:"enabled,omitempty" toml:"enabled,omitempty"`
+	Disabled []string `json:"disabled,omitempty" toml:"disabled,omitempty"`
 }
 
 type CustomizationError struct {
diff --git a/internal/weldr/api.go b/internal/weldr/api.go
index aa307e712..6d774c33a 100644
--- a/internal/weldr/api.go
+++ b/internal/weldr/api.go
@@ -733,7 +733,9 @@ func (api *API) blueprintsInfoHandler(writer http.ResponseWriter, request *http.
 			statusResponseError(writer, http.StatusBadRequest, errors)
 			return
 		}
-		toml.NewEncoder(writer).Encode(blueprints[0])
+		encoder := toml.NewEncoder(writer)
+		encoder.Indent = ""
+		encoder.Encode(blueprints[0])
 	} else {
 		errors := responseError{
 			ID:  "InvalidChars",


Test patch:
diff --git a/internal/weldr/api_test.go b/internal/weldr/api_test.go
index 04e9c9314..998ef7f85 100644
--- a/internal/weldr/api_test.go
+++ b/internal/weldr/api_test.go
@@ -160,8 +160,6 @@ func TestBlueprintsInfoToml(t *testing.T) {
 		t.Fatalf("error decoding toml file: %v", err)
 	}
 
-	t.Logf("%v", got)
-
 	expected := blueprint.Blueprint{
 		Name:        "test1",
 		Description: "Test",
@@ -169,8 +167,6 @@ func TestBlueprintsInfoToml(t *testing.T) {
 		Packages: []blueprint.Package{
 			{"httpd", "2.4.*"},
 		},
-		Groups:  []blueprint.Group{},
-		Modules: []blueprint.Package{},
 	}
 	if diff := cmp.Diff(got, expected); diff != "" {
 		t.Fatalf("received unexpected blueprint: %s", diff)