Looping through a list of dictionaries in Ansible - loops

I've used basic loops before, nice and easy. However, now I have more of a challenge.
The task:
- name: Configure BGP
fortios_router_bgp:
vdom: "FG-traffic"
router_bgp:
as: " {{ as }}"
router_id: "{{ router_id }}"
neighbor:
-
holdtime_timer: "{{ holdtime_timer }}"
interface: "{{ item.interface }}"
ip: "{{ item.ip }}"
keep_alive_timer: "{{ keep_alive_timer }}"
prefix_list_in: "{{ item.prefix_list_in }}"
remote_as: "{{ item.remote_as }}"
route_map_in: "{{ item.route_map_in }}"
update_source: "{{ item.update_source }}"
loop: "{{ bgp_neighbors }}"
tags: bgp
The list of dictionaries/hashes, the variable:
bgp_neighbors:
- { interface: "INT_A", ip: "{{ netid_bgp }}.12", prefix_list_in: "default-route-in", remote_as: "30000", route_map_in: "SET_PREF", update_source: "INT_A" }
- { interface: "INT_B", ip: "{{ netid_bgp }}.14", prefix_list_in: "default-route-in", remote_as: "30000", route_map_in: "SET_PREF", update_source: "INT_B" }
- { interface: "INT_DR_A", ip: "{{ netid_bgp }}.16", prefix_list_in: "default-route-in", remote_as: "30000", route_map_in: "SET_PREF", update_source: "INT_DR_A" }
- { interface: "INT_DR_B", ip: "{{ netid_bgp }}.18", prefix_list_in: "default-route-in", remote_as: "30000", route_map_in: "SET_PREF", update_source: "INT_DR_B" }
The objective is to create a list of four neighbors. What I get, of course, is a list of one, the last dictionary in the list.
I understand the loop is working correctly, that this module runs four times based on the list of four dictionaries, overwriting the key value pairs each time.
I understand that I need to process the keys in the dictionary list seperately although I'm struggling to work this out.
Now that I've started to do more loops I see that is going to be a common requirement.
This is the long hand version that I am trying to replace - ignore the variable names, I haven repopulated them with the actual values:
- name: Configure BGP
fortios_router_bgp:
vdom: "FG-traffic"
router_bgp:
as: " {{ as }}"
router_id: "{{ router_id }}"
neighbor:
-
holdtime_timer: "{{ holdtime_timer }}"
interface: "{{ item.interface }}"
ip: "{{ item.ip }}"
keep_alive_timer: "{{ keep_alive_timer }}"
prefix_list_in: "{{ item.prefix_list_in }}"
remote_as: "{{ item.remote_as }}"
route_map_in: "{{ item.route_map_in }}"
update_source: "{{ item.update_source }}"
-
holdtime_timer: "{{ holdtime_timer }}"
interface: "{{ item.interface }}"
ip: "{{ item.ip }}"
keep_alive_timer: "{{ keep_alive_timer }}"
prefix_list_in: "{{ item.prefix_list_in }}"
remote_as: "{{ item.remote_as }}"
route_map_in: "{{ item.route_map_in }}"
update_source: "{{ item.update_source }}"
-
holdtime_timer: "{{ holdtime_timer }}"
interface: "{{ item.interface }}"
ip: "{{ item.ip }}"
keep_alive_timer: "{{ keep_alive_timer }}"
prefix_list_in: "{{ item.prefix_list_in }}"
remote_as: "{{ item.remote_as }}"
route_map_in: "{{ item.route_map_in }}"
update_source: "{{ item.update_source }}"
-
holdtime_timer: "{{ holdtime_timer }}"
interface: "{{ item.interface }}"
ip: "{{ item.ip }}"
keep_alive_timer: "{{ keep_alive_timer }}"
prefix_list_in: "{{ item.prefix_list_in }}"
remote_as: "{{ item.remote_as }}"
route_map_in: "{{ item.route_map_in }}"
update_source: "{{ item.update_source }}"
tags: bgp
Thanks!

