Change-Id: Id87bf2700e6ddc9183e924f8c9cf6b9f53a44baa Signed-off-by: Artem Goncharov <artem.goncharov@gmail.com>
582 lines
24 KiB
Django/Jinja
582 lines
24 KiB
Django/Jinja
{%- macro mod_docstring(v) %}
|
|
{%- if v %}
|
|
//! {{ v | wrap_markdown(75) | replace('\n', '\n//! ') }}
|
|
{%- endif %}
|
|
{%- endmacro %}
|
|
|
|
{%- macro docstring(doc, indent=0) %}
|
|
{#- docstring for an element #}
|
|
{%- if doc %}
|
|
{{ (' ' * indent) }}/// {{ doc | wrap_markdown(79-indent-4) | trim("\n") | replace('\n', '\n' + (' ' * indent) + '/// ') }}
|
|
{%- endif %}
|
|
{%- endmacro %}
|
|
|
|
{%- macro serde_args(k, attr) -%}
|
|
{%- set serde_args=[
|
|
('rename = "' + attr.name + '"') if attr.name != k else None,
|
|
'deserialize_with="deser_ok_or_default"' if attr.default is not none and (attr.min_version is none and
|
|
attr.max_version is none) else None,
|
|
'default' if (attr.min_version is not none or
|
|
attr.max_version is not none) else None
|
|
] -%}
|
|
{{ serde_args | reject("none") | join(',') }}
|
|
{%- endmacro %}
|
|
|
|
{%- macro arg_raw_type(attr) %}
|
|
{%- if attr.type.__name__ == "str" or attr.type is none -%}
|
|
String
|
|
{%- elif attr.type.__name__ == "int" -%}
|
|
i32
|
|
{%- elif attr.type.__name__ == "float" -%}
|
|
f32
|
|
{%- elif attr.type.__name__ == "bool" -%}
|
|
bool
|
|
{%- elif attr.type.__name__ == "dict" -%}
|
|
HashMapStringString
|
|
{%- endif %}
|
|
{%- endmacro %}
|
|
|
|
{%- macro arg_type(k, attr) %}
|
|
{%- if attr.min_version is not none or attr.max_version is not none -%}
|
|
Option
|
|
{%- endif -%}
|
|
{{ arg_raw_type(attr) }}
|
|
{%- endmacro %}
|
|
|
|
{%- macro struct_field(k, v) %}
|
|
{%- set attr=v['attr'] %}
|
|
{%- if attr.type is none or attr.type.__name__ in
|
|
["str", "int", "float", "bool", "dict"]
|
|
%}
|
|
{{ docstring(v) }}
|
|
#[structable()]
|
|
#[serde({{ serde_args(k, attr) }})]
|
|
{{ k }}: {{ arg_type(k, attr) }},
|
|
{%- endif %}
|
|
{%- endmacro %}
|
|
|
|
{%- macro cli_arg_params(params) %}
|
|
{%- for param in params %}
|
|
{%- if param.schema.type != "null" %}
|
|
{{ docstring(param.description, indent=4) }}
|
|
{%- for macros in param.param_macros %}
|
|
{{ macros }}
|
|
{%- endfor %}
|
|
{{ param.local_name }}: {{ param.type }},
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
{%- endmacro %}
|
|
|
|
{%- macro sdk_builder_setter_btreemap(field) %}
|
|
{%- set is_opt = False if field.data_type.__class__.__name__ != "Option" else True %}
|
|
{%- set dt = field.data_type if not is_opt else field.data_type.item_type %}
|
|
{%- set val_type = field.data_type.value_type %}
|
|
{{ docstring(field.description, indent=4) }}
|
|
pub fn {{ field.local_name }}<I, K, V
|
|
{%- if val_type.__class__.__name__ == "BTreeMap" -%}
|
|
, K1, V1
|
|
{%- elif val_type.__class__.__name__ == "Array" -%}
|
|
, V1
|
|
{%- endif -%}
|
|
>(&mut self, iter: I) -> &mut Self
|
|
where
|
|
I: Iterator<Item = (K, V)>,
|
|
K: Into<Cow<'a, str>>,
|
|
{%- if val_type.__class__.__name__ == "BTreeMap" %}
|
|
V: Iterator<Item = (K1, V1)>,
|
|
K1: Into<Cow<'a, str>>,
|
|
V1: Into<{{ val_type.value_type.type_hint }}>,
|
|
{%- elif val_type.__class__.__name__ == "Array" %}
|
|
V: IntoIterator<Item = V1>,
|
|
V1: Into<{{ val_type.item_type.type_hint }}>,
|
|
{% else %}
|
|
V: Into<{{ dt.value_type.type_hint }}>,
|
|
{% endif%}
|
|
{
|
|
self.{{ field.local_name }}
|
|
{%- if field.is_optional %}
|
|
.get_or_insert(None)
|
|
{%- endif %}
|
|
{%- if is_opt %}
|
|
.get_or_insert(None)
|
|
{%- endif %}
|
|
.get_or_insert_with(BTreeMap::new)
|
|
.extend(iter.map(|(k, v)| (
|
|
k.into(),
|
|
{%- if val_type.__class__.__name__ == "BTreeMap" %}
|
|
BTreeMap::from_iter(
|
|
v.into_iter()
|
|
.map(|(k1, v1)| {(k1.into(), v1.into())})
|
|
)
|
|
{%- elif val_type.__class__.__name__ == "Array" %}
|
|
v.into_iter().map(Into::into).collect()
|
|
{%- else %}
|
|
v.into()
|
|
{%- endif %}
|
|
)));
|
|
self
|
|
}
|
|
{%- endmacro %}
|
|
|
|
{%- macro sdk_builder_setter_btreeset(field) %}
|
|
{%- set is_opt = False if field.data_type.__class__.__name__ != "Option" else True %}
|
|
{%- set dt = field.data_type if not is_opt else field.data_type.item_type %}
|
|
{{ macros.docstring(field.description, indent=4) }}
|
|
pub fn {{ field.local_name }}<I, T>(&mut self, iter: I) -> &mut Self
|
|
where
|
|
I: Iterator<Item = T>,
|
|
V: Into<{{ dt.item_type.type_hint }}>,
|
|
{
|
|
self.{{ field.local_name }}
|
|
.get_or_insert_with(BTreeSet::new)
|
|
.extend(iter.map(Into::into));
|
|
self
|
|
}
|
|
{%- endmacro %}
|
|
|
|
{%- macro sdk_builder_setter_vec_vec(field) %}
|
|
{%- set is_opt = False if field.data_type.__class__.__name__ != "Option" else True %}
|
|
{%- set dt = field.data_type if not is_opt else field.data_type.item_type %}
|
|
{{ macros.docstring(field.description, indent=4) }}
|
|
pub fn {{ field.local_name }}<I1, I2, V>(&mut self, iter: I1) -> &mut Self
|
|
where
|
|
I1: Iterator<Item = I2>,
|
|
I2: IntoIterator<Item = V>,
|
|
V: Into<{{ dt.item_type.item_type.type_hint }}>,
|
|
{
|
|
self.{{ field.local_name }}
|
|
{%- if field.is_optional %}
|
|
.get_or_insert(None)
|
|
{%- endif %}
|
|
.get_or_insert_with(Vec::new)
|
|
.extend(
|
|
iter.map(|x| Vec::from_iter(x.into_iter().map(Into::into)))
|
|
);
|
|
self
|
|
}
|
|
{%- endmacro %}
|
|
|
|
{#- Create DeriveBuilder setter method #}
|
|
{%- macro sdk_builder_setter(field) %}
|
|
{%- set dtc = field.data_type.__class__.__name__ %}
|
|
{%- set subdtc = field.data_type.item_type.__class__.__name__ %}
|
|
{%- if dtc == "BTreeMap" or subdtc == "BTreeMap" %}
|
|
{{ sdk_builder_setter_btreemap(field) }}
|
|
{%- elif dtc == "BTreeSet" or subdtc == "BTreeSet" %}
|
|
{{ sdk_builder_setter_btreeset(field) }}
|
|
{%- elif dtc == "Array" and subdtc == "Array" %}
|
|
{{ sdk_builder_setter_vec_vec(field) }}
|
|
{%- endif %}
|
|
{%- endmacro %}
|
|
|
|
{%- macro wrap_optional(val, is_nullable) %}
|
|
{%- if is_nullable is defined and is_nullable -%}
|
|
Some({{ val }})
|
|
{%- else -%}
|
|
{{ val }}
|
|
{%- endif -%}
|
|
{%- endmacro %}
|
|
|
|
{#- Macros to render setting Request data from CLI input #}
|
|
{%- macro set_request_data_from_input(manager, dst_var, param, val_var, by_ref=False) %}
|
|
{%- set is_nullable = param.is_nullable if param.is_nullable is defined else False %}
|
|
{%- if param.type_hint in ["Option<Option<bool>>", "Option<Option<i32>>", "Option<Option<i64>>"] %}
|
|
{{ dst_var }}.{{ param.remote_name }}({{ ("*" + val_var) if not by_ref else (val + ".clone()") }});
|
|
|
|
{%- elif param.type_hint in ["Option<i32>", "Option<i64>", "Option<f32>", "Option<f64>", "Option<bool>"] %}
|
|
{%- if param.is_optional is defined and not param.is_optional %}
|
|
if let Some(val) = {{ val_var }} {
|
|
{{ dst_var }}.{{ param.remote_name }}({{ "*val" if not by_ref else "val.clone()" }});
|
|
}
|
|
{%- else %}
|
|
{{ dst_var }}.{{ param.remote_name }}({{ ("*" + val_var) if not by_ref else (val_var + ".clone()") }});
|
|
{%- endif %}
|
|
|
|
{%- elif param.type_hint in ["i32", "i64", "f32", "f64", "bool"] %}
|
|
{{ dst_var }}.{{ param.remote_name }}({{ val_var | replace("&", "" )}});
|
|
|
|
{%- elif param.data_type.__class__.__name__ in ["ArrayInput"] %}
|
|
{{ sdk_plain_array_setter(param, val_var.replace("&", ""), dst_var, by_ref=by_ref) }}
|
|
|
|
{%- elif param.data_type.__class__.__name__ in ["JsonValue"] %}
|
|
|
|
{%- set original_type = param.data_type.original_data_type %}
|
|
{%- if original_type and original_type.__class__.__name__ == "StructInput" %}
|
|
{#- from_value needs value and not the ref #}
|
|
{{ dst_var }}.{{ param.remote_name }}(
|
|
serde_json::from_value::<{{ sdk_mod_path[-1] }}::{{ original_type.name }}>({{ val_var }}.to_owned())?
|
|
);
|
|
{%- elif original_type and original_type.__class__.__name__ == "DictionaryInput" and original_type.value_type and original_type.value_type.__class__.__name__ == "DictionaryInput" %}
|
|
{{ dst_var }}.{{ param.remote_name }}(
|
|
serde_json::from_value::<BTreeMap<String, BTreeMap<String, {{ original_type.value_type.value_type.type_hint }}>>>({{ val_var | replace("&", "") }}.clone())
|
|
.wrap_err_with(|| "Failed to parse `{{ param.local_name }}` as dict of dicts of {{ original_type.value_type.value_type.type_hint }}")?
|
|
.into_iter()
|
|
.map(|(k, v)| (k, v.into_iter())),
|
|
);
|
|
{%- else %}
|
|
{{ dst_var }}.{{ param.remote_name }}({{ val_var | replace("&", "" )}}.clone());
|
|
{%- endif %}
|
|
|
|
{%- elif param.data_type.__class__.__name__ == "DictionaryInput" %}
|
|
{{ dictionary_setter(param, val_var, dst_var) }}
|
|
|
|
{%- elif param.data_type.__class__.__name__ == "StringEnum" %}
|
|
let tmp = match {{ val_var }} {
|
|
{%- for variant in param.data_type.variants.keys() | sort %}
|
|
{#- normally we should use the cli enum name, but we don't have it here and names must match anyway#}
|
|
{{ param.data_type.name }}::{{ variant }} => {
|
|
{{ sdk_mod_path[-1] }}::{{ param.data_type.name }}::{{ variant }}
|
|
}
|
|
{%- endfor %}
|
|
};
|
|
{{ dst_var }}.{{ param.remote_name }}(tmp);
|
|
|
|
{%- elif param.data_type.__class__.__name__ == "EnumGroupStruct" %}
|
|
{#- This is a reverse action of Complex SDK enum being converted into the CLI group #}
|
|
{%- for k, v in param.data_type.fields | dictsort %}
|
|
{%- if v.data_type.__class__.__name__ in ["Boolean", "BooleanFlag"] %}
|
|
if {{ val_var | replace("&", "") }}.{{ v.local_name }} {
|
|
{{ dst_var }}.{{ param.remote_name }}(
|
|
{{ sdk_mod_path[-1] }}::{{ param.data_type.name }}::{{ v.sdk_parent_enum_variant }}(
|
|
{{ sdk_mod_path[-1] }}::{{ v.remote_name }}
|
|
)
|
|
);
|
|
}
|
|
{%- elif v.data_type.__class__.__name__ == "ArrayInput" %}
|
|
{% set original_type = v.data_type.original_item_type %}
|
|
if let Some(data) = {{ val_var }}.{{ v.local_name }} {
|
|
{{ sdk_enum_array_setter(manager, param, v, "data", dst_var) }}
|
|
}
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
|
|
{%- elif param.data_type.__class__.__name__ == "StructInput" %}
|
|
{% set builder_name = param.local_name + "_builder" %}
|
|
let mut {{ builder_name }} = {{ sdk_mod_path[-1] }}::{{ param.data_type.name }}Builder::default();
|
|
{%- for k, v in param.data_type.fields.items() %}
|
|
{%- if v.is_optional %}
|
|
if let Some(val) = &{{ val_var }}.{{ v.local_name }} {
|
|
{{ set_request_data_from_input(manager, builder_name, v, "val") }}
|
|
}
|
|
{%- else %}
|
|
{{ set_request_data_from_input(manager, builder_name, v, "&" + val_var + "." + v.local_name) }}
|
|
{%- endif %}
|
|
|
|
{%- endfor %}
|
|
{{ dst_var }}.{{ param.remote_name }}({{ builder_name }}.build().expect("A valid object"));
|
|
|
|
{%- elif param.data_type.__class__.__name__ == "Struct" %}
|
|
{% set builder_name = param.local_name + "_builder" %}
|
|
let {{ builder_name }}: openstack_sdk::api::{{ sdk_mod_path | join("::") }}::{{ param.data_type.name }}Builder = TryFrom::try_from(&{{ val_var}})?;
|
|
{{ dst_var }}.{{ param.remote_name }}({{ builder_name }}.build()?);
|
|
|
|
{%- elif param.data_type.__class__.__name__ in ["String", "SecretString"] %}
|
|
{%- if is_nullable and not param.is_optional %}
|
|
{{ dst_var }}.{{ param.remote_name }}({{ val_var | replace("&", "") }}.clone());
|
|
{%- elif is_nullable and param.is_optional %}
|
|
{{ dst_var }}.{{ param.remote_name }}(Some({{ val_var }}.into()));
|
|
{%- elif (param.is_optional is defined and param.is_optional) or (param.is_required is defined and not param.is_required) %}
|
|
{{ dst_var }}.{{ param.remote_name }}({{ val_var if not by_ref else (val_var + ".clone()")}});
|
|
{%- else %}
|
|
{{ dst_var }}.{{ param.remote_name }}(&{{ val_var | replace("&", "") }});
|
|
{%- endif %}
|
|
|
|
{%- elif param.data_type.__class__.__name__ == "Option" %}
|
|
{%- if param.data_type.item_type.__class__.__name__ == "StructInput" %}
|
|
if let Some(l{{ param.local_name }}) = &{{ val_var | replace("&", "") }} {
|
|
{% set builder_name = param.local_name + "_builder" %}
|
|
let mut {{ builder_name }} = {{ sdk_mod_path[-1] }}::{{ param.data_type.item_type.name }}Builder::default();
|
|
{%- for k, v in param.data_type.item_type.fields.items() %}
|
|
{%- if v.is_optional %}
|
|
if let Some(val) = &l{{ param.local_name }}.{{ v.local_name }} {
|
|
{{ set_request_data_from_input(manager, builder_name, v, "val") }}
|
|
}
|
|
{%- else %}
|
|
{{ set_request_data_from_input(manager, builder_name, v, "&l" + param.local_name + "." + v.local_name) }}
|
|
{%- endif %}
|
|
|
|
{%- endfor %}
|
|
{{ dst_var }}.{{ param.remote_name }}({{ builder_name }}.build().expect("A valid object"));
|
|
}
|
|
|
|
{%- elif param.data_type.item_type.__class__.__name__ == "JsonValue" %}
|
|
{#- atm it is not possible to pass ownership of Option<Json> #}
|
|
if let Some(val) = {{ val_var }} {
|
|
{{ dst_var }}.{{ param.remote_name }}(val.clone());
|
|
}
|
|
{%- else %}
|
|
{{ dst_var }}.{{ param.remote_name }}(*{{ val_var }});
|
|
{%- endif %}
|
|
|
|
{%- else %}
|
|
{{ dst_var }}.{{ param.remote_name }}({{ val_var }});
|
|
{%- endif %}
|
|
{%- endmacro %}
|
|
|
|
{%- macro dictionary_setter(param, val_var, dst_var) %}
|
|
{#- Set sdk dictionary from cli input -#}
|
|
{%- set original_type = param.data_type.value_type.original_data_type %}
|
|
{%- if param.data_type.value_type.__class__.__name__ == "JsonValue" and original_type.__class__.__name__ == "StructInput" %}
|
|
{% set builder_name = param.local_name + "_builder" %}
|
|
{{ dst_var}}.{{ param.remote_name }}(
|
|
{%- if val_var.startswith("&self") %}
|
|
{{ val_var | replace("&", "") }}
|
|
{%- else %}
|
|
{{ val_var }}
|
|
{%- endif %}
|
|
.iter()
|
|
.map(|(k, v)| {
|
|
{#- sdk uses Struct while cli uses StructInput -> thus replace #}
|
|
serde_json::from_value(v.to_owned()).map(|v: {{ sdk_mod_path[-1] }}::{{ original_type.name | replace("StructInput", "Struct") }}| (k, v))
|
|
})
|
|
.collect::<Result<Vec<_>, _>>()?
|
|
.into_iter(),
|
|
);
|
|
|
|
{%- elif param.data_type.value_type.__class__.__name__ == "Option" %}
|
|
{{ dst_var }}.{{ param.remote_name }}({{ val_var | replace("&", "") }}.iter().cloned().map(|(k, v)| (k, v.map(Into::into))));
|
|
{%- elif param.data_type.value_type.__class__.__name__ == "JsonValue" and original_type.__class__.__name__ == "ArrayInput" %}
|
|
{{ dst_var }}.{{ param.remote_name }}(
|
|
{{ val_var }}.iter()
|
|
.map(|(k, v)| {
|
|
serde_json::from_value::<Vec<{{ original_type.item_type.type_hint }}>>(v.to_owned())
|
|
.map(|v| (k, v.into_iter()))
|
|
})
|
|
.collect::<Result<Vec<_>, _>>()?
|
|
.into_iter(),
|
|
);
|
|
{%- else %}
|
|
{{ dst_var }}.{{ param.remote_name }}({{ val_var | replace("&", "") }}.iter().cloned());
|
|
{%- endif %}
|
|
{%- endmacro %}
|
|
|
|
{%- macro sdk_enum_array_setter(manager, param, field, val_var, dst_var) %}
|
|
{#- Set sdk array from cli input -#}
|
|
{%- set original_type = field.data_type.original_data_type %}
|
|
{%- if field.data_type.item_type.__class__.__name__ == "JsonValue" and original_type.__class__.__name__ == "StructInput" %}
|
|
{% set builder_name = param.local_name + "_builder" %}
|
|
let {{ builder_name }}: Vec<{{ sdk_mod_path[-1] }}::{{ original_type.name }}> = {{ val_var }}
|
|
.iter()
|
|
.flat_map(|v|
|
|
serde_json::from_value::<{{ sdk_mod_path[-1] }}::{{ original_type.name }}>(v.to_owned()))
|
|
.collect();
|
|
{{ dst_var }}.{{ param.remote_name }}(
|
|
{{ sdk_mod_path[-1] }}::{{ param.data_type.name }}::{{ field.remote_name }}({{ builder_name }})
|
|
);
|
|
{%- else %}
|
|
{#- Normal array #}
|
|
{{ dst_var }}.{{ param.remote_name }}(
|
|
{{ sdk_mod_path[-1] }}::{{ field.remote_name }}({{ val_var }}.into_iter())
|
|
);
|
|
{%- endif %}
|
|
{%- endmacro %}
|
|
|
|
{%- macro sdk_plain_array_setter(param, val_var, dst_var, by_ref=False) %}
|
|
{%- set original_type = param.data_type.original_data_type %}
|
|
{%- set original_item_type = param.data_type.item_type.original_data_type %}
|
|
{%- if param.data_type.item_type.__class__.__name__ == "JsonValue" and original_type.__class__.__name__ == "StructInput" %}
|
|
{% set builder_name = param.local_name + "_builder" %}
|
|
let {{ builder_name }}: Vec<{{ sdk_mod_path[-1] }}::{{ original_type.name }}> = {{ val_var }}
|
|
.iter()
|
|
.flat_map(|v|
|
|
serde_json::from_value::<{{ sdk_mod_path[-1] }}::{{ original_type.name }}>(v.to_owned()))
|
|
.collect::<Vec<{{ sdk_mod_path[-1] }}:: {{ original_type.name }}>>();
|
|
{{ dst_var }}.{{ param.remote_name }}({{ builder_name }});
|
|
{%- elif param.data_type.item_type.__class__.__name__ == "ArrayInput" and param.data_type.item_type.__class__.__name__ == "ArrayInput" %}
|
|
{#- Array of Arrays - we should have the SDK setter for that #}
|
|
{{ dst_var }}.{{ param.remote_name }}({{ val_var }}.into_iter());
|
|
{%- elif param.data_type.item_type.__class__.__name__ in ["String", "SecretString"] and original_item_type.__class__.__name__ == "StructInput" %}
|
|
{#- Single field structure replaced with only string #}
|
|
{%- set original_type = param.data_type.item_type.original_data_type %}
|
|
{%- set original_field = original_type.fields[param.data_type.item_type.original_data_type.fields.keys()|list|first] %}
|
|
{% set builder_name = param.local_name + "_builder" %}
|
|
let {{ builder_name }}: Vec<{{ sdk_mod_path[-1] }}::{{ original_type.name }}> = {{ val_var }}
|
|
.iter()
|
|
.flat_map(|v| {{ sdk_mod_path[-1] }}::{{ original_type.name }}Builder::default()
|
|
.{{ original_field.remote_name }}(v)
|
|
.build()
|
|
)
|
|
.collect();
|
|
{{ dst_var }}.{{ param.remote_name }}({{ builder_name }});
|
|
{%- elif param.data_type.item_type.__class__.__name__ in ["String", "SecretString"] and original_type.__class__.__name__ == "ArrayInput" %}
|
|
{#- Single field structure replaced with only string #}
|
|
{{ dst_var }}.{{ param.remote_name }}(
|
|
val.iter()
|
|
.cloned()
|
|
.map(|x| Vec::from([x.split(',').collect()]))
|
|
.collect::<Vec<_>>(),
|
|
);
|
|
{%- elif param["setter_type"] is defined %}
|
|
{#- Param with setter present #}
|
|
{{ dst_var }}.{{ param.remote_name }}(
|
|
{{ val_var }}{{ ".iter()" if not by_ref else ".iter().cloned()" }}
|
|
);
|
|
{%- elif param.data_type.item_type.__class__.__name__ == "StringEnum" %}
|
|
{{ dst_var }}.{{ param.remote_name }}(
|
|
{{ val_var }}
|
|
.iter()
|
|
.map(|x| match x {
|
|
{%- for variant in param.data_type.item_type.variants.keys() | sort %}
|
|
{{ param.data_type.item_type.name }}::{{ variant }} => {{ sdk_mod_path[-1] }}::{{ param.data_type.item_type.name }}::{{ variant }},
|
|
{%- endfor %}
|
|
})
|
|
.collect::<Vec<_>>(),
|
|
);
|
|
|
|
{%- elif original_item_type and original_item_type.__class__.__name__ == "DictionaryInput" %}
|
|
use std::collections::BTreeMap;
|
|
{{ dst_var }}.{{ param.remote_name }}(
|
|
{{ val_var }}.iter()
|
|
.map( |v| {
|
|
v.as_object()
|
|
.expect("Is a valid Json object")
|
|
.into_iter()
|
|
.map(|(k, v)| (k.into(), v.clone().into()))
|
|
.collect::<BTreeMap<_,Value>>()
|
|
})
|
|
.collect::<Vec<_>>()
|
|
);
|
|
{%- else %}
|
|
{#- Normal array #}
|
|
{{ dst_var }}.{{ param.remote_name }}(
|
|
{{ val_var }}.iter().map(Into::into).collect::<Vec<_>>()
|
|
);
|
|
{%- endif %}
|
|
{%- endmacro %}
|
|
|
|
{%- macro get_data_for_sdk(data, data_var) %}
|
|
{%- if data.__class__.__name__ == "ArrayInput" -%}
|
|
{{ data_var }}.iter().cloned()
|
|
{%- endif -%}
|
|
{%- endmacro %}
|
|
|
|
{%- macro set_cli_path_parameters(type_manager, builder, find_mode=False) %}
|
|
{%- if not find_mode %}
|
|
|
|
// Set path parameters
|
|
{%- endif %}
|
|
{%- for (k, v) in type_manager.get_parameters("path") %}
|
|
{%- if v.resource_link %}
|
|
{%- set res_name = v.resource_link.split(".")[0].split('/')[-1] %}
|
|
|
|
// Process path parameter `{{ k }}`
|
|
if let Some(id) = &self.path.{{ res_name }}.{{ res_name }}_id {
|
|
// {{ res_name }}_id is passed. No need to lookup
|
|
{{ builder }}.{{ v.remote_name }}(id);
|
|
}
|
|
else if let Some(name) = &self.path.{{ res_name }}.{{ res_name }}_name {
|
|
// {{ res_name }}_name is passed. Need to lookup resource
|
|
let mut sub_find_builder = find_{{ res_name }}::Request::builder();
|
|
warn!("Querying {{ res_name}} by name (because of `--{{res_name}}-name` parameter passed) may not be definite. This may fail in which case parameter `--{{res_name}}-id` should be used instead.");
|
|
|
|
sub_find_builder.id(name);
|
|
let find_ep = sub_find_builder
|
|
.build()
|
|
.map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
|
|
let find_data: serde_json::Value = find_by_name(find_ep).query_async(client).await?;
|
|
// Try to extract resource id
|
|
match find_data.get("id") {
|
|
Some(val) => match val.as_str() {
|
|
Some(id_str) => {
|
|
{{ builder }}.{{ v.remote_name }}(id_str.to_owned());
|
|
}
|
|
None => {
|
|
return Err(OpenStackCliError::ResourceAttributeNotString(
|
|
serde_json::to_string(&val)?,
|
|
))
|
|
}
|
|
},
|
|
None => {
|
|
return Err(OpenStackCliError::ResourceAttributeMissing(
|
|
"id".to_string(),
|
|
))
|
|
}
|
|
};
|
|
}
|
|
{%- if v.remote_name in ["user_id", "project_id", "domain_id"] %}
|
|
else if self.path.{{ res_name }}.current_{{ res_name }} {
|
|
{%- if v.remote_name == "domain_id" %}
|
|
let token = client
|
|
.get_auth_info()
|
|
.ok_or_eyre("Cannot determine current authentication information")?
|
|
.token;
|
|
if let Some(domain) = token.domain {
|
|
ep_builder.domain_id(domain.id.ok_or_eyre("Domain ID is missing in the auth")?);
|
|
} else if let Some(project) = token.project {
|
|
ep_builder.{{ v.remote_name }}(
|
|
project
|
|
.domain
|
|
.ok_or_eyre("Domain information is missing in the project auth info")?
|
|
.id
|
|
.ok_or_eyre("Domain ID is missing in the project.domain auth info")?,
|
|
);
|
|
} else {
|
|
return Err(eyre!("Current domain information can not be identified").into());
|
|
}
|
|
{%- elif v.remote_name == "project_id" %}
|
|
let token = client
|
|
.get_auth_info()
|
|
.ok_or_eyre("Cannot determine current authentication information")?
|
|
.token;
|
|
if let Some(project) = token.project {
|
|
ep_builder.{{ v.remote_name }}(
|
|
project
|
|
.id
|
|
.ok_or_eyre("Project ID is missing in the project auth info")?,
|
|
);
|
|
} else {
|
|
return Err(eyre!("Current project information can not be identified").into());
|
|
}
|
|
{%- elif v.remote_name == "user_id" %}
|
|
{{ builder }}.{{ v.remote_name }}(
|
|
client
|
|
.get_auth_info()
|
|
.ok_or_eyre("Cannot determine current authentication information")?
|
|
.token
|
|
.user
|
|
.id,
|
|
);
|
|
{%- endif %}
|
|
}
|
|
{%- endif %}
|
|
{%- else %}
|
|
{%- if not v.is_required %}
|
|
{%- if k != "project_id" %}
|
|
if let Some(val) = &self.path.{{ v.local_name }} {
|
|
{{ builder }}.{{ v.local_name }}(val);
|
|
}
|
|
{%- else %}
|
|
if let Some(val) = &self.path.{{ v.local_name }} {
|
|
{{ builder }}.{{ v.local_name }}(val);
|
|
} else {
|
|
{{ builder }}.{{ v.local_name }}(client.get_current_project().expect("Project ID must be known").id);
|
|
}
|
|
{%- endif %}
|
|
{%- elif not find_mode and find_present and operation_type in ["show", "set", "download"] %}
|
|
let resource_id = find_data["id"]
|
|
.as_str()
|
|
.expect("Resource ID is a string")
|
|
.to_string();
|
|
{{ builder }}.{{ v.local_name }}(resource_id.clone());
|
|
{%- else %}
|
|
{{ builder }}.{{ v.local_name }}(&self.path.{{ v.local_name }});
|
|
{%- endif %}
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
{%- endmacro %}
|
|
|
|
{%- macro sdk_build_url(url, params, prefix = "", from_attr = False) %}
|
|
{%- if params.values()|selectattr("location", "equalto", "path")|list|length > 0 -%}
|
|
format!(
|
|
"{{ prefix }}{{ url }}",
|
|
{%- for k, v in params.items() %}
|
|
{%- if v.location == "path" %}
|
|
{{ v.local_name }} = {{ ('"' + v.local_name + '"') if not from_attr else ('self.' + v.local_name + '.as_ref()') }},
|
|
{%- endif %}
|
|
{%- endfor %}
|
|
)
|
|
{%- else %}
|
|
"{{ prefix }}{{ url }}".to_string()
|
|
{%- endif %}
|
|
{%- endmacro %}
|