I'm trying to build a configuration file dynamically with Ansible, using a Jinja2 template.
In Ansible, I've defined a role in which I have the template and the set of variables.
I want my output file to look like this :
models:
model1:
username: user1
password: password1
model2:
username: user2
password: password2
I have defined my variables like so :
model_list:
name:
- model1
- model2
user:
- user1
- user2
pass:
- password1
- password2
My .j2 template :
{% for model in vars[model_list] %}
{{ model.name }}
username: {{ model.user }}
password: {{ model.pass }}
{% endfor %}
My playbook is quite simple :
- name: Building config file
template:
src: ./config.j2
dest: my/path/config
When I run the playbook I've got the following error :
fatal: [FRADEV048]: FAILED! => {"changed": false, "msg":
"AnsibleUndefinedVariable: dict object has no element {u'user':
u'user1', u'name': u'model1', u'pass': u'password1'}"}
I'm quite new in programming so I don't really see where my error is ... Any clues ?
Thanks in advance for your help,
Simon
Template content
models:
{% for model in model_list.name %}
{{ model }}:
username: {{ model_list.user[loop.index0] }}
password: {{ model_list.pass[loop.index0] }}
{% endfor %}
Reference: https://stackoverflow.com/a/24959173/5439195
Related
I fail to display the routable index page for categories/given category.
My code uses:
-BlogCategory(model)
-BlogPageBlogCategory (page) an intemediary structure that links to:
-PostPage(page)
I can pass the code to the post_page template, but when I click on a specific category link I get:
Reverse for 'post_by_category' with arguments '('',)' not found. 1 pattern(s) tried: ['category/(?P<category>[-\\w]+)/$']
In the following post #gasman wrote: "the routablepageurl tag has received an empty string". I couldn't find the 'empty' string/missing link.
I assume it's related to the route of my 'def post_by_category'. Any input that would help me deepen my learning woulg be great.
NB - in case it helps, when I run this procedure without the intemeiary page all's fine. I can display the BlogPage/given_category once I click on the category in the PostPage.
Here's my code:
Models
class BlogPage(RoutablePageMixin, Page):
...
def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
context["posts"] = posts
return context
def get_posts(self):
return PostPage.objects.descendant_of(self).live().order_by("-post_date")
#route(r'^category/(?P<category>[-\w]+)/$')
def post_by_category(self, request, category, *args, **kwargs):
self.posts = self.get_posts().filter(categories__blog_category__slug=category)
context["categories"] = BlogCategory.objects.all()
return self.render(request)
class PostPage(MetadataPageMixin, Page):
...
content_panels = Page.content_panels + [
...
InlinePanel("categories", label="category"),
...
def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
return context
class PostPageBlogCategory(models.Model):
page = ParentalKey(
"blog.PostPage", on_delete=models.CASCADE, related_name="categories"
)
blog_category = models.ForeignKey(
"blog.BlogCategory", on_delete=models.CASCADE, related_name="post_pages"
)
panels = [
SnippetChooserPanel("blog_category"),
]
class Meta:
unique_together = ("page", "blog_category")
#register_snippet
class BlogCategory(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=80)
panels = [
FieldPanel('name'),
FieldPanel("slug"),
]
def __str__(self):
return self.name
class Meta:
verbose_name_plural = 'categories'
The post_page.html:
{% extends "base.html" %}
{% load wagtailroutablepage_tags %}
...
{% for category in page.categories.all %}
<li>
<a href="{% routablepageurl blog_page "post_by_category" category.slug %}">
{{ blog_category.name }}
</a>
</li>
{% empty %}
No categories yet'
{% endfor %}
...
After debugging and testing, I didn't find any blank categories, (which doesn't mean there were none, but that I didn't find or deleted them Unintentionally).
I case it could help, what worked for me was adding the category_type at the beginning of my varaiable:
{{ category.blog_category.name }} rather than {{ blog_category.name }}
{% for category in page.categories.all %}
<a href="{% routablepageurl article_index_page "post_by_category" category.blog_category.slug %}" class="link-primary text-decoration-none">
{{ category.blog_category.name }}
</a>
{% empty %}
No categories yet'
{% endfor %}
Contact form data (using Wagtail's formbuilder) is not sending to email what is the issue?
I added email host also but not sending data to email
The form response (contact data) is being saved in wagtail admin but data not sending to email.
Console Output
DEBUG CONSOLE
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: contact form submission
From: archanapco8#gmail.com
To: ranjuranjitha. 1997#gmail.com
Date: Mon, 08 Nov 2021 08:13:45 -0000
Message-ID: <163635922547.9304.15785246130187863651#DESKTOP-NC1TOGR>
Auto-submitted: auto-generated
Your Name: ranjitha
Your company: mdrift
Your email address: rmanju#dgmail.com
When do you want to start?: 20-09-2021
What is your budget: 1000
Describe your needs, the more we know, the better: hi
[08/Nov/2021 13:43:45] "POST /contact-us/ HTTP/1.1" 200 9590
[08/Nov/2021 13:43:45] "GET /static/img/Thank-you.png HTTP/1.1" 200 15470
O
contact/models.py
from wagtail.contrib.forms.models import AbstractEmailForm, AbstractFormField
class FormField(AbstractFormField):
page = ParentalKey('Form Page', related_name='custom_form_fields')
class Form Page(AbstractEmailForm):
thank_you_text = RichTextField(blank=True)
content_panels = AbstractEmailForm.content_panels + [
InlinePanel('custom_form_fields', label="Form fields"),
FieldPanel('thank_you_text', classname="full"),
MultiFieldPanel([
FieldRowPanel([
FieldPanel('from_address', classname="col6"),
FieldPanel('to_address', classname="col6"),
]),
FieldPanel('subject'),
], "Email Notification Config"),
]
def get_form_fields(self):
return self.custom_form_fields.all()
form_page.html
{% load static wagtailcore_tags widget_tweaks %}
{% block content %}
<h1>Contact</h1>
<br>
<form action="{% pageurl page %}" method="POST">
{% csrf_token %}
{% if form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
{% for field in form.visible_fields %}
<div class="form-group">
{{ field.label_tag }}
{% render_field field class+="form-control" %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary" >Submit</button>
</form>
{% endblock %}
settings/base.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'ranjuranjitha.1997#gmail.com'
EMAIL_HOST_PASSWORD = 'Password$'
EMAIL_USE_TLS = True
EMAIL_USE_SSL = True
DEFAULT_FROM_EMAIL ='ranjuranjitha.1997#gmail.com'
EMAIL_TO = 'ap8366106#gmail.com'
This is dev.py file. I given email backend also but not sending the mail.
settings/dev.py
from .base import *
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-iu22rfee4za6ro+mez!4*#_trpy7!ebpbtu8iw$95v(rh_5fib'
# SECURITY WARNING: define the correct hosts in production!
ALLOWED_HOSTS = ['*']
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
try:
from .local import *
except ImportError:
pass
A few potential solutions below.
1. dev mode settings
Based on your log output and your settings/dev.py file, it appears that the email is working but is just logging the email.
In the dev settings you have EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend', this is a normal dev setup and leverages the Email Console backend which will never actually send an email but just log the email output to the console (terminal).
This means, while in development mode you can easily check the email content without actually sending a real email.
To temporarily override this you can create a file settings/local.py and put a different email backend in that file.
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
Then restart your dev server and it should use the override in the local.py file.
This works because of the settings/dev.py code you already have
try:
from .local import *
except ImportError:
pass
Note: Ensure that your settings/local.py is not committed to your code (git) as this may contain private secrets/passwords etc and usually is just a quick way to test something different.
Refer to this answer about managing Django settings for more insights. It would be good to read the full documentation page end to end that explains how sending email works in Django also.
2. Gmail settings
Check you have ensured that your Gmail will allow SMTP sending? You need to ensure less secure apps are enabled - support.google.com/accounts/answer/6010255?hl=en
See also How to send Django emails with SMTP for more details.
However, using Gmail for this purpose is quite risky and likely to be blocked by Gmail and have spam issues. It is recommended you use a third party service, see some recommendations for third party email services.
I am trying with ansible to make 2 calls api.
The first one is a GET which have to return a json response and match (or not) with a variable.
The second one is a POST only if the GET match the variable.
- name: check if hostname exist
uri:
url: 'some_url'
headers:
Authorization: 'api-key'
Accept: 'application/json'
method: GET
validate_certs: yes
return_content: yes
body_format: json
register: result
- name: defined the new variable
register: resultmatch
when: "{{ ansible_hostname }} is in result.content"
- name: create the group with the hostname
uri:
url: ""
headers:
Authorization: 'api-key'
Accept: 'application/json'
method: POST
validate_certs: yes
body: "{
'{{ hostname }}': '{{ ansible_hostname }}'
}"
return_content: yes
body_format: json
register: add_secret
when: resultmatch is defined
I expect that the script create a new group when the hostname is setted into the variable.
But it seems that the variable result is not seen as a json content and I have one other problem which is:
name: defined the new variable
^ here
You cannot register without an ansible module. there is no output to be registered here.
- name: defined the new variable
register: resultmatch
when: "{{ ansible_hostname }} is in result.content"
Use as below if you need to define a new variable.
- name: defined the new variable
set_fact:
resultmatch: true
when: "{{ ansible_hostname }} is in result.content"
This is my controller Symfony :
$em = $this->getDoctrine()->getManager();
$advert = $em->getRepository('OCPlatformBundle:Advert')->find($id);
if ($advert == null) {
throw $this->createNotFoundException("L'annonce d'id ".$id." n'existe pas.");
}
$em->remove($advert);
$em->flush();
$request->getSession()->getFlashBag()->add('notice', 'Annonce bien enregistrée.');
return $this->redirect($this->generateUrl('oc_platform_view', array('id' => $advert->getId())));
}
}
and in twig
{% for advert in adverts %}
<li>{{ advert.name|e }}</li>
Delete
{% endfor %}
Please help, I dont know how to make angularJs to show modal confirmation for delete action and refresh my view page
You can do it in javascript:
delete
having a list of users which should be different for stage and production:
user1:
name: username1
password: password1
email: email1
roles: role1, role2
user2:
name: username2
password: password2
email: email2
roles: role1, role2
user3:
name: username3
password: password3
email: email3
roles: role1, role2
user4:
name: username4
password: password4
email: email4
roles: role1, role2
user5:
name: username5
password: password5
email: email5
roles: role1, role2
i tried to put them in the build.properties file (i skipped the roles part)
[user]
admins=username1|password1|email1,username2|password2|email2,username3|password3|email3,username4|password4|email4,username5|password5|email5
which work quite ok with the following code snippet in the build.xml
<target name="createUsers">
<foreach list="${admins}" param="_userset" target="createUser" />
</target>
<target name="createUser">
<php expression="strpos('${_userset}', '|')" returnProperty="_pos1"/>
<php expression="strrpos('${_userset}', '|')" returnProperty="_pos2"/>
<php expression="${_pos2}-${_pos1}" returnProperty="_len"/>
<php expression="substr('${_userset}', 0, ${_pos1})" returnProperty="_username"/>
<php expression="substr('${_userset}', ${_pos1}+1, ${_len}-1)" returnProperty="_password"/>
<php expression="substr('${_userset}', ${_pos2}+1)" returnProperty="_email"/>
<SymfonyConsole console="${bin.symfony}" command="fos:user:create">
<arg value="${_username}" />
<arg value="${_email}" />
<arg value="${_password}" />
</SymfonyConsole>
</target>
but the part in the build.properties file is quite unreadable and unhandy, also adding new values like roles, which is also a list, is rather unhandy.
breaking up the lines does not work, like for java https://stackoverflow.com/a/8978515/590247:
[user]
admins=username1|password1|email1,\
username2|password2|email2,\
username3|password3|email3,\
username4|password4|email4,\
username5|password5|email5
is there a better way to store the multidimensional data?
One solution for this, would be to write an adhoctask, partially similar to http://raphaelstolt.blogspot.ie/2009/04/creating-and-using-phing-ad-hoc-tasks.html ( a very simple example is in the phing documentation at https://www.phing.info/docs/guide/stable/app.coretasks.html#AdhocTaskdefTask ).
You would iterate through your arrays in that adhoctask (perhaps passed in as a property or read in directly from the properties file... - better yet as a serialized array written to a file).
It's not strictly possible to call a phing task from an adhoc task, but you can get around this with exec...
$r = exec(escapeshellcommand("phing -f build.xml symfonycreateusertask");
But as you're simply using SymfonyConsole to essentially exec control out to symfony, I would do that directly instead.
As a very rough example, code for this might look like:
<adhoc-task name="createusers"><![CDATA[
class CreateusersTask extends Task {
private $filename;
function setFile($filename) {
$this->filename = $filename;
}
function main() {
$this->log("Createusers: " . $this->filename);
$serialised = file_get_contents($this->filename);
$users = unserialize($serialised);
foreach($users as $userRow) {
$output = [];
$return = 0;
$user = $userRow['user'];
//....
$r = exec(
"symfony fos:user:create $user $email $password",
$output,
$return
);
$this->log(implode($output));
}
}
}
]]></adhoc-task>
And in the target...
<target name="...">
<createusers file="users.data"/>
</target>