diff --git a/cobblerclient.go b/cobblerclient.go index b0fdf8e..2fd5802 100644 --- a/cobblerclient.go +++ b/cobblerclient.go @@ -20,13 +20,14 @@ import ( "bytes" "errors" "fmt" - "github.com/go-viper/mapstructure/v2" - "github.com/kolo/xmlrpc" "io" "net/http" "reflect" "sort" "strings" + + "github.com/go-viper/mapstructure/v2" + "github.com/kolo/xmlrpc" ) const bodyTypeXML = "text/xml" @@ -157,11 +158,15 @@ func (c *Client) Ping() (bool, error) { } } -// AutoAddRepos automatically imports any repos server side that are known to the daemon. It is the responsitbility -// of the caller to execute [Client.BackgroundReposync]. -func (c *Client) AutoAddRepos() error { - _, err := c.Call("auto_add_repos", c.Token) - return err +// AutoAddRepos automatically imports any repos server-side that are known to the daemon. +// Returns whether the operation succeeded. The caller is responsible for following up +// with [Client.BackgroundReposync]. +func (c *Client) AutoAddRepos() (bool, error) { + result, err := c.Call("auto_add_repos", c.Token) + if err != nil { + return false, err + } + return result.(bool), nil } // GetAutoinstallTemplates retrieves a list of all templates that are in use by Cobbler. @@ -176,10 +181,13 @@ func (c *Client) GetAutoinstallSnippets() error { return err } -// IsAutoinstallInUse checks if a given system has reported that it is currently installing. -func (c *Client) IsAutoinstallInUse(name string) error { - _, err := c.Call("is_autoinstall_in_use", name, c.Token) - return err +// IsAutoinstallInUse reports whether the named system is currently installing. +func (c *Client) IsAutoinstallInUse(name string) (bool, error) { + result, err := c.Call("is_autoinstall_in_use", name, c.Token) + if err != nil { + return false, err + } + return result.(bool), nil } // GenerateIPxe generates the iPXE (formerly gPXE) configuration data. @@ -206,36 +214,82 @@ func (c *Client) GetBlendedData(profile, system string) (map[string]interface{}, return result.(map[string]interface{}), err } -// RegisterNewSystem registers a new system without a Cobbler token. This is normally called -// during unattended installation by a script. -func (c *Client) RegisterNewSystem(info map[string]interface{}) error { - _, err := c.Call("register_new_system", info, c.Token) - return err +// RegisterNewSystem registers a new system without a Cobbler token. Normally +// called during unattended installation by a script. Returns the backend's +// status code (0 on success). +func (c *Client) RegisterNewSystem(info map[string]interface{}) (int, error) { + result, err := c.Call("register_new_system", info, c.Token) + if err != nil { + return -1, err + } + return convertToInt(result) } -// RunInstallTriggers runs installation triggers for a given object. This is normally called during -// unattended installation. -func (c *Client) RunInstallTriggers(mode string, objtype string, name string, ip string) error { - _, err := c.Call("run_install_triggers", mode, objtype, name, ip, c.Token) - return err +// RunInstallTriggers runs installation triggers for a given object. Normally +// called during unattended installation. mode is "pre", "post", or "firstboot"; +// objtype is "system" or "profile". Returns whether the trigger ran successfully. +func (c *Client) RunInstallTriggers(mode, objtype, name, ip string) (bool, error) { + result, err := c.Call("run_install_triggers", mode, objtype, name, ip, c.Token) + if err != nil { + return false, err + } + return result.(bool), nil } -// GetReposCompatibleWithProfile returns all repositories that can be potentially assigned to a given profile. -func (c *Client) GetReposCompatibleWithProfile(profile_name string) error { - _, err := c.Call("get_repos_compatible_with_profile", profile_name, c.Token) - return err +// GetReposCompatibleWithProfile returns all repositories that can be assigned +// to the named profile (filtered by arch compatibility with the profile's distro). +func (c *Client) GetReposCompatibleWithProfile(profileName string) ([]map[string]interface{}, error) { + result, err := c.Call("get_repos_compatible_with_profile", profileName, c.Token) + if err != nil { + return nil, err + } + raw, ok := result.([]interface{}) + if !ok { + return nil, fmt.Errorf("get_repos_compatible_with_profile returned %T, want list", result) + } + out := make([]map[string]interface{}, 0, len(raw)) + for _, v := range raw { + if m, ok := v.(map[string]interface{}); ok { + out = append(out, m) + } + } + return out, nil } -// FindSystemByDnsName searches for a system with a given DNS name. -func (c *Client) FindSystemByDnsName(dns_name string) error { - _, err := c.Call("find_system_by_dns_name", dns_name) - return err +// FindSystemByDnsName searches for a system by DNS name. Returns the rendered +// system dict or an empty map if not found. +func (c *Client) FindSystemByDnsName(dnsName string) (map[string]interface{}, error) { + result, err := c.Call("find_system_by_dns_name", dnsName) + if err != nil { + return nil, err + } + if m, ok := result.(map[string]interface{}); ok { + return m, nil + } + return map[string]interface{}{}, nil +} + +// GetRandomMacFor returns a random MAC address tailored for the given virt_type. +// Valid values per Python signature: "qemu", "kvm", "xenpv", "xenfv", "vmware", +// "vmwarew", "openvz", "auto". +func (c *Client) GetRandomMacFor(virtType string) (string, error) { + if virtType == "" { + virtType = "kvm" + } + result, err := c.Call("get_random_mac", virtType, c.Token) + if err != nil { + return "", err + } + s, ok := result.(string) + if !ok { + return "", fmt.Errorf("get_random_mac returned %T, want string", result) + } + return s, nil } // GetRandomMac generates a random MAC address for use with a virtualized system. -func (c *Client) GetRandomMac() error { - _, err := c.Call("get_random_mac") - return err +func (c *Client) GetRandomMac() (string, error) { + return c.GetRandomMacFor("xenpv") } type StatusOption string diff --git a/cobblerclient_test.go b/cobblerclient_test.go index c628569..e0f78c9 100644 --- a/cobblerclient_test.go +++ b/cobblerclient_test.go @@ -83,7 +83,7 @@ func TestPing(t *testing.T) { func TestAutoAddRepos(t *testing.T) { c := createStubHTTPClientSingle(t, "auto-add-repos") - err := c.AutoAddRepos() + _, err := c.AutoAddRepos() FailOnError(t, err) } @@ -110,7 +110,7 @@ func TestGetAutoinstallSnippets(t *testing.T) { func TestIsAutoinstallInUse(t *testing.T) { c := createStubHTTPClientSingle(t, "is-autoinstall-in-use") - err := c.IsAutoinstallInUse("") + _, err := c.IsAutoinstallInUse("") FailOnError(t, err) } @@ -151,7 +151,7 @@ func TestRegisterNewSystem(t *testing.T) { c := createStubHTTPClientSingle(t, "register-new-system") - err := c.RegisterNewSystem( + _, err := c.RegisterNewSystem( map[string]interface{}{ "name": "test", "profile": "testprof", @@ -168,7 +168,7 @@ func TestRegisterNewSystem(t *testing.T) { func TestRunInstallTriggers(t *testing.T) { c := createStubHTTPClientSingle(t, "run-install-triggers") - err := c.RunInstallTriggers("", "", "", "") + _, err := c.RunInstallTriggers("", "", "", "") FailOnError(t, err) } @@ -178,7 +178,7 @@ func TestGetReposCompatibleWithProfile(t *testing.T) { "get-repos-compatible-with-profile", ) - err := c.GetReposCompatibleWithProfile("testprof") + _, err := c.GetReposCompatibleWithProfile("testprof") FailOnError(t, err) } @@ -188,14 +188,14 @@ func TestFindSystemByDnsName(t *testing.T) { "find-system-by-dns-name", ) - err := c.FindSystemByDnsName("testname") + _, err := c.FindSystemByDnsName("testname") FailOnError(t, err) } func TestGetRandomMac(t *testing.T) { c := createStubHTTPClientSingle(t, "get-random-mac") - err := c.GetRandomMac() + _, err := c.GetRandomMac() FailOnError(t, err) } diff --git a/distro.go b/distro.go index 012677e..c144a6b 100644 --- a/distro.go +++ b/distro.go @@ -347,3 +347,18 @@ func (c *Client) GetDistroHandle(name string) (string, error) { res, err := c.Call("get_distro_handle", name, c.Token) return returnString(res, err) } + +// GetValidDistroBootLoaders retrieves the list of bootloaders that can be assigned to a distro. +func (c *Client) GetValidDistroBootLoaders(distroName string) ([]string, error) { + resultUnmarshalled, err := c.Call("get_valid_distro_boot_loaders", distroName, c.Token) + return returnStringSlice(resultUnmarshalled, err) +} + +// GetDistroAsRendered returns the datastructure after it has passed through Cobblers inheritance structure. +func (c *Client) GetDistroAsRendered(name string) (map[string]interface{}, error) { + result, err := c.Call("get_distro_as_rendered", name, c.Token) + if err != nil { + return nil, err + } + return result.(map[string]interface{}), nil +} diff --git a/distro_test.go b/distro_test.go index dacdcbe..bb2712e 100644 --- a/distro_test.go +++ b/distro_test.go @@ -131,6 +131,26 @@ func TestGetDistroHandle(t *testing.T) { } } +func TestGetValidDistroBootLoaders(t *testing.T) { + c := createStubHTTPClientSingle(t, "get-valid-distro-boot-loaders") + res, err := c.GetValidDistroBootLoaders("Ubuntu-20.04-x86_64") + FailOnError(t, err) + + if len(res) < 1 { + t.Error("Expected at least one boot loader.") + } +} + +func TestGetDistroAsRendered(t *testing.T) { + c := createStubHTTPClientSingle(t, "get-distro-as-rendered") + res, err := c.GetDistroAsRendered("Ubuntu-20.04-x86_64") + FailOnError(t, err) + + if res["name"] != "Ubuntu-20.04-x86_64" { + t.Errorf("Wrong distro name returned: %v", res["name"]) + } +} + /* * NOTE: We're skipping the testing of CREATE, UPDATE, DELETE methods for now because * the current implementation of the StubHTTPClient does not allow diff --git a/fixtures/clear-system-logs-req.xml b/fixtures/clear-system-logs-req.xml new file mode 100644 index 0000000..90df395 --- /dev/null +++ b/fixtures/clear-system-logs-req.xml @@ -0,0 +1,16 @@ + + + clear_system_logs + + + + system::testsys + + + + + securetoken99 + + + + diff --git a/fixtures/clear-system-logs-res.xml b/fixtures/clear-system-logs-res.xml new file mode 100644 index 0000000..d02b2d3 --- /dev/null +++ b/fixtures/clear-system-logs-res.xml @@ -0,0 +1,8 @@ + + + + + 1 + + + diff --git a/fixtures/disable-netboot-req.xml b/fixtures/disable-netboot-req.xml new file mode 100644 index 0000000..a5a5b40 --- /dev/null +++ b/fixtures/disable-netboot-req.xml @@ -0,0 +1,16 @@ + + + disable_netboot + + + + testsys + + + + + securetoken99 + + + + diff --git a/fixtures/disable-netboot-res.xml b/fixtures/disable-netboot-res.xml new file mode 100644 index 0000000..d02b2d3 --- /dev/null +++ b/fixtures/disable-netboot-res.xml @@ -0,0 +1,8 @@ + + + + + 1 + + + diff --git a/fixtures/get-distro-as-rendered-req.xml b/fixtures/get-distro-as-rendered-req.xml new file mode 100644 index 0000000..3560eff --- /dev/null +++ b/fixtures/get-distro-as-rendered-req.xml @@ -0,0 +1,16 @@ + + + get_distro_as_rendered + + + + Ubuntu-20.04-x86_64 + + + + + securetoken99 + + + + diff --git a/fixtures/get-distro-as-rendered-res.xml b/fixtures/get-distro-as-rendered-res.xml new file mode 100644 index 0000000..ae742d7 --- /dev/null +++ b/fixtures/get-distro-as-rendered-res.xml @@ -0,0 +1,17 @@ + + + + + + + + name + + Ubuntu-20.04-x86_64 + + + + + + + diff --git a/fixtures/get-menu-as-rendered-req.xml b/fixtures/get-menu-as-rendered-req.xml new file mode 100644 index 0000000..64d9764 --- /dev/null +++ b/fixtures/get-menu-as-rendered-req.xml @@ -0,0 +1,16 @@ + + + get_menu_as_rendered + + + + testmenu + + + + + securetoken99 + + + + diff --git a/fixtures/get-menu-as-rendered-res.xml b/fixtures/get-menu-as-rendered-res.xml new file mode 100644 index 0000000..fa620b4 --- /dev/null +++ b/fixtures/get-menu-as-rendered-res.xml @@ -0,0 +1,23 @@ + + + + + + + + name + + testmenu + + + + display_name + + + + + + + + + diff --git a/fixtures/get-profile-as-rendered-req.xml b/fixtures/get-profile-as-rendered-req.xml new file mode 100644 index 0000000..b840dc3 --- /dev/null +++ b/fixtures/get-profile-as-rendered-req.xml @@ -0,0 +1,16 @@ + + + get_profile_as_rendered + + + + Ubuntu-20.04-x86_64 + + + + + securetoken99 + + + + diff --git a/fixtures/get-profile-as-rendered-res.xml b/fixtures/get-profile-as-rendered-res.xml new file mode 100644 index 0000000..ae742d7 --- /dev/null +++ b/fixtures/get-profile-as-rendered-res.xml @@ -0,0 +1,17 @@ + + + + + + + + name + + Ubuntu-20.04-x86_64 + + + + + + + diff --git a/fixtures/get-random-mac-req.xml b/fixtures/get-random-mac-req.xml index 2933a15..f1abe30 100644 --- a/fixtures/get-random-mac-req.xml +++ b/fixtures/get-random-mac-req.xml @@ -1,4 +1,8 @@ get_random_mac + + xenpv + securetoken99 + diff --git a/fixtures/get-repo-as-rendered-req.xml b/fixtures/get-repo-as-rendered-req.xml new file mode 100644 index 0000000..0e022cb --- /dev/null +++ b/fixtures/get-repo-as-rendered-req.xml @@ -0,0 +1,16 @@ + + + get_repo_as_rendered + + + + rhel-7-x86_64 + + + + + securetoken99 + + + + diff --git a/fixtures/get-repo-as-rendered-res.xml b/fixtures/get-repo-as-rendered-res.xml new file mode 100644 index 0000000..861db28 --- /dev/null +++ b/fixtures/get-repo-as-rendered-res.xml @@ -0,0 +1,17 @@ + + + + + + + + name + + rhel-7-x86_64 + + + + + + + diff --git a/fixtures/get-repo-config-for-profile-req.xml b/fixtures/get-repo-config-for-profile-req.xml new file mode 100644 index 0000000..3f4e972 --- /dev/null +++ b/fixtures/get-repo-config-for-profile-req.xml @@ -0,0 +1,11 @@ + + + get_repo_config_for_profile + + + + testprof + + + + diff --git a/fixtures/get-repo-config-for-profile-res.xml b/fixtures/get-repo-config-for-profile-res.xml new file mode 100644 index 0000000..580fd99 --- /dev/null +++ b/fixtures/get-repo-config-for-profile-res.xml @@ -0,0 +1,13 @@ + + + + + [testrepo] +name=testrepo +baseurl=http://cobbler.example.com/cobbler/repo_mirror/testrepo +enabled=1 +gpgcheck=0 + + + + diff --git a/fixtures/get-repo-config-for-system-req.xml b/fixtures/get-repo-config-for-system-req.xml new file mode 100644 index 0000000..c0939a7 --- /dev/null +++ b/fixtures/get-repo-config-for-system-req.xml @@ -0,0 +1,11 @@ + + + get_repo_config_for_system + + + + testsys + + + + diff --git a/fixtures/get-repo-config-for-system-res.xml b/fixtures/get-repo-config-for-system-res.xml new file mode 100644 index 0000000..580fd99 --- /dev/null +++ b/fixtures/get-repo-config-for-system-res.xml @@ -0,0 +1,13 @@ + + + + + [testrepo] +name=testrepo +baseurl=http://cobbler.example.com/cobbler/repo_mirror/testrepo +enabled=1 +gpgcheck=0 + + + + diff --git a/fixtures/get-system-as-rendered-req.xml b/fixtures/get-system-as-rendered-req.xml new file mode 100644 index 0000000..aab9ff1 --- /dev/null +++ b/fixtures/get-system-as-rendered-req.xml @@ -0,0 +1,16 @@ + + + get_system_as_rendered + + + + test + + + + + securetoken99 + + + + diff --git a/fixtures/get-system-as-rendered-res.xml b/fixtures/get-system-as-rendered-res.xml new file mode 100644 index 0000000..5abbf94 --- /dev/null +++ b/fixtures/get-system-as-rendered-res.xml @@ -0,0 +1,17 @@ + + + + + + + + name + + test + + + + + + + diff --git a/fixtures/get-valid-distro-boot-loaders-req.xml b/fixtures/get-valid-distro-boot-loaders-req.xml new file mode 100644 index 0000000..fbd2723 --- /dev/null +++ b/fixtures/get-valid-distro-boot-loaders-req.xml @@ -0,0 +1,16 @@ + + + get_valid_distro_boot_loaders + + + + Ubuntu-20.04-x86_64 + + + + + securetoken99 + + + + diff --git a/fixtures/get-valid-distro-boot-loaders-res.xml b/fixtures/get-valid-distro-boot-loaders-res.xml new file mode 100644 index 0000000..ffab829 --- /dev/null +++ b/fixtures/get-valid-distro-boot-loaders-res.xml @@ -0,0 +1,11 @@ + + + + + + grub + pxelinux + + + + diff --git a/fixtures/get-valid-profile-boot-loaders-req.xml b/fixtures/get-valid-profile-boot-loaders-req.xml new file mode 100644 index 0000000..00e9018 --- /dev/null +++ b/fixtures/get-valid-profile-boot-loaders-req.xml @@ -0,0 +1,16 @@ + + + get_valid_profile_boot_loaders + + + + Ubuntu-20.04-x86_64 + + + + + securetoken99 + + + + diff --git a/fixtures/get-valid-profile-boot-loaders-res.xml b/fixtures/get-valid-profile-boot-loaders-res.xml new file mode 100644 index 0000000..ffab829 --- /dev/null +++ b/fixtures/get-valid-profile-boot-loaders-res.xml @@ -0,0 +1,11 @@ + + + + + + grub + pxelinux + + + + diff --git a/fixtures/get-valid-system-boot-loaders-req.xml b/fixtures/get-valid-system-boot-loaders-req.xml new file mode 100644 index 0000000..dcbc0d1 --- /dev/null +++ b/fixtures/get-valid-system-boot-loaders-req.xml @@ -0,0 +1,16 @@ + + + get_valid_system_boot_loaders + + + + test + + + + + securetoken99 + + + + diff --git a/fixtures/get-valid-system-boot-loaders-res.xml b/fixtures/get-valid-system-boot-loaders-res.xml new file mode 100644 index 0000000..ffab829 --- /dev/null +++ b/fixtures/get-valid-system-boot-loaders-res.xml @@ -0,0 +1,11 @@ + + + + + + grub + pxelinux + + + + diff --git a/fixtures/new-subprofile-req.xml b/fixtures/new-subprofile-req.xml new file mode 100644 index 0000000..e0ff742 --- /dev/null +++ b/fixtures/new-subprofile-req.xml @@ -0,0 +1,11 @@ + + + new_subprofile + + + + securetoken99 + + + + diff --git a/fixtures/new-subprofile-res.xml b/fixtures/new-subprofile-res.xml new file mode 100644 index 0000000..025ab6f --- /dev/null +++ b/fixtures/new-subprofile-res.xml @@ -0,0 +1,10 @@ + + + + + + ___NEW___profile::subprof01== + + + + diff --git a/fixtures/upload-log-data-req.xml b/fixtures/upload-log-data-req.xml new file mode 100644 index 0000000..c02f025 --- /dev/null +++ b/fixtures/upload-log-data-req.xml @@ -0,0 +1,36 @@ + + + upload_log_data + + + + testsys + + + + + /var/log/cobbler/testsys.log + + + + + 12 + + + + + 0 + + + + + hello world! + + + + + securetoken99 + + + + diff --git a/fixtures/upload-log-data-res.xml b/fixtures/upload-log-data-res.xml new file mode 100644 index 0000000..d02b2d3 --- /dev/null +++ b/fixtures/upload-log-data-res.xml @@ -0,0 +1,8 @@ + + + + + 1 + + + diff --git a/item.go b/item.go index 04de825..17922d6 100644 --- a/item.go +++ b/item.go @@ -149,10 +149,19 @@ func (c *Client) GetItemNames(what string) ([]string, error) { return returnStringSlice(resultUnmarshalled, err) } -// GetItemResolvedValue retrieves the value of a single attribute of a single item which was passed through the -// inheritance chain of Cobbler. -func (c *Client) GetItemResolvedValue(itemUuid string, attribute string) error { - _, err := c.Call("get_item_resolved_value", itemUuid, attribute) +// GetItemResolvedValue returns the value of a single attribute of a single +// item with the inheritance chain applied. attribute is the dotted path to +// the property (e.g. []string{"ipv4", "address"} for a NetworkInterface). +// Cobbler 4.0.0 returns Union[str, int, float, List, dict]. +func (c *Client) GetItemResolvedValue(itemUuid string, attribute []string) (interface{}, error) { + return c.Call("get_item_resolved_value", itemUuid, attribute) +} + +// SetItemResolvedValue sets a single attribute on an item with inheritance +// rules applied. attribute is the dotted path; value is the desired value. +// Added in Cobbler 4.0.0. +func (c *Client) SetItemResolvedValue(itemUuid string, attribute []string, value interface{}) error { + _, err := c.Call("set_item_resolved_value", itemUuid, attribute, value, c.Token) return err } diff --git a/menu.go b/menu.go index 15966ea..afdd201 100644 --- a/menu.go +++ b/menu.go @@ -93,13 +93,13 @@ func convertRawMenusList(xmlrpcResult interface{}) ([]*Menu, error) { } // GetMenus returns all menus in Cobbler. -func (c *Client) GetMenus() ([]*Distro, error) { +func (c *Client) GetMenus() ([]*Menu, error) { result, err := c.Call("get_menus", "-1", c.Token) if err != nil { return nil, err } - return convertRawDistrosList(result) + return convertRawMenusList(result) } // GetMenu returns a single menu obtained by its name. @@ -234,9 +234,12 @@ func (c *Client) GetMenusSince(mtime time.Time) ([]*Menu, error) { } // GetMenuAsRendered returns the datastructure after it has passed through Cobblers inheritance structure. -func (c *Client) GetMenuAsRendered() error { - _, err := c.Call("get_menu_as_rendered") - return err +func (c *Client) GetMenuAsRendered(name string) (map[string]interface{}, error) { + result, err := c.Call("get_menu_as_rendered", name, c.Token) + if err != nil { + return nil, err + } + return result.(map[string]interface{}), nil } // SaveMenu saves all changes performed via XML-RPC to disk on the server side. diff --git a/menu_test.go b/menu_test.go index bb5e5df..f24ecc3 100644 --- a/menu_test.go +++ b/menu_test.go @@ -135,6 +135,16 @@ func TestGetMenuHandle(t *testing.T) { } } +func TestGetMenuAsRendered(t *testing.T) { + c := createStubHTTPClientSingle(t, "get-menu-as-rendered") + res, err := c.GetMenuAsRendered("testmenu") + FailOnError(t, err) + + if res["name"] != "testmenu" { + t.Errorf("Wrong menu name returned: %v", res["name"]) + } +} + /* * NOTE: We're skipping the testing of CREATE, UPDATE, DELETE methods for now because * the current implementation of the StubHTTPClient does not allow diff --git a/profile.go b/profile.go index 82175ff..eb948d0 100644 --- a/profile.go +++ b/profile.go @@ -355,3 +355,25 @@ func (c *Client) GetProfileHandle(name string) (string, error) { res, err := c.Call("get_profile_handle", name, c.Token) return returnString(res, err) } + +// GetValidProfileBootLoaders retrieves the list of bootloaders that can be assigned to a profile. +func (c *Client) GetValidProfileBootLoaders(profileName string) ([]string, error) { + resultUnmarshalled, err := c.Call("get_valid_profile_boot_loaders", profileName, c.Token) + return returnStringSlice(resultUnmarshalled, err) +} + +// GetProfileAsRendered returns the datastructure after it has passed through Cobblers inheritance structure. +func (c *Client) GetProfileAsRendered(name string) (map[string]interface{}, error) { + result, err := c.Call("get_profile_as_rendered", name, c.Token) + if err != nil { + return nil, err + } + return result.(map[string]interface{}), nil +} + +// NewSubprofile creates a new blank sub-profile on the server and returns its object ID. +// A sub-profile inherits from another profile (rather than a distro). +func (c *Client) NewSubprofile() (string, error) { + result, err := c.Call("new_subprofile", c.Token) + return returnString(result, err) +} diff --git a/profile_test.go b/profile_test.go index 0e666c9..3b7283e 100644 --- a/profile_test.go +++ b/profile_test.go @@ -134,3 +134,32 @@ func TestGetProfileHandle(t *testing.T) { t.Error("Wrong object id returned.") } } + +func TestGetValidProfileBootLoaders(t *testing.T) { + c := createStubHTTPClientSingle(t, "get-valid-profile-boot-loaders") + res, err := c.GetValidProfileBootLoaders("Ubuntu-20.04-x86_64") + FailOnError(t, err) + + if len(res) < 1 { + t.Error("Expected at least one boot loader.") + } +} + +func TestGetProfileAsRendered(t *testing.T) { + c := createStubHTTPClientSingle(t, "get-profile-as-rendered") + res, err := c.GetProfileAsRendered("Ubuntu-20.04-x86_64") + FailOnError(t, err) + + if res["name"] != "Ubuntu-20.04-x86_64" { + t.Errorf("Wrong profile name returned: %v", res["name"]) + } +} + +func TestNewSubprofile(t *testing.T) { + c := createStubHTTPClientSingle(t, "new-subprofile") + res, err := c.NewSubprofile() + FailOnError(t, err) + if res == "" { + t.Error("Expected a non-empty object ID from NewSubprofile.") + } +} diff --git a/repo.go b/repo.go index 644d501..53c5398 100644 --- a/repo.go +++ b/repo.go @@ -270,3 +270,24 @@ func (c *Client) GetRepoHandle(name string) (string, error) { res, err := c.Call("get_repo_handle", name, c.Token) return returnString(res, err) } + +// GetRepoConfigForProfile returns the rendered repository configuration for a profile. +func (c *Client) GetRepoConfigForProfile(profileName string) (string, error) { + result, err := c.Call("get_repo_config_for_profile", profileName) + return returnString(result, err) +} + +// GetRepoConfigForSystem returns the rendered repository configuration for a system. +func (c *Client) GetRepoConfigForSystem(systemName string) (string, error) { + result, err := c.Call("get_repo_config_for_system", systemName) + return returnString(result, err) +} + +// GetRepoAsRendered returns the datastructure after it has passed through Cobblers inheritance structure. +func (c *Client) GetRepoAsRendered(name string) (map[string]interface{}, error) { + result, err := c.Call("get_repo_as_rendered", name, c.Token) + if err != nil { + return nil, err + } + return result.(map[string]interface{}), nil +} diff --git a/repo_test.go b/repo_test.go index 7dda63b..130bacc 100644 --- a/repo_test.go +++ b/repo_test.go @@ -165,6 +165,36 @@ func TestGetRepoHandle(t *testing.T) { } } +func TestGetRepoConfigForProfile(t *testing.T) { + c := createStubHTTPClientSingle(t, "get-repo-config-for-profile") + res, err := c.GetRepoConfigForProfile("testprof") + FailOnError(t, err) + + if res == "" { + t.Error("Expected a non-empty repo config.") + } +} + +func TestGetRepoConfigForSystem(t *testing.T) { + c := createStubHTTPClientSingle(t, "get-repo-config-for-system") + res, err := c.GetRepoConfigForSystem("testsys") + FailOnError(t, err) + + if res == "" { + t.Error("Expected a non-empty repo config.") + } +} + +func TestGetRepoAsRendered(t *testing.T) { + c := createStubHTTPClientSingle(t, "get-repo-as-rendered") + res, err := c.GetRepoAsRendered("rhel-7-x86_64") + FailOnError(t, err) + + if res["name"] != "rhel-7-x86_64" { + t.Errorf("Wrong repo name returned: %v", res["name"]) + } +} + /* * NOTE: We're skipping the testing of CREATE, UPDATE, DELETE methods for now because * the current implementation of the StubHTTPClient does not allow diff --git a/system.go b/system.go index fef2e7d..936cb3d 100644 --- a/system.go +++ b/system.go @@ -591,3 +591,36 @@ func (c *Client) GetSystemHandle(name string) (string, error) { res, err := c.Call("get_system_handle", name, c.Token) return returnString(res, err) } + +// DisableNetboot disables PXE booting for the named system (pxe_just_once feature). +func (c *Client) DisableNetboot(name string) error { + _, err := c.Call("disable_netboot", name, c.Token) + return err +} + +// UploadLogData uploads Anaconda log data for the named system (anamon logging). +func (c *Client) UploadLogData(sysName, file string, size, offset int, data string) (bool, error) { + result, err := c.Call("upload_log_data", sysName, file, size, offset, data, c.Token) + return returnBool(result, err) +} + +// ClearSystemLogs clears the console logs for the system identified by its object ID. +func (c *Client) ClearSystemLogs(objectId string) (bool, error) { + result, err := c.Call("clear_system_logs", objectId, c.Token) + return returnBool(result, err) +} + +// GetValidSystemBootLoaders retrieves the list of bootloaders that can be assigned to a system. +func (c *Client) GetValidSystemBootLoaders(systemName string) ([]string, error) { + resultUnmarshalled, err := c.Call("get_valid_system_boot_loaders", systemName, c.Token) + return returnStringSlice(resultUnmarshalled, err) +} + +// GetSystemAsRendered returns the datastructure after it has passed through Cobblers inheritance structure. +func (c *Client) GetSystemAsRendered(name string) (map[string]interface{}, error) { + result, err := c.Call("get_system_as_rendered", name, c.Token) + if err != nil { + return nil, err + } + return result.(map[string]interface{}), nil +} diff --git a/system_test.go b/system_test.go index a2e8d68..e618658 100644 --- a/system_test.go +++ b/system_test.go @@ -248,6 +248,26 @@ func TestModifyInterface(t *testing.T) { FailOnError(t, err) } +func TestGetValidSystemBootLoaders(t *testing.T) { + c := createStubHTTPClientSingle(t, "get-valid-system-boot-loaders") + res, err := c.GetValidSystemBootLoaders("test") + FailOnError(t, err) + + if len(res) < 1 { + t.Error("Expected at least one boot loader.") + } +} + +func TestGetSystemAsRendered(t *testing.T) { + c := createStubHTTPClientSingle(t, "get-system-as-rendered") + res, err := c.GetSystemAsRendered("test") + FailOnError(t, err) + + if res["name"] != "test" { + t.Errorf("Wrong system name returned: %v", res["name"]) + } +} + func TestGetInterfaces(t *testing.T) { // Arrange c := createStubHTTPClient(t, []string{ @@ -329,3 +349,27 @@ func TestRenameInterface(t *testing.T) { // Assert FailOnError(t, err) } + +func TestDisableNetboot(t *testing.T) { + c := createStubHTTPClientSingle(t, "disable-netboot") + err := c.DisableNetboot("testsys") + FailOnError(t, err) +} + +func TestUploadLogData(t *testing.T) { + c := createStubHTTPClientSingle(t, "upload-log-data") + res, err := c.UploadLogData("testsys", "/var/log/cobbler/testsys.log", 12, 0, "hello world!") + FailOnError(t, err) + if !res { + t.Error("Expected true result from UploadLogData.") + } +} + +func TestClearSystemLogs(t *testing.T) { + c := createStubHTTPClientSingle(t, "clear-system-logs") + res, err := c.ClearSystemLogs("system::testsys") + FailOnError(t, err) + if !res { + t.Error("Expected true result from ClearSystemLogs.") + } +}