cli: support explicitly selecting team-config as file or json data
nmcli has a heuristic when setting the team-config to accepting both a filename or the plain json text. Add support for two schemes "file://" and "json://" to explicitly determine whether to read from file or from json. Also, no longer silently ignore an all-whitespace word. That is an error (unless you have a file named " "). Also, no longer replace newlines with space. Don't mangle the input text at all.
This commit is contained in:
@@ -826,10 +826,11 @@ nmc_bond_validate_mode (const char *mode, GError **error)
|
|||||||
/*
|
/*
|
||||||
* nmc_team_check_config:
|
* nmc_team_check_config:
|
||||||
* @config: file name with team config, or raw team JSON config data
|
* @config: file name with team config, or raw team JSON config data
|
||||||
* @out_config: raw team JSON config data (with removed new-line characters)
|
* @out_config: raw team JSON config data
|
||||||
|
* The value must be freed with g_free().
|
||||||
* @error: location to store error, or %NUL
|
* @error: location to store error, or %NUL
|
||||||
*
|
*
|
||||||
* Check team config from @config parameter and return the checked/sanitized
|
* Check team config from @config parameter and return the checked
|
||||||
* config in @out_config.
|
* config in @out_config.
|
||||||
*
|
*
|
||||||
* Returns: %TRUE if the config is valid, %FALSE if it is invalid
|
* Returns: %TRUE if the config is valid, %FALSE if it is invalid
|
||||||
@@ -837,33 +838,58 @@ nmc_bond_validate_mode (const char *mode, GError **error)
|
|||||||
gboolean
|
gboolean
|
||||||
nmc_team_check_config (const char *config, char **out_config, GError **error)
|
nmc_team_check_config (const char *config, char **out_config, GError **error)
|
||||||
{
|
{
|
||||||
char *contents = NULL;
|
enum {
|
||||||
|
_TEAM_CONFIG_TYPE_GUESS,
|
||||||
|
_TEAM_CONFIG_TYPE_FILE,
|
||||||
|
_TEAM_CONFIG_TYPE_JSON,
|
||||||
|
} desired_type = _TEAM_CONFIG_TYPE_GUESS;
|
||||||
|
const char *filename = NULL;
|
||||||
size_t c_len = 0;
|
size_t c_len = 0;
|
||||||
|
gs_free char *config_clone = NULL;
|
||||||
|
|
||||||
*out_config = NULL;
|
*out_config = NULL;
|
||||||
|
|
||||||
if (!config || strlen (config) == strspn (config, " \t"))
|
if (!config || !config[0])
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* 'config' can be either a file name or raw JSON config data */
|
if (g_str_has_prefix (config, "file://")) {
|
||||||
if (g_file_test (config, G_FILE_TEST_EXISTS))
|
config += NM_STRLEN ("file://");
|
||||||
(void) g_file_get_contents (config, &contents, NULL, NULL);
|
desired_type = _TEAM_CONFIG_TYPE_FILE;
|
||||||
else
|
} else if (g_str_has_prefix (config, "json://")) {
|
||||||
contents = g_strdup (config);
|
config += NM_STRLEN ("json://");
|
||||||
|
desired_type = _TEAM_CONFIG_TYPE_JSON;
|
||||||
if (contents) {
|
|
||||||
g_strstrip (contents);
|
|
||||||
c_len = strlen (contents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do a simple validity check */
|
if (NM_IN_SET (desired_type, _TEAM_CONFIG_TYPE_FILE, _TEAM_CONFIG_TYPE_GUESS)) {
|
||||||
if (!contents || !contents[0] || c_len > 100000 || contents[0] != '{' || contents[c_len-1] != '}') {
|
gs_free char *contents = NULL;
|
||||||
|
|
||||||
|
if (!g_file_get_contents (config, &contents, &c_len, NULL)) {
|
||||||
|
if (desired_type == _TEAM_CONFIG_TYPE_FILE) {
|
||||||
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
|
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
|
||||||
_("'%s' is not a valid team configuration or file name."), config);
|
_("cannot read team config from file '%s'"),
|
||||||
g_free (contents);
|
config);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
*out_config = g_strdelimit (contents, "\r\n", ' ');
|
} else {
|
||||||
|
filename = config;
|
||||||
|
config = config_clone = g_steal_pointer (&contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_utils_is_json_object (config, NULL)) {
|
||||||
|
if (filename) {
|
||||||
|
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
|
||||||
|
_("'%s' does not contain a valid team configuration"), filename);
|
||||||
|
} else {
|
||||||
|
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
|
||||||
|
_("team configuration must be a JSON object"));
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_config = (config == config_clone)
|
||||||
|
? g_steal_pointer (&config_clone)
|
||||||
|
: g_strdup (config);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1827,21 +1827,25 @@ It's equivalent of using the <literal>+bond.options 'option=value'</literal> syn
|
|||||||
</tbody>
|
</tbody>
|
||||||
</tgroup></table>
|
</tgroup></table>
|
||||||
|
|
||||||
<table><title>Team options</title><tgroup cols="2">
|
<table><title>Team options</title><tgroup cols="3">
|
||||||
<thead>
|
<thead>
|
||||||
<row><entry>Alias</entry><entry>Property</entry></row>
|
<row><entry>Alias</entry><entry>Property</entry><entry>Note</entry></row>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<row><entry align="left">config</entry><entry align="left"><link linkend="nm-settings.property.team.config">team.config</link></entry></row>
|
<row><entry align="left">config</entry><entry align="left"><link linkend="nm-settings.property.team.config">team.config</link></entry>
|
||||||
|
<entry align="left">Either a filename or a team configuration in JSON format. To enforce one or the other, the value can be prefixed with "file://" or "json://".</entry>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup></table>
|
</tgroup></table>
|
||||||
|
|
||||||
<table><title>Team port options</title><tgroup cols="2">
|
<table><title>Team port options</title><tgroup cols="3">
|
||||||
<thead>
|
<thead>
|
||||||
<row><entry>Alias</entry><entry>Property</entry></row>
|
<row><entry>Alias</entry><entry>Property</entry><entry>Note</entry></row>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<row><entry align="left">config</entry><entry align="left"><link linkend="nm-settings.property.team-port.config">team-port.config</link></entry></row>
|
<row><entry align="left">config</entry><entry align="left"><link linkend="nm-settings.property.team-port.config">team-port.config</link></entry>
|
||||||
|
<entry align="left">Either a filename or a team configuration in JSON format. To enforce one or the other, the value can be prefixed with "file://" or "json://".</entry>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup></table>
|
</tgroup></table>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user