Remove wwctl node import --csv

- Closes #1862

Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
Jonathon Anderson
2025-07-02 21:25:54 -06:00
parent 1d3f0095fa
commit 2ba6e28215
4 changed files with 19 additions and 108 deletions

View File

@@ -39,6 +39,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Removed ### Removed
- Removed the gRPC API servers and client. #1876 - Removed the gRPC API servers and client. #1876
- Removed ``wwctl node import --csv``. #1862
## v4.6.1, 2025-04-04 ## v4.6.1, 2025-04-04

View File

@@ -1,8 +1,6 @@
package imprt package imprt
import ( import (
"bytes"
"encoding/csv"
"fmt" "fmt"
"io" "io"
"os" "os"
@@ -27,58 +25,18 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
if err != nil { if err != nil {
return fmt.Errorf("could not read: %s", err) return fmt.Errorf("could not read: %s", err)
} }
if !ImportCSV {
err = yaml.Unmarshal(buffer, importMap) err = yaml.Unmarshal(buffer, importMap)
if err == nil { if err != nil {
return fmt.Errorf("could not parse import file: %s", err)
}
if setYes || util.Confirm(fmt.Sprintf("Are you sure you want to modify %d nodes", len(importMap))) { if setYes || util.Confirm(fmt.Sprintf("Are you sure you want to modify %d nodes", len(importMap))) {
err = apinode.NodeAddFromYaml(&wwapiv1.NodeYaml{NodeConfMapYaml: string(buffer)}) err = apinode.NodeAddFromYaml(&wwapiv1.NodeYaml{NodeConfMapYaml: string(buffer)})
if err != nil { if err != nil {
return fmt.Errorf("got following problem when writing back yaml: %s", err) return fmt.Errorf("got following problem when writing back yaml: %s", err)
} }
} }
} else {
return fmt.Errorf("could not parse import file: %s", err)
}
} else {
// reading from buffer is a bit overshot
csvReader := csv.NewReader(bytes.NewReader(buffer))
records, err := csvReader.ReadAll()
if err != nil {
return fmt.Errorf("could not parse %s: %s", args[0], err)
}
if len(records) < 1 || len(records[0]) < 1 {
return fmt.Errorf("did not find any data in %s", args[0])
}
if !(records[0][0] == "node" || records[0][0] == "nodename") {
Usage()
os.Exit(1)
}
argsLen := len(records[0])
for i, line := range records[1:] {
if len(line) != argsLen {
return fmt.Errorf("wrong number of fields in lube %d", i+1)
}
for j := range line {
if j == 0 {
continue
}
if importMap[line[0]] == nil {
importMap[line[0]] = new(node.Node)
}
}
}
if setYes || util.Confirm(fmt.Sprintf("Are you sure you want to import %d nodes", len(importMap))) {
// create second buffer an marshall nodeMap to it
buffer, err = yaml.Marshal(importMap)
if err != nil {
return fmt.Errorf("got following problem when creating yaml: %s", err)
}
err = apinode.NodeAddFromYaml(&wwapiv1.NodeYaml{NodeConfMapYaml: string(buffer)})
if err != nil {
return fmt.Errorf("got following problem when writing back yaml: %s", err)
}
}
}
return nil return nil
} }

View File

@@ -1,8 +1,6 @@
package imprt package imprt
import ( import (
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -11,22 +9,15 @@ var (
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
Use: "import [OPTIONS] FILE", Use: "import [OPTIONS] FILE",
Short: "Import node(s) from yaml FILE", Short: "Import node(s) from yaml FILE",
Long: "This command imports all the nodes defined in a file. It will overwrite nodes with same name.", Long: "This command imports all the nodes defined in a YAML file. It will overwrite nodes with same name.",
RunE: CobraRunE, RunE: CobraRunE,
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
Aliases: []string{"import"}, Aliases: []string{"import"},
} }
ImportCSV bool
setYes bool setYes bool
) )
func init() { func init() {
baseCmd.PersistentFlags().BoolVarP(&ImportCSV, "csv", "c", false, "Import CSV file")
baseCmd.Flags().BoolVar(&ImportCSV, "cvs", false, "Import CSV file")
baseCmd.Flags().Lookup("cvs").Hidden = true
if err := baseCmd.Flags().MarkDeprecated("cvs", "use --csv instead"); err != nil {
panic(err)
}
baseCmd.PersistentFlags().BoolVarP(&setYes, "yes", "y", false, "Set 'yes' to all questions asked") baseCmd.PersistentFlags().BoolVarP(&setYes, "yes", "y", false, "Set 'yes' to all questions asked")
} }
@@ -34,9 +25,3 @@ func init() {
func GetCommand() *cobra.Command { func GetCommand() *cobra.Command {
return baseCmd return baseCmd
} }
func Usage() {
fmt.Println(`The csv file must be structured in following way:
node,option1,option2,net.netname1.netopt
node01,value1,value2,net.netname1,netvalue`)
}

View File

@@ -203,47 +203,14 @@ Resources can only be managed with ``wwctl node edit``.
Importing Nodes From a File Importing Nodes From a File
=========================== ===========================
You can import nodes into Warewulf by using the ``wwctl node import`` command. The You can import nodes into Warewulf by using the ``wwctl node import`` command.
file used must be in YAML or CSV format. The file used must be in YAML format.
.. warning:: The YAML file must be a mapping of node names to their attributes, where each
Importing a node configuration will fully overwrite the existing settings, node is represented as a dictionary of attributes. To simplify the creation of
including any customizations not present in the import file. If the node the YAML file, you can use the wwctl node export command to export the current
already exists and you wish to update it, ensure that the import file node configuration to a YAML file. This exported file can serve as a template
includes all the options you want to retain. for creating new nodes.
CSV Import
----------
.. note::
As of Warewulf v4.6.1, the csv import functionality is broken and an
`issue <https://github.com/warewulf/warewulf/issues/1862>`_
has been created to track this.
The CSV file must have a header where the first field must always be the nodename,
and the rest of the fields are the same as the long commandline options. Network
device must have the form ``net.$NETNAME.$NETOPTION``. (e.g., ``net.default.ipaddr``).
Tags are currently not supported and must be added separately after the import.
As an example, the following CSV file:
.. code-block:: csv
nodename,net.default.hwaddr,net.default.ipaddr,net.default.netmask,net.default.gateway,discoverable,image
n1,00:00:00:00:00:01,10.0.2.1,255.255.255.0,10.0.2.254,false,rockylinux-9
This can be imported with the following command:
.. code-block:: shell
wwctl node import --csv /path/to/nodes.csv
YAML Import
-----------
The YAML file must be a mapping of node names to their attributes, where each node is represented as a dictionary of attributes.
To simplify the creation of the YAML file, you can use the wwctl node export command to export the current node configuration to a YAML file.
This exported file can serve as a template for creating new nodes.
A minimal example of a YAML file looks like this: A minimal example of a YAML file looks like this: