<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>python &#8211; Luxing Huang</title>
	<atom:link href="https://luxing.im/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>https://luxing.im</link>
	<description>Thoughs and things</description>
	<lastBuildDate>Tue, 31 May 2016 13:26:56 +0000</lastBuildDate>
	<language>en-CA</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.2</generator>
<site xmlns="com-wordpress:feed-additions:1">58771605</site>	<item>
		<title>Sending email with Python</title>
		<link>https://luxing.im/sending-email-with-python/</link>
					<comments>https://luxing.im/sending-email-with-python/#respond</comments>
		
		<dc:creator><![CDATA[Luxing Huang]]></dc:creator>
		<pubDate>Tue, 22 Mar 2016 19:41:37 +0000</pubDate>
				<category><![CDATA[Techie Stuff]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[smtplib]]></category>
		<category><![CDATA[tls]]></category>
		<guid isPermaLink="false">https://luxing.im/?p=629</guid>

					<description><![CDATA[This is a note from learning Python&#8217;s email and smtplib modules. Most of emails nowadays consists of 3 parts: plain text content, HTML content and attachments. Python&#8217;s smtplib library indeed saved us a lot of work. 1. Create a multipart/alternative email envelope. from email.mime.multipart import MIMEMultipart alter = MIMEMultipart('alternative') msg = MIMEMultipart() This will create &#8230; <p class="link-more"><a href="https://luxing.im/sending-email-with-python/" class="more-link">Continue reading<span class="screen-reader-text"> "Sending email with Python"</span></a></p>]]></description>
										<content:encoded><![CDATA[<p>This is a note from learning Python&#8217;s <code>email</code> and <code>smtplib</code> modules.<br />
Most of emails nowadays consists of 3 parts: plain text content, HTML content and attachments. Python&#8217;s <code>smtplib</code> library indeed saved us a lot of work.<br />
<span id="more-629"></span></p>
<p>1. Create a multipart/alternative email envelope.</p>
<pre>
from email.mime.multipart import MIMEMultipart
alter = MIMEMultipart('alternative')
msg = MIMEMultipart()
</pre>
<p>This will create an envelope that will contain all 3 mentioned parts. In mutt&#8217;s view:</p>
<pre>
1 <no description>                    [multipa/alternativ, 7bit, 16K] 
2 ├─><no description>                 [text/plain, base64, utf-8, 0.1K] 
3 ├─><no description>                 [text/html, base64, utf-8, 0.1K]  
4 ca.crt                              [applica/octet-stre, base64, 1.5K]
</pre>
<p>Some MIME type is truncated, but you get the idea.</p>
<p>2. Unicode<br />
You will have to append the coding part in the source file.</p>
<pre>
#!/usr/bin/python
# -*- coding: utf-8 -*-
</pre>
<p>The second line must exist.</p>
<p>Then a unicode title and text:</p>
<pre>
from email.mime.text import MIMEText

# msg and alter is derived from the previous example
msg['Subject'] = u'中文'
text = u'正在用Python写东西'
alter.attach(MIMEText(text, 'plain', 'utf-8'))

msg.attach(alter)
</pre>
<p>Appending HTML just change the <code>plain</code> to <code>html</code> when you call <code>MIMEText</code> against HTML content.</p>
<p>3. Add attachments<br />
Mind the relative / absolute path from the location you execute the script. It&#8217;s recommend to use absolute path.</p>
<pre>
from os.path import basename, dirname, realpath

# assuming I will attach all the files in the same location as the script itself, also a file from other relative path.
cwd = dirname(realpath(__file__))
files = ['myfile.bin', 'herfile.bin', '../other/dir/s.bin']

for f in files:
        # use absolute path
        with open(cwd + '/' + f, "rb") as fil:
            msg.attach(MIMEApplication(
                fil.read(),
                Content_Disposition='attachment; filename="%s"' % basename(f),
                Name=basename(f)
            ))
</pre>
<p>4. Message ID.<br />
Some SMTP server supports adding message id to your email on a specific port, e.g. 25. But when you use <code>starttls</code> to connect the SMTP or use a different port, e.g. 587, Message-Id may not be added automatically. So your email probably won&#8217;t be received as it&#8217;s required in <a href="https://tools.ietf.org/html/rfc2822.html" target="_blank">RFC 2822</a>.</p>
<p>One way to get around that is to generate your own message id. Then you could use <code>starttls()</code> to send your emails securely.</p>
<pre>
from email.utils import make_msgid

# Inherit the msg from above example.
msg['Message-Id'] = make_msgid('example.com')

smtp = smtplib.SMTP('smtp.example.com', 587)
smtp.starttls()
smtp.login('sender@example.com', 'emailpassword')
smtp.sendmail(sender, to, msg.as_string().encode('utf-8'))
smtp.quit()
</pre>
<p>Note that the message id it generated will use the host name of your current machine if you do not specify.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://luxing.im/sending-email-with-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">629</post-id>	</item>
		<item>
		<title>Merging Chef JSONs into 1 template</title>
		<link>https://luxing.im/merging-chef-jsons-into-1-template/</link>
					<comments>https://luxing.im/merging-chef-jsons-into-1-template/#respond</comments>
		
		<dc:creator><![CDATA[Luxing Huang]]></dc:creator>
		<pubDate>Tue, 02 Feb 2016 18:15:12 +0000</pubDate>
				<category><![CDATA[Techie Stuff]]></category>
		<category><![CDATA[chef]]></category>
		<category><![CDATA[environment]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[role]]></category>
		<guid isPermaLink="false">https://luxing.im/?p=595</guid>

					<description><![CDATA[Recently I am playing with Chef and I am having fun on some software with a little difference across different VMs. For example, on VM1: at log.xml: ... verbosity=INFO ... On VM2 it is set to ERROR, VM3 is set to DEBUG, etc. TL;DR: https://github.com/hlx98007/deployment-scripts/blob/master/chef_scripts/merge.py We know this can be separated by Chef Environment or &#8230; <p class="link-more"><a href="https://luxing.im/merging-chef-jsons-into-1-template/" class="more-link">Continue reading<span class="screen-reader-text"> "Merging Chef JSONs into 1 template"</span></a></p>]]></description>
										<content:encoded><![CDATA[<p>Recently I am playing with Chef and I am having fun on some software with a little difference across different VMs. For example, on VM1:<br />
at log.xml:</p>
<pre>
...
verbosity=INFO
...</pre>
<p>On VM2 it is set to <code>ERROR</code>, VM3 is set to <code>DEBUG</code>, etc.<br />
<span id="more-595"></span><br />
TL;DR: <a href="https://github.com/hlx98007/deployment-scripts/blob/master/chef_scripts/merge.py" target="_blank">https://github.com/hlx98007/deployment-scripts/blob/master/chef_scripts/merge.py</a></p>
<p>We know this can be separated by Chef Environment or Chef Role depend on how you set it up. Let&#8217;s say, I am using environment for this configuration.</p>
<pre>
{
  "name" : "vm1"
  ...
  "log_level" : "INFO",
  ...
}
</pre>
<p>I assume that you can derive the other VM template file on your head.</p>
<p>OK. I happen to manage a large group of Chef managed laboratories during my internship. We have several development environments and several test environments. And those values are apparently not secret (to our employees). So we have the need to manage them. With the complexity of our product, if any new key is added to, or some old keys are deleted from the environment file, we need to add/subtract the same key to each environment file across all my responsible labs.</p>
<p>This is a pain!</p>
<p>So we have a brilliant idea to include all labs detail into 1 master <code>template.json</code>. Like this:</p>
<pre>
{
  "name" : { // We must have a "name" key due to it's Chef!
    "default" : "",
    "vm1" : "vm1",
    "vm2" : "vm2",
    ...
  },
  ...
  "log_level" : {
    "default" : "INFO",
    "vm2" : "ERROR",
    "vm3" : "DEBUG",
    ...
  },
  ...
}
</pre>
<p>Looks neat? The keyword to any merged template is the &#8220;default&#8221; keyword, or anything you define. As long as we just keep the 1 template file, we can version control it, tag it however we like. In the Python script I wrote, I used &#8220;template_default&#8221; keyword.</p>
<p>We will talk about how to extract those values in the next blog post, here, we will talk about how to merge those files in Python.</p>
<p>In Python&#8217;s eye, JSONs are dictionaries. Dictionaries can have indefinite depth and it is not easy to create the same structure with an empty dict. I believe it is best to do this recursively, calling a <code>merge()</code> to a smaller subset of itself, and create the result to a new dictionary.</p>
<p>Each time when we call the <code>merge()</code>, we will create an empty dictionary to hold the copied values and eventually return to the upper function. Eventually we will have the correct structure and data.</p>
<p>Consider the following scenarios and my decisions when we call <code>merge.py env1.json env2.json template.json</code>, we will extract the keys on the current level only for env1.</p>
<pre>for key in env1_json.keys()</pre>
<p>If env2 has the new key, we can do <code>merge.py env2.json template.json template2.json</code> to merge the missing keys. (notes at the bottom)</p>
<pre>
0. value of env1 is exactly the same to env2. (copy and continue)
1. value of env1 is a string, value of env2 is a string
  1.1 they equal (copy and continue)
  1.2 they differ (build the template structure)
2. value of env1 is a string, value of env2 is a dict
  2.1 env2 is not a template style dict (notify and stop)
  2.2 env2 is a template style dict
    2.2.1 env1 does not exist (add)
    2.2.2 env1 does exist but with different value (update)
    2.2.3 env1 does exist and with the same value (update)
3. both values of env1 and env2 are dicts.
  3.1 env1 is a template style dict (stop and report)
  3.2 env2 is a template style dict (stop and report)
  3.3 env1 and env2 are both normal dicts (recursive call on itself)
</pre>
<p>With those points sorted out, the program is not difficult to write.</p>
<p>Known features/bugs that not yet categorized:<br />
1. When env1 has some missing keys and merge with a template json, such keys will be lost in <code>merged.json</code>. (may be we do want to delete that key in the template?)</p>
]]></content:encoded>
					
					<wfw:commentRss>https://luxing.im/merging-chef-jsons-into-1-template/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">595</post-id>	</item>
	</channel>
</rss>
