tag:blogger.com,1999:blog-55821826121878333272024-03-13T23:51:01.750-07:00John Tells All<p>This blog is for technical and personal posts. Over different jobs over the years I've written hundreds of articles, and now it's time to share with everyone!
</p>John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.comBlogger242125tag:blogger.com,1999:blog-5582182612187833327.post-54501021483248429592019-07-13T12:39:00.000-07:002019-07-13T12:39:09.355-07:00NEW SITE!hi all!<br />
<br />
Thanks to the friendly people at Gozcodes, I now have a new site!<br />
<br />
=> <a href="https://johntellsall.com/">https://JohnTellsAll.com</a><br />
<br />
This Blogger domain might go away at some point, so update your links.<br />
<br />
<br />John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com1tag:blogger.com,1999:blog-5582182612187833327.post-87443066565983325992019-03-10T19:28:00.004-07:002019-03-10T19:28:50.723-07:00Testing Pyramid and Consequences... Developer Edition this Wednesday<br />
giving a talk this Wednesday in Santa Monica! Testing Pyramid and Consequences - for developers. I gave this talk last month to QA people who really enjoyed it!<br />
<br />
<a href="https://www.meetup.com/testable/events/wmkmdqyzfbrb/">https://www.meetup.com/testable/events/wmkmdqyzfbrb/</a>John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-11944257007796500122019-03-10T19:21:00.001-07:002019-03-10T19:21:59.428-07:00Testing Pyramid and Consequences, video editionthanks to Evgeny Kim, I'm on the youtubes!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/zGRyJUro7Tg/0.jpg" src="https://www.youtube.com/embed/zGRyJUro7Tg?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br />
<a href="http://2.bp.blogspot.com/-1lz7a2YMcQE/XIXGG013ZtI/AAAAAAAAgCo/hNL_Wj_JOX4A1QGG1ca87nC7nwdcx6V7ACK4BGAYYCw/s1600/Screen%2BShot%2B2019-03-10%2Bat%2B7.20.11%2BPM.png" imageanchor="1"><img border="0" height="195" src="https://2.bp.blogspot.com/-1lz7a2YMcQE/XIXGG013ZtI/AAAAAAAAgCo/hNL_Wj_JOX4A1QGG1ca87nC7nwdcx6V7ACK4BGAYYCw/s320/Screen%2BShot%2B2019-03-10%2Bat%2B7.20.11%2BPM.png" width="320" /></a>John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-55600035053333228162019-02-28T11:22:00.002-08:002019-02-28T11:22:32.794-08:00Testing Pyramid vs... Testing Trophy?<div dir="ltr" style="line-height: 1.4048784; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">I was honored to chat to a bunch of professional QA people last night about Testing Pyramid and Consequences, details on a previous blog post. People last night seemed interested and curious in the "Testing Trophy" concept. That is, in contrast to the Testing Pyramid, tests should be mostly integration, with a few UI and unit tests. In this way we get the most business value for each test we write.</span></span></div>
<div dir="ltr" style="line-height: 1.4048784; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;"><br /></span></span></div>
<div dir="ltr" style="line-height: 1.4048784; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">I'm a fan of the Testing Pyramid (lots of unit tests), however I'm an even bigger fan of paying really close attention to business value. Tests aren't free, and they aren't cheap! They can have bugs, and can be over-designed, so they function as "change detector" as opposed to a safety net. </span></span></div>
<div dir="ltr" style="line-height: 1.4048784; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;"><br /></span></span></div>
<div dir="ltr" style="line-height: 1.4048784; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">From Kent C Dodds:</span></span></div>
<div dir="ltr" style="line-height: 1.4048784; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">"Testing Trophy</span></span></div>
<span id="docs-internal-guid-4a188653-7fff-aac6-922f-906fe9c0d12a"><span style="font-family: inherit;"><br /></span></span>
<br />
<div dir="ltr" style="line-height: 1.4048784; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">A general guide for the </span><span style="background-color: transparent; color: #14171a; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">return on investment</span><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> of the different forms of testing with regards to testing JavaScript applications.</span><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">- End to end: Cypress</span><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">- Integration, Unit: Jest</span><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">- Static:</span><a href="https://twitter.com/flowtype" style="text-decoration: none;"><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span></a><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Flow, ESLint"</span></span></div>
<div dir="ltr" style="line-height: 1.4048784; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://pbs.twimg.com/media/DVUoM94VQAAzuws.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="688" data-original-width="679" height="320" src="https://pbs.twimg.com/media/DVUoM94VQAAzuws.jpg" width="315" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
From <a href="https://twitter.com/kentcdodds/status/960723172591992832?lang=en">@kentcdodds tweet</a></div>
<div dir="ltr" style="line-height: 1.4048784; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: #14171a; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span></div>
John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-30501308902842456052019-02-24T14:40:00.001-08:002019-03-22T10:31:39.594-07:00new talk: Testing Pyramid and ConsequencesI'm giving a new talk! This Wednesday in Pasadena for the <a href="https://www.meetup.com/Los-Angeles-Software-Testing-Meetup/">LA Software Testing</a> meetup, and again soon in Santa Monica at the <a href="https://www.meetup.com/testable/">Testable LA</a> meetup.<br />
<br />
The traditional testing pyramid is a useful tool for investing in tests which deliver business value... but there are a lot of subtleties. In this talk I'll highlight each area of the Pyramid, then discuss extensions and variations, so that we all can more fully deliver wonderful quality code, quickly!<br />
<br />
Slides on google docs: <a href="https://docs.google.com/presentation/d/1pBzn_3wTH2FSoWVkGtqwCV5WOiMD6Mrav9hB8-iAuvs/edit?usp=sharing">Testing Pyramid and Consequences</a><br />
<br />
Here's a <a href="https://www.youtube.com/watch?v=zGRyJUro7Tg">recording</a> from the LA Software Testing meetup.<br />
<br />
Resources:<br />
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Meetups: </span><a href="https://www.meetup.com/testable/" style="text-decoration: none;"><span style="background-color: transparent; color: #0097a7; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">Testable LA</span></a><span style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">, </span><a href="https://www.meetup.com/Los-Angeles-Software-Testing-Meetup/" style="text-decoration: none;"><span style="background-color: transparent; color: #0097a7; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">LA Software Testing</span></a><span style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Brian Okken - </span><a href="http://pythontesting.net/" style="text-decoration: none;"><span style="background-color: transparent; color: #0097a7; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">Test and Code</span></a><span style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> podcast</span></span></div>
</li>
</ul>
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Martin Fowler - </span><a href="https://martinfowler.com/articles/practical-test-pyramid.html" style="text-decoration: none;"><span style="background-color: transparent; color: #0097a7; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">Practical Test Pyramid</span></a><span style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">article</span></span></div>
</li>
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">Books: Refactoring, NoSQL Distilled</span></span></div>
</li>
</ul>
<li dir="ltr" style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Lisa Crispin: </span><a href="https://agiletester.ca/" style="text-decoration: none;"><span style="background-color: transparent; color: #0097a7; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">Agile Testing</span></a><span style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> books</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: #595959; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="color: #0097a7; font-family: inherit; vertical-align: baseline; white-space: pre-wrap;"><a href="https://safaribooksonline.com/" style="text-decoration-line: none;">Safari Online</a></span><span style="font-family: inherit; vertical-align: baseline; white-space: pre-wrap;"> books, training videos</span></div>
</li>
</ul>
<div>
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://i1.wp.com/www.communitycatspodcast.com/wp-content/uploads/2018/03/Cat-PyramidRev2.jpg?fit=800%2C800&ssl=1" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="800" height="320" src="https://i1.wp.com/www.communitycatspodcast.com/wp-content/uploads/2018/03/Cat-PyramidRev2.jpg?fit=800%2C800&ssl=1" width="320" /></a></div>
<br />John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-37677414613980268452019-02-20T15:19:00.000-08:002019-02-20T15:19:09.093-08:00tradeoffs of having a distributed companyif y'all have a company and are considering making it mostly remote/distributed, track down talks by Mitchell "Hashicorp" Hashimoto. His co makes Vagrant and Terraform and Packer and Vault. Anyway he gave a talk in which he talked about having a mostly-distributed company. He said a lot of things were much cheaper (renting offices), but a lot of things were more expensive/awkward (per-site licensing for video equipment). Overall he called it "a wash"<br />
<br />
Here's the talk, recorded at Replicated in Culver City, CA => https://www.youtube.com/watch?v=iV5doaYReyUJohn Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-76169254793335177752018-11-21T11:32:00.000-08:002018-11-21T11:32:00.214-08:00importing AWS resources into TerraformTerraform is a wonderful tool! It helps simplify DevOps work. It turns the thorny bramble of delicate networking, users, databases, and virtual machines into a simple and well-running machine. It allows us to chant "infrastructure as code" to the amusement of well-meaning technologists. Best of all: it lets us have consistent environments. A dev can wreak havoc, learn things, then create a Terraform patch that applies to the entire collection of systems, making everything just a little bit cleaner and better understood.<br />
<br />
Terraform, although being a moderately baked and flexible tool, has a few warts. One challenge is that it doesn't play with manually-created resources very well. If you create some users in Terraform, and some users in the AWS Console, applying Terraform later will try to <i>delete</i> the manual users. Terraform imagines that it is the alpha and omega, and that all things are as it thinks they are.<br />
<br />
Additionally, Terraform isn't very smart about <i>importing</i> manually-created resources. Traditionally we have to use a third-party tool, <span style="font-family: Courier New, Courier, monospace;">terraforming</span><span style="font-family: inherit;">, to do this task. The combination of </span><span style="font-family: Courier New, Courier, monospace;">terraform</span><span style="font-family: inherit;"> (to create/update resources) and </span><span style="font-family: Courier New, Courier, monospace;">terraforming</span><span style="font-family: inherit;"> (to import manually-created resources) is useful.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Example: here's how to import all the SNS Topics ("snst") to a Terraform file:</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">$ AWS_PROFILE=myprofile terraforming snst --region=myregion | tee temp-sns.tf</span><br />
<span style="font-family: Courier New, Courier, monospace;">resource "aws_sns_topic" "dynamodb" {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> name = "dynamodb"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> display_name = ""</span><br />
<span style="font-family: Courier New, Courier, monospace;"> policy = ...</span><br />
<br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: inherit;">Now, edit the temp-sns.tf file to make things more clear and regular, then plan and apply with Terraform as per usual.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">In AWS, users aren't just users, they're defined in several different types of I</span>dentity and Access Management (IAM) resources. Here's how to import just the simple user records:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">AWS_PROFILE=myprofile terraforming iamu --region=myregion | tee temp-iamu.tf</span><br />
<span style="font-family: Courier New, Courier, monospace;">resource "aws_iam_user" "john" {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> name = "john@johntellsall.com"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> path = "/"</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<br />
In practice, users aren't useful except as combined with Roles, Groups, and Policies. It's a whole thing. Fortunately, here's a bit of code which imports all AWS IAM user-related permissions into a single Terraform file:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">terraforming help | egrep -o 'iam\w+' | AWS_PROFILE=myprofile xargs -I{} -t terraforming {} --region=myregion >> temp-users.tf</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: inherit;">Now, you'll be left with a 1,000-line Terraform file for further editing. This isn't that fun, however once you're done, you can move this file into its own module, and apply the same users/groups/permissions on all your environments!</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Terraform is a wonderful tool, and in combination with Terraforming and a bit of work, will make your DevOps work a lot simpler!</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"><br /></span>John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-6083287384437733292018-11-15T16:39:00.002-08:002018-11-15T16:39:32.473-08:00Docker leads to so much win (psql ftw)Containers are an incredibly effective way to be more productive. I'd put it on the same order of convenience as version control: a bit of effort to learn but each technology allows tremendous flexibility and safety and enjoyment out of programming.<br />
<br />
Just now I wanted to verify my backups. I didn't want to run Postgres directly on my macOS, as I'm going to nuke the database after a few tests. So instead I started one in its own container. I ran it on a weird port so I couldn't accidentally use the wrong database/proxy:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ docker run --name temp_postgres -p 5555:5432 -d postgres:9.6</span><br />
<br />
Next I verify my new database is up and answering commands:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ PGPASSWORD='' psql postgresql://postgres@localhost:5555/postgres -c 'select now()'</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"><i> now</i></span><br />
<span style="font-family: Courier New, Courier, monospace;"><i>-------------------------------</i></span><br />
<span style="font-family: Courier New, Courier, monospace;"><i> 2018-11-16 00:32:31.104194+00</i></span><br />
<span style="font-family: Courier New, Courier, monospace;"><i>(1 row)</i></span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">The commands worked on the first try! Now I can go ahead and do my real work of verifying backups, then my task will be finished and I'll move on to the next one. Win!</span><br />
<span style="font-family: inherit;"><br /></span>John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-19999527658107945492018-11-11T09:52:00.003-08:002018-11-11T09:52:52.499-08:00fast searches with custom search enginesI do a lot of learning, which today means tons of searching on different websites. I've found a trick which makes my job a <b>lot</b> faster -- custom search aliases. In the URL bar, I can type "<span style="font-family: Courier New, Courier, monospace;">k explain</span>" to automatically go to the Kubernetes.io site, search for "explain", and give me the results. When I need another cat image for one of my presentations, I type "<span style="font-family: Courier New, Courier, monospace;">gis cat</span>" into the URL bar to ask Google Image Search for some inspirational furriness. Man.cx has all the Linux manpages. Python.org has all the Python modules carefully documented. I have aliases for all of the above and use them <i>constantly</i>.<br />
<br />
Here's how to make your daily searches much, much easier:<br />
<br />
<h3>
Easy, very fast keyword searches</h3>
<br />
1. go to site, do search. Example: <a href="https://kubernetes.io/">https://kubernetes.io</a>, search for "explain"<br />
2. URL has term in bar. Replace it with "%s". For the above example you'll get <span style="font-family: Courier New, Courier, monospace;">https://kubernetes.io/docs/search/?q=%s</span><br />
3. copy URL<br />
4. right click URL, select "Edit Search Engines"<br />
5. under Other Search Engines, click Add button<br />
6. type something for Search Engine ("kubernetes"), then a short alias ("k"), and for the URL, paste the URL with "%s" in it<br />
7. click Add<br />
<br />
<h3>
Testing</h3>
<br />
In URL bar, type alias then another search term. e.g. "k beer". The resulting page will be a Search Results page, with your new term in it.<br />
<br />
<h3>
Compatibility</h3>
<div>
<br /></div>
<div>
The above instructions are for Google Chrome, but all browsers support something like this.</div>
<div>
<br /></div>
<br />John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-77129330448064575372018-07-20T10:32:00.000-07:002018-07-20T10:32:24.461-07:00TIP: Bash has “global search and replace”! TIP: Bash has “global search and replace”! It works with the history mechanism. Example, the bangbang (<span style="font-family: Courier New, Courier, monospace;">!!</span><span style="font-family: inherit;">) command repeats the previous command:</span><br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ !! # repeat previous command</span><br />
<br />
Adding a colon (<span style="font-family: Courier New, Courier, monospace;">:</span>) and then a letter or two will modify the command before running it. A useful modifier is "<span style="font-family: Courier New, Courier, monospace;">p</span>" for printing. That is:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ !!:p # repeat previous command, but just :p-print it</span><br />
<br />
This is useful because you can use up-arrow to now go to the previous command and edit it interactively.<br />
<br />
For non-interactive editing, you can do global search and replace! Example: use the "repeat previous command" command, bangbang (!!). Then modify it (:), then say "global search" (gs). To do this to find "one" and replace it with "two", use this command:<br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">$ !!:gs/one/two</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
In my real-world case, I'd already run a command to deploy my Development server with Terraform. The specific command is:<br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">AWS_PROFILE=development terraform plan -var-file=../config/development.tfvars</span><br />
<br />
This command was in my shell history. I want to recall this command (bangbang, aka <span style="font-family: Courier New, Courier, monospace;">!!</span>), then search and replace "development" with "staging" to use Terraform to deploy to my staging environment.<br />
<br />
Command:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ !!:gs/development/staging</span><br />
<br />
Got me:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">AWS_PROFILE=staging terraform plan -var-file=../config/staging.tfvars</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<h4>
<span style="font-family: inherit;">Resources:</span></h4>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">- <a href="https://devhints.io/bash">Bash scripting cheatsheet</a></span>John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-87559882776245723512018-07-20T10:04:00.000-07:002018-07-20T10:04:07.535-07:00running My Traceroute (aka Matt's traceroute) (MTR) on macOS<br />
<a href="https://en.wikipedia.org/wiki/MTR_(software)">Mtr</a> is a wonderful program that combines ping and traceroute. It shows you each hop along a path to another host on the internet, and how long each hop takes. It's my #1 go-to tool to debug wifi / networking / DNS issues. And, it's pretty!<br />
<br />
Anyway it requires extra privileges, so it's a bit fiddly to run. Even worse, The Internet Is Wrong on this topic, there's lots of bad advice.<br />
<br />
Here's how to install and run mtr on a macOS machine:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">brew install mtr</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">PATH=$PATH:/usr/local//Cellar/mtr/0.92/sbin sudo mtr 8.8.8.8</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: inherit;">The "8.8.8.8" is a magic IP. Easy to remember, it's a public DNS router that our friends at Google make available to the public. You can use any IP or domain name here. I use the all-8s IP, because sometimes my DNS isn't working, so pinging a raw IP will tell me if my DNS is acting up, and if so, which one.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Here's what it looks like:</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><a href="http://4.bp.blogspot.com/-i3DknC4Vjas/W1IVIxYkzvI/AAAAAAAAdZY/vblS7-ZP_LYwYrW1RAAbh--G3YM7_Dd0ACK4BGAYYCw/s1600/Screen%2BShot%2B2018-07-20%2Bat%2B9.58.03%2BAM.png" imageanchor="1"><img border="0" height="200" src="https://4.bp.blogspot.com/-i3DknC4Vjas/W1IVIxYkzvI/AAAAAAAAdZY/vblS7-ZP_LYwYrW1RAAbh--G3YM7_Dd0ACK4BGAYYCw/s320/Screen%2BShot%2B2018-07-20%2Bat%2B9.58.03%2BAM.png" width="320" /></a></span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">If you press </span><b style="font-family: "Courier New", Courier, monospace;">d</b><span style="font-family: inherit;">, it switches displays to more visual. This lets the "bad actors" in the network jump out:</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><a href="http://4.bp.blogspot.com/-SBp758Sh1DY/W1IVKsJhdbI/AAAAAAAAdZg/TfiiA7XTWBAVZRe9FdR5ppwa28gXulA2wCK4BGAYYCw/s1600/Screen%2BShot%2B2018-07-20%2Bat%2B9.58.08%2BAM.png" imageanchor="1"><img border="0" height="200" src="https://4.bp.blogspot.com/-SBp758Sh1DY/W1IVKsJhdbI/AAAAAAAAdZg/TfiiA7XTWBAVZRe9FdR5ppwa28gXulA2wCK4BGAYYCw/s320/Screen%2BShot%2B2018-07-20%2Bat%2B9.58.08%2BAM.png" width="320" /></a></span><br />
Since this is a terminal-based CLI program it's easy to install and run on a server. Maybe your local network is good, but the server's network or DNS is acting up -- mtr will make issues really easy to see and fix!<br />
<br />John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-27961526603445633622018-07-19T09:30:00.002-07:002018-07-19T09:30:32.956-07:00tech book recommendationsRecently I was asked about Python books covering Object Oriented programming for someone coming from another language. Here are some resources:<br />
<br />
- I recommend subscribing to <a href="https://www.safaribooksonline.com/">Safari Books Online</a>. They have <i>jillions</i> of books and videos, including "Python Beyond The Basics - Object Oriented Programming" (high-ranked video). It's $40/month. If you're a professional Dev or DevOps, or trying to be, it's an easy investment.<br />
<br />
- the class section of "<a href="https://www.safaribooksonline.com/library/view/modern-python-cookbook/9781786469250/">Modern Python Cookbook</a>" (book) has tons of real-world Python idioms: designing classes with lots vs little processing, classes with <span style="font-family: Courier New, Courier, monospace;">__slots__</span>, and advanced class design... Actually this book looks great I'm going to read it.<br />
<br />
- David Beazley's "<a href="https://www.safaribooksonline.com/library/view/python-cookbook-3rd/9781449357337/">Python Cookbook</a>" is great, overflowing with real-world problems, solutions, and discussion.<br />
<br />
- in the <a href="https://www.lapl.org/collections-resources/online-learning">Los Angeles region all the Lynda.com</a> tech resources are <i>freeee</i> with an LA public library card.<br />
<br />
- the "Cookbook" books I find are good for someone coming from another language, the books don't spend 100 pages talking about dictionaries and strings and so forth. It turns out there's tons of Cookbooks nowadays: data visualization, machine learning, testing, you name it!John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-78499008532263859152018-07-06T21:34:00.000-07:002018-07-06T21:34:52.595-07:00Kafka on macOSGenerally I run everything in Docker: it's less fiddly, and I can do a clean uninstall very easily. Alas Docker networking is different, and changes every few months as Docker makes things easier... by changing the networking.<br />
<br />
As of July 2018 here's the easiest way I've found to run Kafka on macOS:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">brew install kafka kafkacat zookeeper</span><br />
<span style="font-family: Courier New, Courier, monospace;">brew services start zookeeper</span><br />
<span style="font-family: Courier New, Courier, monospace;">brew services start kafka</span><br />
<br />
Once Kafka is up, list out the brokers:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ kafkacat -L -b localhost</span><br />
<span style="font-family: Courier New, Courier, monospace;">Metadata for all topics (from broker -1: localhost:9092/bootstrap):</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 1 brokers:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> broker 0 at 192.168.0.133:9092</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 0 topics:</span><br />
<br />
Now let's go to the mysterious directory that has tons of good tools. Create a topic, then use "kafkacat" again to verify our new topic has been created:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ cd /usr/local/Cellar/kafka/*/libexec/bin</span><br />
<span style="font-family: Courier New, Courier, monospace;">./kafka-topics.sh --create --topic <b>example-topic</b> --zookeeper localhost:2181 --partitions 1 --replication-factor 1</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">$ kafkacat -L -b localhost</span><br />
<span style="font-family: Courier New, Courier, monospace;">Metadata for all topics (from broker -1: localhost:9092/bootstrap):</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 1 brokers:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> broker 0 at 192.168.0.133:9092</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 1 topics:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> topic "<b>example-topic</b>" with 1 partitions:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> partition 0, leader 0, replicas: 0, isrs: 0</span><br />
<br />
Woot! My thanks to <a href="https://gist.github.com/jarrad/3528a5d9128fe693ca84#gistcomment-2323553">springheeledjak</a> and <a href="https://gist.github.com/pkafel/7cca260427532bf64c58407964c623d2">pkafel</a>!<br />
<br />John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-57567828776477018042018-06-23T12:16:00.003-07:002018-06-23T12:16:37.465-07:00Quality Code in Practice<span style="font-family: inherit;">Developers like to write code. They like to type fast, to work fast, and deploy fast. This is fine. We all like this, it's fun!</span><br />
<span style="font-family: inherit;">A more high-level view is that as a business, as a team we want to <i>deliver value</i> fast. This is harder: <i>which</i> value to <i>what</i> audience are we serving? If we deliver buggy code to the client, no one is happy. If we make some users happy but our core audience is not served, then we haven't really delivered on our goals. Our goal as professionals, as entrepreneurs, is to find/create an audience, and serve that audience by giving them value.</span><br />
<span style="font-family: inherit;">In practice, "clean" code helps us work fast and also deliver value to our audience. Clean in this case meaning free of bugs, clearly designed, and of a design which directly meets the needs of our audience.</span><br />
Automated workflow tools can help us move forward. They run very quickly, giving us positive feedback that what we write is legible and missing the most egregious errors. The basic categories of tools are 1) surface-level syntax, 2) language-centric analysis, 3) project-based unit and other tests.<br />
For a recent project, this is our top-level Makefile. It lets us as developers get rapid feedback on the quality of our project. Also, having a single file lets these tasks be repeatable by a Continuous Integration system, so we can be confident things don't break if we had too much coffee and committed something without running tests.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">all:</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">auto-fix:</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>git ls-files '*.py' \</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>| xargs autopep8 --in-place --aggressive</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">lint:</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>flake8</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">clean:</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>find . -name '*.pyc' | xargs rm</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">run:</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>cd cj ; ./manage.py run</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">test:</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>pytest</span><br />
<div>
<br /></div>
John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-15082023621741101632018-06-18T07:26:00.000-07:002018-06-18T07:27:51.212-07:00Easy DockerThis talk was given at the <a href="https://www.meetup.com/ladjango/events/250439537/">LA Django meetup</a> in DTLA on 6/19/2018. My thanks to Anthony at Gridspace for sponsoring! Also thanks to Marcel for inviting me again.<br />
<br />
This page is <a href="http://bit.ly/jta-easy-docker">http://bit.ly/jta-easy-docker</a><br />
<br />
The slides are <a href="https://docs.google.com/presentation/d/1F5OCzifaGDRznCoYvsBGmdykJI15a8DvVysIkWt1Xlo/edit?usp=sharing">in Googledocs</a>, source code is in Github => <a href="https://github.com/johntellsall/easy-docker">https://github.com/johntellsall/easy-docker</a><br />
<br />
<br />John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-78016052481708391442018-06-14T11:26:00.003-07:002018-06-14T11:26:57.391-07:00Testing Pyramid and Feedback Loops (Platonic Solids of Quality)This talk was given 6/14/2018 in sunny downtown Santa Monica, at Carbon Five. Rit Li's Testable group is all about, well, testing, especially for webapps. Given my focus on being an expert at "quality, dev, and devops", this group is perfect for me!<br />
<br />
Here's the event link => https://www.meetup.com/testable/events/jsjqjpyxjbkb/<br />
<br />
Here are the slides, in Google Docs => <a href="https://docs.google.com/presentation/d/149jImYeWq0w0QRy1hb-yaq09UdFocLKDqANQxOHR9gU/edit?usp=sharing">Testing Pyramid and Feedback Loops</a><br />
<br />
This page is http://bit.ly/jta-platonic2 , I'll add more to it as different versions of the talk appear. Please send me photos!<br />
<br />
<br />John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-51234059702691361382018-06-07T10:00:00.000-07:002018-06-07T10:00:01.190-07:00Appearances June 2018hi all! Here are upcoming events at which I'll be speaking<br />
<br />
- 6/7: private event, talking about Infrastructure as Code on a panel<br />
<br />
This is going to be fun! I haven't spoken on a panel before. The audience is a bit different, C-level executives. I won't have any slides filled with dense code, but I <i>will</i> have a cat t-shirt. My goal is to sip wine, be quiet, and support my fellow speakers.<br />
<br />
- 6/14 at Testable LA, I'll be talking about the Testing Pyramid and Feedback Loops. Feel free to come by and say hi! Meetup link => <a href="https://www.meetup.com/testable/events/jsjqjpyxjbkb/">Testable LA: Monthly Meetup</a><br />
<br />
This talk is an expansion of my <a href="http://bit.li/jta-platonic">Platonic Solids of Quality</a> work. In this update I'll skim over the Testing Pyramid, then enumerate the different Feedback patterns we use to write code but also steer the ship of our company.<br />
<br />
The traditional Testing Pyramid has higher-level UI tests on top, medium-level API tests in the middle, and small Unit Tests on the bottom. Tests higher in the pyramid run more code, but also give less specific feedback about exactly what's going on. Low level unit tests are great in that they're super fast, easy to write, and allow us to validate exactly which inputs correspond to exactly which outputs. In practical, for-real, professional projects, how much effort should be spent at which types of tests? How do we as a team achieve our goal with the least amount of chaos and drama?<br />
<br />John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-20973913211569870432018-05-23T10:34:00.004-07:002018-05-23T10:34:47.793-07:00CI Tip: block insecure changes to your source codeAs a dev or devops person, it's pretty easy to accidentally expose AWS or other secrets by putting them into "temporary" code or environment files. Once a secret appears in version control, it should no longer be trusted, go ahead and rotate the key.<br />
<br />
Here's how to write a checker, so that secrets won't make it into source code! This is perfect for a Git commit hook. The important feature to use is Perl-style regular expressions, which allow you to say "match this exactly N number of times". Also, the "-w" flag to Ack lets us match word boundaries. Thus, if something is a word, and exactly some number of characters long, we flag it.<br />
<br />
Example:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ echo 'I love gin' | ack -w '[a-z]{3}'</span><br />
<span style="font-family: Courier New, Courier, monospace;">I love <b>gin</b></span><br />
<br />
This example finds words of exactly three letters. The word "gin" is found, as it's exactly three characters. The second word "love" is not flagged, even though it has 3 characters included in it, because we added the "-w" flag to only find words. "Gin" has a non-letter on either side, so it's a word, so we match it.<br />
<br />
To catch AWS keys, search for "words" of exactly 20 characters, uppercase letters and numbers only:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ ack -lw '[0-9A-Z]{20}'</span><br />
<span style="font-family: Courier New, Courier, monospace;">env-sales</span><br />
<span style="font-family: Courier New, Courier, monospace;">web-services/src/config/configResolver.ts</span><br />
<span style="font-family: Courier New, Courier, monospace;">.env</span><br />
<br />
Ah: two local environment files have AWS keys, which is okay. These are not checked in to Git. However, a key snuck in to another file, in source code! Now that Ack alerted me to a mislaid key, I can go fix it and make our system more secure. Win!<br />
<br />
<br />John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-62597243898678721112018-05-21T11:48:00.001-07:002018-05-21T11:48:10.091-07:00Sublime tips and tricks<a href="https://generalassemb.ly/blog/sublime-text-3-tips-tricks-shortcuts/">https://generalassemb.ly/blog/sublime-text-3-tips-tricks-shortcuts/</a><br />
<br />
Things I learned:<br />
<br />
- ⌘-SHIFT-J = select everything that's similarly indented<br />
<br />
- CTRL-⌘-UP = move selection up (vs dragging the region with the mouse)<br />
<br />
- CTRL-SHIFT-K = delete entire current line. I used to do ⌘-L, Delete dozens of times a day. Now there's another way!John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-68491266923673133042018-05-21T09:35:00.002-07:002018-05-21T09:35:41.742-07:00TIP: you can exclude file types when searching for stuff in Git!Git isn't just a database, it's a comprehensive searching system XX. You can exclude file types when searching for stuff in Git!<br />
<br />
Example: the Development branch broke some time between two Git commits. I want to find the error but don't want to look at huge piles of changes. I don’t think the front end Vue files broke the build, so let's find changes excluding those files, so I can find the error.<br />
<br />
First, I list the files between the two commits, to see if it’s roughly what I want:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">git diff --stat c7b5d2d^..2de4986 -- ':(exclude)*.vue'</span><br />
<br />
Looks good. Next, I list the actual content by zapping the "--stat" argument:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">^--stat^</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
Or: <span style="font-family: Courier New, Courier, monospace;">git diff c7b5d2d^..2de4986 -- ':(exclude)*.ts'</span><br />
<br />
I found the problem! Yay, Git!<br />
<br />
More info:<br />
- <a href="http://kgrz.io/git-intro-to-pathspec.html">Git pathspec</a><br />
- Bash <a href="https://www.gnu.org/software/bash/manual/bashref.html#Event-Designators">"Event Designators"</a> (the upcaret to search and replace previous line)John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-84920419382954625362018-05-18T15:02:00.003-07:002018-05-18T15:02:56.326-07:00console.log macro in Sublime Text<div>
Here's how to make a selection macro in Sublime Text. </div>
<div>
<br /></div>
<div>
Type the word "beer", select it, then press a key to turn it into a console.log statement!</div>
<div>
<br /></div>
<div>
Here's how to do it:</div>
<div>
<br /></div>
<div>
1. Create the console.log template:</div>
<div>
<br /></div>
<div>
Click <i>Tools > Developer > New Snippet...</i></div>
<div>
<br /></div>
<div>
Paste the following:</div>
<div>
<br /></div>
<span style="font-family: Courier New, Courier, monospace;"><snippet></snippet></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span><content><![CDATA[</content></span><br />
<span style="font-family: Courier New, Courier, monospace;">console.log("$SELECTION");</span><br />
<span style="font-family: Courier New, Courier, monospace;">]]></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span><tabtrigger>log</tabtrigger></span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span><!-- optional: <scope>source.typescript</scope> --></span><br />
<span style="font-family: Courier New, Courier, monospace;"></span><br />
<div>
<br /></div>
<div>
Save the above as <span style="font-family: Courier New, Courier, monospace;">log.sublime-snippet</span></div>
<div>
<br /></div>
<div>
2. Create a keybinding to the snippet:</div>
<div>
<br /></div>
<div>
Click <i>Sublime Text > Preferences > Key Bindings</i></div>
<div>
<br /></div>
<div>
Paste this bit into the middle of the keymap:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> "keys": ["ctrl+shift+l"], </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> "command": "insert_snippet", </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> "args": { "name": "Packages/User/log.sublime-snippet" } },</span></div>
</div>
<div>
<br /></div>
<div>
Save it.</div>
<div>
<br /></div>
<div>
To use, type <span style="font-family: Courier New, Courier, monospace;">beer</span> in your program. Double-click to select it, then hit your "log this message" keyboard command <span style="font-family: "Courier New", Courier, monospace;">ctrl+shift+l.</span></div>
<div>
<span style="font-family: "Courier New", Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: inherit;">Boom!</span></div>
<div>
<span style="font-family: "Courier New", Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">console.log("beer");</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: "Courier New", Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: "Courier New", Courier, monospace;"><br /></span></div>
John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-67280711941079931892018-02-20T11:39:00.003-08:002018-02-20T11:39:58.712-08:00quality interactive tests with Lynx, the server-side browser<span style="font-family: inherit;">Working on a web page test on a server, but can't view the page in a normal web browser? It's easy enough to transfer the HTML to your local computer, or... use a text-mode browser!</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">The Lynx browser is tiny, fast, and supports a good part of modern web pages. It's a great tool for quickly getting a rough idea of what your page looks like.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Example: my Flask app refuses to handle authentication correctly. So, I write a API test to log in to myserver, capture the response, then write it to a server-side HTML file. Next I use Lynx to view it so I can see what it's doing!</span><br />
<span style="font-family: inherit;"><br /></span>
Here's my Registration test:<br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">def test_post(client):</span><br />
<span style="font-family: Courier New, Courier, monospace;"> "validate page that uses POST"</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> rv = client.post('/auth/register', data=dict(</span><br />
<span style="font-family: Courier New, Courier, monospace;"> email='test@example.com',</span><br />
<span style="font-family: Courier New, Courier, monospace;"> username='test',</span><br />
<span style="font-family: Courier New, Courier, monospace;"> password='test',</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ))</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if 1:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> with open('zoot.html', 'w') as pagef:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> pagef.write(rv.data)</span><br />
<br />
Run the test<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">pytest</span><br />
<br />
Next, use the server-side browser to view my output:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><b>lynx -dump -stdin < zoot.html</b></span><br />
<br />
Output:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> (BUTTON) Toggle navigation [1]test</span><br />
<span style="font-family: Courier New, Courier, monospace;"> * [2]Home</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> * [3]Log In</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">Register</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> Email test@example.com____</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Username test________________</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Password ____________________</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> Passwords must match.</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Confirm password ____________________</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> This field is required.</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Register</span><br />
<div>
<br /></div>
<div>
Note the "Passwords must match" bit. Ah, there's my bug. In the POST I'd forgotten to send both the <span style="font-family: Courier New, Courier, monospace;">password</span> and validating <span style="font-family: Courier New, Courier, monospace;">password2 </span><span style="font-family: inherit;">fields. Bug fixed, thanks to Lynx!</span></div>
John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-74632983174062410832018-02-07T22:06:00.003-08:002018-02-07T22:06:48.488-08:00Terraform and iTerm2 FTW1) install imgcat from <a href="https://iterm2.com/documentation-images.html">iTerm2 page</a><br />
2) <span style="font-family: Courier New, Courier, monospace;">brew install graphviz</span><br />
<br />
Now, when you're working on a complex set of Terraform dependencies, you can display them directly in your terminal!<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">terraform graph | dot -Tpng | imgcat</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-WQPKCoF3uB8/Wnvokyad4tI/AAAAAAAAbUI/CmhrXx6ZV1EaAdokOFMOD8ppspVhEkvlwCLcBGAs/s1600/Screen%2BShot%2B2018-02-07%2Bat%2B10.04.25%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1297" height="640" src="https://3.bp.blogspot.com/-WQPKCoF3uB8/Wnvokyad4tI/AAAAAAAAbUI/CmhrXx6ZV1EaAdokOFMOD8ppspVhEkvlwCLcBGAs/s640/Screen%2BShot%2B2018-02-07%2Bat%2B10.04.25%2BPM.png" width="516" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
(Code from the excellent book <em style="background-color: white; box-sizing: border-box; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px;"><a href="http://www.terraformupandrunning.com/" rel="nofollow" style="background-color: transparent; box-sizing: border-box; color: #0366d6; outline-width: 0px;">Terraform: Up and Running</a></em><span style="background-color: white; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px;"> by </span><a href="http://www.ybrikman.com/" rel="nofollow" style="background-color: white; box-sizing: border-box; color: #0366d6; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; text-decoration-line: none;">Yevgeniy Brikman</a><span style="background-color: white; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px;">.)</span></div>
<br />John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-65616284839670555032017-12-01T16:01:00.001-08:002017-12-01T16:01:48.648-08:00pretty titles (and cats) in your terminal!<span style="font-family: inherit;">A little-known feature of iTerm2 is that you can insert images directly into your (previously text only) terminal! This can be useful (render calculation as plot directly in terminal) or we can use it for silly purposes.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Cats. Who on the interwebs doesn't love cats?</span><br />
<br />
<h3>
Setup</h3>
<span style="font-family: Courier New, Courier, monospace;">brew install imagemagick</span><br />
copy iTerm2's imgcat script into your path<br />
<br />
<h3>
Test: display built-in image</h3>
<span style="font-family: Courier New, Courier, monospace;">convert rose: - | imgcat /dev/stdin</span><br />
<br />
<a href="http://2.bp.blogspot.com/-0hsLPHnsVG8/WiHq5dsJgYI/AAAAAAAAadM/1B1j5aW58MAJ6nCe0hP0aDmO8MN42NKkACK4BGAYYCw/s1600/Screen%2BShot%2B2017-12-01%2Bat%2B3.50.46%2BPM.png" imageanchor="1"><img border="0" height="56" src="https://2.bp.blogspot.com/-0hsLPHnsVG8/WiHq5dsJgYI/AAAAAAAAadM/1B1j5aW58MAJ6nCe0hP0aDmO8MN42NKkACK4BGAYYCw/s320/Screen%2BShot%2B2017-12-01%2Bat%2B3.50.46%2BPM.png" width="320" /></a><br />
<br />
<h3>
Pretty Title</h3>
<span style="font-family: Courier New, Courier, monospace;">convert -background lightblue -fill blue -font Tahoma -size 165x70 label:Anthony z.png && imgcat z.png</span><br />
<br />
<a href="http://1.bp.blogspot.com/-Olsgs15tqyY/WiHrOoaXZOI/AAAAAAAAadY/kdd39qYGemYmuJkg_1ItcIXiq_sBMZ88wCK4BGAYYCw/s1600/Screen%2BShot%2B2017-12-01%2Bat%2B3.51.47%2BPM.png" imageanchor="1"><img border="0" height="57" src="https://1.bp.blogspot.com/-Olsgs15tqyY/WiHrOoaXZOI/AAAAAAAAadY/kdd39qYGemYmuJkg_1ItcIXiq_sBMZ88wCK4BGAYYCw/s320/Screen%2BShot%2B2017-12-01%2Bat%2B3.51.47%2BPM.png" width="320" /></a><br />
<br />
<h3>
Good Job, Bub!</h3>
<div>
<span style="font-family: Courier New, Courier, monospace;">curl -s http://thinga.com/assets/uploads/images/Lil-Bub-pic-02.jpg | imgcat /dev/stdin</span></div>
<div>
<br /></div>
<div>
<a href="http://1.bp.blogspot.com/-gK9jiZTT4nA/WiHs-1De0uI/AAAAAAAAadk/RoGFGIVqBIUylYnMlVKXoDxY91_khT33QCK4BGAYYCw/s1600/Screen%2BShot%2B2017-12-01%2Bat%2B3.58.24%2BPM.png" imageanchor="1"><img border="0" height="127" src="https://1.bp.blogspot.com/-gK9jiZTT4nA/WiHs-1De0uI/AAAAAAAAadk/RoGFGIVqBIUylYnMlVKXoDxY91_khT33QCK4BGAYYCw/s320/Screen%2BShot%2B2017-12-01%2Bat%2B3.58.24%2BPM.png" width="320" /></a></div>
<br />
<br />
<br />
Note the "Tahoma" font used above is probably only on macOS. Choose another font that's installed into ImageMagick. What fonts are those, you say? Here you go:<br />
<h3>
List ImageMagick Fonts (Awk FTW)</h3>
<br />
<span style="font-family: Courier New, Courier, monospace;">$ convert -list font | awk '/Font:/ {print $2} {next}' | pr -4t</span><br />
<span style="font-family: Courier New, Courier, monospace;">AndaleMono<span style="white-space: pre;"> </span> BigCaslonM<span style="white-space: pre;"> </span> Herculanum<span style="white-space: pre;"> </span> TimesNewRomanBI</span><br />
<span style="font-family: Courier New, Courier, monospace;">AppleChancery<span style="white-space: pre;"> </span> BrushScriptI<span style="white-space: pre;"> </span> HoeflerTextOrname TimesNewRomanI</span><br />
<span style="font-family: Courier New, Courier, monospace;">AppleMyungjo<span style="white-space: pre;"> </span> Chalkduster<span style="white-space: pre;"> </span> Impact<span style="white-space: pre;"> </span> Trebuchet</span><br />
<span style="font-family: Courier New, Courier, monospace;">Arial<span style="white-space: pre;"> </span> ComicSans<span style="white-space: pre;"> </span> InaiMathi<span style="white-space: pre;"> </span> TrebuchetMSB</span><br />
<span style="font-family: Courier New, Courier, monospace;">ArialB<span style="white-space: pre;"> </span> ComicSansMSB<span style="white-space: pre;"> </span> Kokonor<span style="white-space: pre;"> </span> TrebuchetMSBI</span><br />
<span style="font-family: Courier New, Courier, monospace;">ArialBI<span style="white-space: pre;"> </span> CourierNew<span style="white-space: pre;"> </span> Krungthep<span style="white-space: pre;"> </span> TrebuchetMSI</span><br />
<span style="font-family: Courier New, Courier, monospace;">ArialBk<span style="white-space: pre;"> </span> CourierNewB<span style="white-space: pre;"> </span> MicrosoftSansSeri Verdana</span><br />
<span style="font-family: Courier New, Courier, monospace;">ArialI<span style="white-space: pre;"> </span> CourierNewBI<span style="white-space: pre;"> </span> PlantagenetCherok VerdanaB</span><br />
<span style="font-family: Courier New, Courier, monospace;">ArialNarrow<span style="white-space: pre;"> </span> CourierNewI<span style="white-space: pre;"> </span> Sathu<span style="white-space: pre;"> </span> VerdanaBI</span><br />
<span style="font-family: Courier New, Courier, monospace;">ArialNarrowB<span style="white-space: pre;"> </span> GB18030Bitmap<span style="white-space: pre;"> </span> Silom<span style="white-space: pre;"> </span> VerdanaI</span><br />
<span style="font-family: Courier New, Courier, monospace;">ArialNarrowBI<span style="white-space: pre;"> </span> Georgia<span style="white-space: pre;"> </span> Skia<span style="white-space: pre;"> </span> Webdings</span><br />
<span style="font-family: Courier New, Courier, monospace;">ArialNarrowI<span style="white-space: pre;"> </span> GeorgiaB<span style="white-space: pre;"> </span> Tahoma<span style="white-space: pre;"> </span> Wingdings</span><br />
<span style="font-family: Courier New, Courier, monospace;">ArialRoundedB<span style="white-space: pre;"> </span> GeorgiaBI<span style="white-space: pre;"> </span> TahomaB<span style="white-space: pre;"> </span> Wingdings2</span><br />
<span style="font-family: Courier New, Courier, monospace;">ArialUnicode<span style="white-space: pre;"> </span> GeorgiaI<span style="white-space: pre;"> </span> TimesNewRoman Wingdings3</span><br />
<span style="font-family: Courier New, Courier, monospace;">Ayuthaya<span style="white-space: pre;"> </span> Gurmukhi<span style="white-space: pre;"> </span> TimesNewRomanB Zapfino</span><br />
<br />John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0tag:blogger.com,1999:blog-5582182612187833327.post-38329977228073203712017-11-29T19:34:00.003-08:002017-11-29T19:34:43.480-08:00November appearance: KubeCon in Austin!I'll be at <a href="https://www.linuxfoundation.org/kubecon-cloudnativecon-north-america-l-1/">KubeCon / CloudNativeCon</a> in Austin next week (December 4-8). Feel free to say "hi"!<br />
<br />John Tells Allhttp://www.blogger.com/profile/10134085861618082210noreply@blogger.com0