Create a template
shell> cat templates/neighbor.j2
{% for i in bgp_neighbors %}
- holdtime_timer: "{{ holdtime_timer }}"
interface: "{{ i.interface }}"
ip: "{{ i.ip }}"
keep_alive_timer: "{{ keep_alive_timer }}"
prefix_list_in: "{{ i.prefix_list_in }}"
remote_as: "{{ i.remote_as }}"
route_map_in: "{{ i.route_map_in }}"
update_source: "{{ i.update_source }}"
{% endfor %}
Put the declarations into the vars
netid_bgp: 10.1.0
holdtime_timer: value of holdtime timer
keep_alive_timer: value of keep alive timer
_neighbor: "{{ lookup('template', 'templates/neighbor.j2') }}"
neighbor: "{{ _neighbor|from_yaml }}"
Then the tasks below
- set_fact:
neighbor: "{{ neighbor }}"
- debug:
var: neighbor
give the list
neighbor:
- holdtime_timer: value of holdtime timer
interface: INT_A
ip: 10.1.0.12
keep_alive_timer: value of keep alive timer
prefix_list_in: default-route-in
remote_as: '30000'
route_map_in: SET_PREF
update_source: INT_A
- holdtime_timer: value of holdtime timer
interface: INT_B
ip: 10.1.0.14
keep_alive_timer: value of keep alive timer
prefix_list_in: default-route-in
remote_as: '30000'
route_map_in: SET_PREF
update_source: INT_B
- holdtime_timer: value of holdtime timer
interface: INT_DR_A
ip: 10.1.0.16
keep_alive_timer: value of keep alive timer
prefix_list_in: default-route-in
remote_as: '30000'
route_map_in: SET_PREF
update_source: INT_DR_A
- holdtime_timer: value of holdtime timer
interface: INT_DR_B
ip: 10.1.0.18
keep_alive_timer: value of keep alive timer
prefix_list_in: default-route-in
remote_as: '30000'
route_map_in: SET_PREF
update_source: INT_DR_B
Use the variable in the module
- name: Configure BGP
fortios_router_bgp:
vdom: "FG-traffic"
router_bgp:
as: " {{ as }}"
router_id: "{{ router_id }}"
neighbor: "{{ neighbor }}"
...

Related

Hugo – How to add different class names based on counter

Using Hugo, I need add unique class names to the first few posts. How can this be done?
My code that's obviously not working…
// if the first post
{{ if eq .Site.GetPage 1 }}
{{ $classname := "class-one" }}
// else the second post
{{ elseif eq .Site.GetPage 2 }}
{{ $classname := "class-two" }}
// else the third post
{{ elseif eq .Site.GetPage 3 }}
{{ $classname := "class-three" }}
{{ else }}
{{ end }}
<li class="{{ $classname }}">
…
</li>
Maybe there's some more efficient way, but this works:
{{ $paginator := .Paginate (where .Data.Pages.ByDate.Reverse "Type" "post") }}
{{ range $index, $element := $paginator.Pages }}
{{ if (eq $index 0) }}
{{ $.Scratch.Set "classname" "class-one" }}
{{ else if (eq $index 1) }}
{{ $.Scratch.Set "classname" "class-two" }}
{{ else }}
{{ $.Scratch.Set "classname" "" }}
{{ end }}
<li class="{{ $.Scratch.Get "classname" | safeHTML }}">
…
</li>
{{ end }}

Angularjs : add multiple ng_if condition in with haml syntax

I'm working on an item_selector directive, I want to add an indicator for archived element, this is the item selector template .haml :
.directive-items-selector{ ng_click: "openItemsSelector( $event )" }
.wrapper
%ui_select.ui-select{ ng: { model: "input.model", disabled: "disabled",
change: "itemSelectModelChanged()" },
search_enabled: "{{ options.searchable }}" }
%ui_select_match.ui-select-match{ items_selector_match: '',
placeholder: "{{ input.placeholder }} ",
allow_clear: "{{ options.clearable }}",
title: "{{ $select.selected.label }}" }
%i.fa{ ng_class: 'icon' }
%span{'ng': {'class': "{'is-archived': $select.selected.object.is_archived === true}"}}
{{ $select.selected.label }}
%ui_select_choices.ui-select-choices{ repeat: "item.id as item in input.filteredItems track by item.id",
refresh: "reloadItems( $select.search )",
refresh_delay: '{{ input.filterDelay }}' }
.item{ ng_attr_title: "{{ ::item.label }}" }
.item-label {{ ::item.label }}
%small.item-details {{ ::item.details }}
.items-selector-actions
%a.pointer.action{ ng: { if: 'linkToModal', click: 'openDetails()', disabled: "!model" }}
{{ 'btn.details' | translate }}
%a.pointer.action{ ng: { if: 'createButton && klassName && !disabled', click: 'createItem()' }}
{{ 'btn.new' | translate }}
I've add a through line css propoerty to archived element by :
%span{'ng': {'class': "{'is-archived': $select.selected.object.is_archived === true}"}}
{{ $select.selected.label }
and I want to add a mouse hover indicator that tell user "this element is archived", I thought about ng_if multiple condition in this attribute of ui_select.ui-select : title: "{{ $select.selected.label }}"
*
if $select.selected.object.is_archived return true : costume message
else {{ $select.selected.label }
*

multiple forms same page ionic2

I am new in Ionic2 and can't solve one thing myself, I have small app width page: user-list and getting data from firebase width angularfire2.
First table name in Firebase is: imported
Second Table name in Firebase is: userProfile
in the imported table is user details (name, email, bdate etc..) and I want to get data from this table, then push to the userProfile table one by one.
so my user-list.ts is this:
export class UsersListPage {
public signupForm: FormGroup;
user:any;
usersList: FirebaseListObservable<any[]>;
usersTable: FirebaseListObservable<any[]>;
constructor(
public navCtrl: NavController,
public formBuilder: FormBuilder,
public navParams: NavParams,
public authProvider: AuthProvider,
public db: AngularFireDatabase
) {
this.usersList = db.list('/imported');
this.usersTable = db.list('usersProfile');
this.user = authProvider.userUid();
this.signupForm = formBuilder.group({
address: [''],
password: [''],
bday: [''],
email: [''],
name: [''],
number: [''],
signedup: [''],
telephone: [''],
zip: [''],
uid: [''],
});
}
createUser(){
this.authProvider.signupUser(this.signupForm.value.email, this.signupForm.value.password).then(() => {
this.usersTable.push({
email: this.signupForm.value.email,
password: this.signupForm.value.password,
address: this.signupForm.value.address,
bday: this.signupForm.value.bday,
name: this.signupForm.value.name,
number: this.signupForm.value.number,
signedup: this.signupForm.value.signedup,
telephone: this.signupForm.value.telephone,
zip: this.signupForm.value.zip,
uid: this.user
});
});
}
}
and my html is:
<ion-content padding>
<form *ngFor="let user of usersList | async" [formGroup]="signupForm" (submit)="createUser()">
<ion-input formControlName="email" value="{{ user.email }}" type="text"></ion-input>
<ion-input formControlName="password" value="{{ user.telephone }}" type="text"></ion-input>
<ion-input formControlName="address" value="{{ user.address }}" type="text"></ion-input>
<ion-input formControlName="bday" value="{{ user.bday }}" type="text"></ion-input>
<ion-input formControlName="name" value="{{ user.name }}" type="text"></ion-input>
<ion-input formControlName="number" value="{{ user.number }}" type="text"></ion-input>
<ion-input formControlName="signedup" value="{{ user.signedup }}" type="text"></ion-input>
<ion-input formControlName="telephone" value="{{ user.telephone }}" type="text"></ion-input>
<ion-input formControlName="zip" value="{{ user.zip }}" type="hidden"></ion-input>
<button ion-button type="submit" color="secondary" >
User Registration
</button>
</form>
</ion-content>
it works but one problem is here, when I click the button only adds the last record from imported table, so I can not add one by one user per click

Dropdown filter in angularjs

I have an array of data which I need to bind it to dropdown list in angularjs.
$scope.offerFilter = [ {title :'Matching Ticket' , Status : '1'},
{title :'Non-matched Ticket',Status : '2'},
{title :'Rejected Ticket',Status : '3'},
{title: 'Not Sale', Status: '0'}]
I have binded the title to my dropdown list. When I select the option from dropdown list my page not getting filtered. I don't know where I am going wrong.
My View:
<select ng-model="SelectedStatus" ng-options="type.Status as type.title for type in offerFilter" style="float:right;width:40%;font-family:'Segoe UI';font-size:12px;">
<option value="">All {{type.title}}</option>
</select>
<md-list-item dir-paginate="ticket in ticketInventoryList.data.hits.hits | itemsPerPage:10 | filter : SelectedStatus">
<div style="width:15%">
<img alt="{{ ticket._source.SeriesName }}" ng-src="{{ ticket._source.ImagePath }}" class="md-avatar" style="width:90%" />
</div>
</md-list-item>
My controller:
I have declared the ng-model variabe as $scope.SelectedStatus='';
Thanks in advance.
Hope it will be work for you
<select ng-model="SelectedStatus" ng-change="changeValue(SelectedStatus)" ng-options="type.Status as type.title for type in offerFilter" style="float:right;width:40%;font-family:'Segoe UI';font-size:12px;">
<option value="">All {{type.title}}</option>
</select>
Please this all code in controller
$scope.isShow=false;
$scope.changeValue=function(selectedValue){
if(condtion you want){
$scope.isShow=false;
$timeout(function(){
$scope.isShow=true;
},500);
}
}
<md-list-item dir-paginate="ticket in ticketInventoryList.data.hits.hits | itemsPerPage:10 | filter : SelectedStatus" data-ng-if="isShow">
<div style="width:15%">
<img alt="{{ ticket._source.SeriesName }}" ng-src="{{ ticket._source.ImagePath }}" class="md-avatar" style="width:90%" />
</div>
</md-list-item>
Your change to refresh directive when select value is changed.

Switching between modes / Accessing parts of data structure

Given the following data:
{
id: "",
title: "",
// modes
one: {
stage: 1,
order: 3,
more: "",
}
two: {
stage: 14,
order: 5,
more: "",
}
// ...
},
// ...
how can I combine the following two pieces of code into one that uses a variable as a switching mechanism for the mode?
// If selected mode was "one"
<li ng-repeat="item in items | orderBy: ['one.stage', 'one.order']
| filter: oneFilter" ng-class="{ topline: isNewOneStage( item )}">
{{ item.title }},
{{ item.one.stage }}
// ...
</li>
// If selected mode was "two"
<li ng-repeat="item in items | orderBy: ['two.stage', 'two.order']
| filter: twoFilter" ng-class="{ topline: isNewTwoStage( item )}">
{{ item.title }},
{{ item.two.stage }}
// ...
</li>
Since the two pieces of code are completely identical - apart from the mode - I would like to avoid code duplication. (Note also that there will eventually be more than just two modes.)
I agree with Michael that you should probably reorganize your code, but if you must have it all at once you can do this depending on what version of angular you are using:
// variable mode is either 'one' or 'two'
<li ng-repeat="item in items | orderBy: [ mode + '.stage', mode + '.order']
| filter: (mode == 'one' ? oneFilter: twoFilter)" ng-class="{ topline: (mode == 'one' ? isNewOneStage: isNewTwoStage)( item )}">
{{ item.title }},
{{ item[mode].stage }}
// ...
</li>

Resources