<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Liz Rice on Medium]]></title>
        <description><![CDATA[Stories by Liz Rice on Medium]]></description>
        <link>https://medium.com/@lizrice?source=rss-d9e5549e8e2c------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*1b8qaRhjVGxSqaSq.jpg</url>
            <title>Stories by Liz Rice on Medium</title>
            <link>https://medium.com/@lizrice?source=rss-d9e5549e8e2c------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 09:04:05 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@lizrice/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Connecting Roland TD-27 to Melodics on iPad]]></title>
            <link>https://medium.com/@lizrice/connecting-roland-td-27-to-melodics-on-ipad-c7bc8800e6b0?source=rss-d9e5549e8e2c------2</link>
            <guid isPermaLink="false">https://medium.com/p/c7bc8800e6b0</guid>
            <category><![CDATA[drums]]></category>
            <category><![CDATA[midi]]></category>
            <dc:creator><![CDATA[Liz Rice]]></dc:creator>
            <pubDate>Sat, 21 Sep 2024 18:06:36 GMT</pubDate>
            <atom:updated>2024-09-21T18:06:36.558Z</atom:updated>
            <content:encoded><![CDATA[<p>Since Roland electronic drum kits come with a free subscription to Melodics, you might think it would be easy to find out how to connect them. But I found it surprisingly challenging to get Melodics on my iPad cooperating nicely with my new drum kit. Here’s what I learnt.</p><p>Setting up audio Bluetooth on the Roland TD-27 had been super easy, and I’ve been using it to play along to backing tracks or to use with Drumeo. I think my success there might have led me down a misleading path of thinking that Bluetooth would be the answer to all my problems. The trouble is that any audio latency shows up really quickly when you’re using Melodics and trying to trigger drums over MIDI at the same time as you’re hearing the backing track.</p><p>One approach is to connect using a cable between MIDI out on the TD-27 to a USB hub. This is actually <a href="https://support.melodics.com/en/articles/6777115-connecting-your-midi-instrument-to-melodics-on-ipad">documented on the Melodics site</a> as their Method 1, although because of the enshittification of search on the internet, it took me far too long to find that page.</p><p>My MIDI cable has a USB-A plug that I’m connecting into an Anker USB-C hub that connects to my iPad. I’ve also got a USB to headphones adapter plugged into that hub so that I can hear the sound. To be honest the MIDI connection seems pretty unreliable, and unplugging and plugging things at random can seem to help.</p><p>Another option is to use MIDI over Bluetooth between the TD-27 and the iPad, following Melodics Method 2 for connection, but do make sure you’re not using the Bluetooth audio and trying to listen through headphones connected to the TD-27 because that’s WAY too laggy. I’ve ended up leaving both Bluetooth audio and MIDI turned on on the TD-27, because it’s easier to leave it that way for when I just want to play along to a backing track, but I just need to make sure the audio out from the iPad is not over Bluetooth when I’m using Melodics. With this set up, I don’t need the Anker hub, and I’m using my USB-C to headphones adapter plugged directly into the iPad.</p><p>On the TD-27 I was having further problems because the hi-hat always appeared to be triggering as open, even when it was closed. It turns out there’s a setting under MIDI -&gt; Control called the Hi-hat Note Border which I ended up setting to 80 instead of its default setting of 127, thanks to this <a href="https://www.reddit.com/r/edrums/s/CTkW7PmG05">useful post on Reddit</a>. This setting defines the border between open and closed. For what it’s worth I also changed the MIDI mapping to trigger the general midi closed hihat note 42 (F#2), whether I’m hitting the high hat on the bow or the edge – the settings for this are under Kit Edit -&gt; Kit Midi.</p><p>I hope this helps someone else get set up more quickly than it took me!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c7bc8800e6b0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Exposing LoadBalancer services running on Kind in Lima VMs]]></title>
            <link>https://medium.com/@lizrice/exposing-loadbalancer-services-running-on-kind-in-lima-vms-4d58cd4b5e12?source=rss-d9e5549e8e2c------2</link>
            <guid isPermaLink="false">https://medium.com/p/4d58cd4b5e12</guid>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[lima-vm]]></category>
            <category><![CDATA[cilium]]></category>
            <dc:creator><![CDATA[Liz Rice]]></dc:creator>
            <pubDate>Thu, 11 Aug 2022 19:07:01 GMT</pubDate>
            <atom:updated>2022-08-11T19:07:01.896Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="Lima beans in a bowl" src="https://cdn-images-1.medium.com/max/1024/1*BmfESRhapDjRI0noln6Z7g.jpeg" /><figcaption>Photo of lima beans by <a href="https://www.flickr.com/photos/wfiupublicradio/5410661531">Indiana Public Media on Flickr</a></figcaption></figure><p><em>Another episode in an occasional series of learnings about using containers, virtual machines, and Kubernetes.</em></p><p>If I’m doing a demo on stage, I prefer to avoid network dependencies, conference WiFi being what it usually is. So for years I ran container or Kubernetes-related demos in virtual machines running on my laptop, with no dependency on the outside world.</p><p>Virtual conferences changed all that —streaming from home, I figured that if my internet connection goes down, no-one would be able to see or hear the fact that my demo had broken since the stream would also be affected. Additionally, after switching to an M1 Mac it was a whole lot harder to run demos on that, since it seemed there was always something I wanted to lean on that didn’t run on ARM architecture yet.</p><p>But as we gear back up to IRL events, I’ve been exploring whether it’s realistic for me to get back to VM-based demos. And I believe it is, because:</p><ul><li><a href="http://github.com/lima-vm/lima">Lima-VM</a> is awesome. It knocks the socks off Vagrant/VirtualBox or UTM, at least for my use-cases.</li><li>Most things (<a href="https://twitter.com/lizrice/status/1557714059939790848?s=20&amp;t=JPXN0h-32SApB6548M5_uQ">but not everything</a>) now seem to be built for ARM as well as Intel.</li></ul><h3>Lima config files</h3><p>You define your VM config in a YAML file that can also run provisioning scripts. Here’s an <a href="https://github.com/lizrice/learning-ebpf/blob/main/ubuntu-ebpf.yaml">example of a Lima config file</a> that I’ve been using for eBPF coding, based on Ubuntu. I know it works on ARM, I would love to hear from you if you try it out on an Intel machine.</p><pre># This example requires Lima v0.8.0 or later<br>images:<br>- location: &quot;https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img&quot;<br>  arch: &quot;x86_64&quot;<br>- location: &quot;https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-arm64.img&quot;<br>  arch: &quot;aarch64&quot;<br><br>cpus: 4<br>memory: &quot;10GiB&quot;<br><br>mounts:<br>- location: &quot;~&quot;<br>  writable: true<br>- location: &quot;/tmp/lima&quot;<br>  writable: true<br>provision:<br>- mode: system<br>  script: |<br>    apt-get update<br>    apt-get install -y apt-transport-https ca-certificates curl clang llvm jq<br>    apt-get install -y libelf-dev libpcap-dev libbfd-dev binutils-dev build-essential make <br>    apt-get install -y linux-tools-common linux-tools-5.15.0-41-generic</pre><h3>Kind on Lima</h3><p>To run a Kubernetes cluster, I’ve been running a multi-node Kind in the Lima machine, and this has been working flawlessly so far. Cilium works great too.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Z50iQ1fXgQjbt0GUJZMkCw.png" /><figcaption>Status output from Cilium’s CLI shows that Cilium and Hubble components are all running as expected</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fgEoA-oDMTfCkWo9WiqQJg.png" /><figcaption>Cilium connectivity test completed successfully</figcaption></figure><h3>Lima port-forwarding to localhost</h3><p>Lima comes with automatic port forwarding for localhost so that if you run a web server on the VM on, say, port 3000, you can use your browser to it from <a href="https://localhost:3000.">https://localhost:3000</a>. That example is exactly what I do if I want to run the <a href="https://docs.cilium.io/en/v1.12/operations/metrics/#example-prometheus-grafana-deployment">Prometheus &amp; Grafana dashboard</a> set-up described in the Cilium docs.</p><pre>kubectl -n cilium-monitoring port-forward service/grafana --address 0.0.0.0 --address :: 3000:3000 </pre><p>This works for localhost, but what if you want to access a different IP address within the virtual machine? For example, if I want to demo exposing a service using <a href="https://docs.cilium.io/en/v1.12/gettingstarted/servicemesh/ingress/">Cilium Ingress</a>, using Kubernetes port-forwarding would simply bypass the Ingress — and that would be missing the point.</p><h3>Lima port-forwarding to other IP addresses</h3><p>In a real-world deployment, services are exposed to the world using a LoadBalancer service with an external IP address. If you’re running in a public cloud like AWS, GKE or Azure, the LoadBalancer service will automatically get assigned an external IP address that you can access from outside the Kubernetes cluster. You can recreate this on your own virtual machines using <a href="https://metallb.universe.tf/">MetalLB</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EWkA8cEpuZIeXd_0zg2c4w.png" /><figcaption>Creating a Cilium Ingress automatically created a LoadBalancer service with an external IP address, thanks to Metal LB</figcaption></figure><p>In this example the LoadBalancer for my Ingress has been assigned the address 172.18.255.200 but this address is only meaningful within the VM. Your laptop can’t route to it automatically as it has no way of knowing anything about the IP addresses assigned inside the VM.</p><p>But we can get traffic there using ssh port forwarding from the Mac (shout-out to my colleague <a href="https://medium.com/u/eba5d6fc42dc">Marga Manterola</a> for pointing me in this direction!) The pattern looks like this:</p><pre>ssh -L &lt;port on Mac&gt;:&lt;external IP address&gt;:&lt;port&gt; -o Hostname=127.0.0.1 -o Port=&lt;Lima VM&#39;s port&gt; lima-&lt;VM name&gt; </pre><ul><li>&lt;port on Mac&gt;is whatever port you want to assign (you’ll be pointing your browser to localhost:&lt;port on Mac&gt; )</li><li>&lt;external IP address&gt;is the assigned IP address for the LoadBalancer</li><li>&lt;port&gt; is the port number for the service on the LoadBalancer’s IP address</li><li>&lt;VM name&gt; is the name you gave to the VM when you created it with limactl</li><li>&lt;Lima VM&#39;s port&gt; is the port on which the VM is accessible from your Mac. You can get this by running limactl list:</li></ul><pre>~ ❯ limactl list<br>NAME           STATUS     SSH                ARCH       CPUS    MEMORY    DISK      DIR<br>ubuntu-kind    Running    127.0.0.1:50156    aarch64    4       20GiB     100GiB    /Users/liz/.lima/ubuntu-kind</pre><p>Here, my VM name is ubuntu-kind and it’s accessible through port 50156. I can arbitrarily pick port 9999 on my Mac, and use it to access the external IP address assigned to the LoadBalancer inside the cluster, with this command:</p><pre>ssh -L 9999:172.18.255.200:80 -o Hostname=127.0.0.1 -o Port=50156 lima-ubuntu-kind </pre><p>So now I can access the <em>bookinfo </em>service that I exposed using the Cilium Ingress.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sGCV0hbl0BbfnXcCqRSzmQ.png" /><figcaption>The <em>bookinfo example app, accessible at localhost:9999 from my Mac</em></figcaption></figure><p>The <em>bookinfo </em>example from Istio is one thing that hasn’t been officially built with ARM support yet. I was able to built most of its services easily enough with <em>docker build</em>, though I ran into issues building the reviews component. The beauty of a microservices architecture is that I can just leave that component out for now!</p><p>Istio has recently got <a href="https://github.com/istio/istio/issues/26652">ARM support built in the master branch</a>, with support coming in the upcoming 1.15 release. That should make it a lot easier to run <a href="https://isovalent.com/blog/post/cilium-service-mesh/">Cilium Service Mesh</a> and Istio demos side-by-side on ARM machines!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4d58cd4b5e12" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Linux VMs on an M1-based Mac with VScode and UTM]]></title>
            <link>https://medium.com/@lizrice/linux-vms-on-an-m1-based-mac-with-vscode-and-utm-d73e7cb06133?source=rss-d9e5549e8e2c------2</link>
            <guid isPermaLink="false">https://medium.com/p/d73e7cb06133</guid>
            <category><![CDATA[mac]]></category>
            <category><![CDATA[virtual-machine]]></category>
            <category><![CDATA[arm-processors]]></category>
            <dc:creator><![CDATA[Liz Rice]]></dc:creator>
            <pubDate>Sat, 01 May 2021 16:03:06 GMT</pubDate>
            <atom:updated>2021-05-01T18:26:42.547Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*Up42E8W3tYe_aD4SXZkbcw.jpeg" /><figcaption>Photo © <a href="https://www.geograph.org.uk/profile/43729">David Dixon</a> (<a href="http://creativecommons.org/licenses/by-sa/2.0/">cc-by-sa/2.0</a>)</figcaption></figure><p>On my Intel-based Macs I have been using <a href="https://medium.com/@lizrice/kubernetes-in-vagrant-with-kubeadm-21979ded6c63">VirtualBox and Vagrant to run Linux virtual machines</a> for years. Using VScode to SSH “remotely” into these VMs is a great set-up for development, for me.</p><p>I recently got a MacBookPro built on Apple’s M1 ARM CPU, and my usual set-up is impossible because VirtualBox doesn’t (yet) support ARM processors. For a couple of minutes I seriously entertained the idea of returning this machine and getting another Intel-based one. But a bit of searching led me to <a href="https://mac.getutm.app/">UTM</a> as a MacOS hypervisor that would support the M1 processor.</p><p>Here’s what I did to get myself up-and-running with an Ubuntu virtual machine running on UTM, editing code with VScode’s Remote-SSH extension.</p><h3>Downloads</h3><ul><li>Download and install UTM — you can get a free version, or <a href="https://apps.apple.com/gb/app/utm-virtual-machines/id1538878817?mt=12">pay a small amount for it to get updates and to its support development</a></li><li>Download the Ubuntu Server ISO image for the version you’re interested in (I used 20.10). The Ubuntu site tends to take you to the Intel version, so make sure you grab an <a href="https://ubuntu.com/download/server/arm">ARM download</a>.</li></ul><h3>Set up the VM</h3><p>I essentially followed the <a href="https://mac.getutm.app/gallery/ubuntu-20-04">UTM instructions</a> to set up the virtual machine, with a few minor differences.</p><ul><li>I picked 8 GB memory as hinted at by the the illustration in step 6</li><li>Under Display set console access only (I don’t need the GUI as I’ll be SSHing into the box)</li><li>In the Network tab, configure port forwarding so that an arbitrary port on the host (I picked 2200) gets forwarded to port 22 on the guest virtual machine.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yABPQBtxXg8_5l8MlYOLqA.png" /><figcaption>Port forwarding setup</figcaption></figure><h3>First boot</h3><p>On the first boot I did get thrown into the UEFI shell as described in the <a href="https://mac.getutm.app/gallery/ubuntu-20-04">UTM instructions</a> Troubleshooting section. Running fso:\efi\boot\bootaa64.efi as described in the Troubleshooting section seemed to work.</p><p>You then get a series of prompts about the installation process. I accepted all the defaults including downloading a new installer, except for accepting to installing OpenSSH Server. You get to pick a username &amp; password as part of this process.</p><p>At the end of the installer process you’re asked to reboot. For me, this first reboot didn’t look terribly promising, reporting a firmware error about a image base having a bogus value. But like all good engineers my first resort was to turn it off and on again — after another reboot all looked good and I was able to log in with the username &amp; password previously selected.</p><p>At this point you might want to check that you can access the VM from a terminal on the Mac with ssh &lt;username&gt;@127.0.0.1 -p 2200</p><h3>VScode remote SSH</h3><p>VScode’s excellent <a href="https://code.visualstudio.com/docs/remote/ssh">remote-SSH extension</a> lets you access a remote machine as if it were local — not only can you edit files on the remote machine through the VScode interface, but you can also access the built-in terminal in the normal way. VScode does this by accessing the remote machine over SSH and installing an agent on it.</p><p>Once you’ve added the extension to VScode, run <strong>Remote-SSH: Add New SSH Host… </strong>and you’ll be prompted to enter the SSH command. Use the same command as you tested earlier, using port 2200 so that the connection is forwarded to the VM.</p><p>For me this results in an SSH config like this:</p><pre>Host 127.0.0.1<br>  HostName 127.0.0.1<br>  User liz<br>  Port 2200</pre><p>You’ll be able to clone a Git repo directly onto the VM from within VScode, and then work away at it as if it were your local machine!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MM2GVaj8_2Naw0xKFgXP7w.png" /></figure><h3>Should you buy an M1 Mac?</h3><p>The price/performance ratio for ARM is very attractive, and I’m noticing the difference. My old machine would regularly sound like it was attempting lift-off but I’m honestly not even sure whether my new laptop has fans. And every Mac app I have tried to run on the laptop has worked perfectly. But does that mean that I wholeheartedly recommend switching to an M1 Mac?</p><p>I kept having to remind myself for what seemed an embarrassingly long time that this VM can still only run executables built for ARM. And not every container image has an ARM version included. You can’t necessarily just `docker pull` and expect that everything is going to work.</p><p>Not everything will build nicely either. Everything I’ve tried written in Golang has been seamless, but I found myself trying to build something written in Node (not an area of expertise for me) and ended up resorting to my old laptop. When I bought the new machine, I figured that if I ever found that I needed an Intel processor, I still had that old one to hand – or I could always just use a cloud provider. Those options might not be suitable for everyone, or might be inconvenient. If you’re a developer you might want to think carefully about your tools, your team’s workflow, and whether you need to be able to replicate builds that are currently only being performed for Intel, before jumping aboard the M1 train.</p><p>But with such attractive pricing, I see a lot of folks moving to ARM processors anyway. This is happening not just in personal, but also in the cloud, for example with <a href="https://aws.amazon.com/ec2/graviton/">AWS Graviton processors</a>. With this momentum, I don’t think it will be long before it’s completely normal to expect builds for both Intel and ARM as a matter of course. And then there will be no good reason not to adopt the cheaper, higher-performance option.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d73e7cb06133" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[My first AWS DeepComposer tracks]]></title>
            <link>https://medium.com/@lizrice/my-first-aws-deepcomposer-tracks-c8e43926c654?source=rss-d9e5549e8e2c------2</link>
            <guid isPermaLink="false">https://medium.com/p/c8e43926c654</guid>
            <category><![CDATA[machine-learning-music]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[deepcomposer]]></category>
            <category><![CDATA[aws]]></category>
            <dc:creator><![CDATA[Liz Rice]]></dc:creator>
            <pubDate>Sat, 29 Feb 2020 18:59:13 GMT</pubDate>
            <atom:updated>2020-02-29T18:59:13.440Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JyzLM9W7V7foy0JvURL3vw.jpeg" /><figcaption>Unboxing the AWS DeepComposer keyboard</figcaption></figure><p>As an <a href="https://aws.amazon.com/developer/community/heroes/?community-heroes-all.sort-by=item.additionalFields.sortPosition&amp;community-heroes-all.sort-order=asc&amp;awsf.filter-hero-category=heroes%23container">AWS Container Hero</a> I was lucky enough to get hold of one of the new <a href="https://www.amazon.com/AWS-DeepComposer-learning-enabled-keyboard-developers/dp/B07YGZ4V5B">DeepComposer keyboards</a> at re:Invent a couple of months ago. The service preview has been rolling out slowly, and I’ve finally had a chance to get hands-on with it.</p><p>The idea with DeepComposer is that you input a melody, and artificial intelligence will generate accompanying tracks that harmonize and complement the melody.</p><p>At time of writing the Music Studio interface within DeepComposer is pretty basic. You input 8 bars using the physical <a href="https://www.amazon.com/AWS-DeepComposer-learning-enabled-keyboard-developers/dp/B07YGZ4V5B">keyboard</a> (or the on-screen version) but there’s no editing just now. Having recorded the melody you can download it as a Midi file; hopefully that means you’ll soon be able to upload the melody file so that you can use something else, like Garageband, to correct any errors.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JXK5U7ku737w4ktrQ9wC4g.png" /><figcaption>DeepComposer Music Studio interface</figcaption></figure><p>Thinking that it might be unfair to saddle the poor algorithm with a melody from my own brain, I thought I’d start with something that might already be familiar: the <a href="https://youtu.be/DyDfgMOUjCI?t=74">keyboard riff from Billie Eilish’s <em>Bad Guy</em></a>. It happens to be eight bars long, which is conveniently the length of melody that you can input into DeepComposer today.</p><p>I managed to pick it out on the keyboard. With the melody in place you get to choose one of five pre-trained AI models, and then hit “Generate Composition”.</p><p>The first model in the list is “Rock” so I thought I’d give that a whirl. It takes very little time to get the generated composition back, but I can’t say I loved the results. The first six bars sound like five musicians each battling to play a different song, and then finally coming to some kind of rough consensus for the last two bars.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fw.soundcloud.com%2Fplayer%2F%3Furl%3Dhttps%253A%252F%252Fapi.soundcloud.com%252Ftracks%252F768559786%26show_artwork%3Dtrue&amp;display_name=SoundCloud&amp;url=https%3A%2F%2Fsoundcloud.com%2Flizrice%2Fbad-guy-comp-1-rock&amp;image=https%3A%2F%2Fsoundcloud.com%2Fimages%2Ffb_placeholder.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=soundcloud" width="800" height="166" frameborder="0" scrolling="no"><a href="https://medium.com/media/9c8be1424be9813801d0ad339c709ed3/href">https://medium.com/media/9c8be1424be9813801d0ad339c709ed3/href</a></iframe><p>The “Symphony” model was marginally more successful in that my artificial players seem to be more-or-less agreed on the rhythm of the piece, if not the key.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fw.soundcloud.com%2Fplayer%2F%3Furl%3Dhttps%253A%252F%252Fapi.soundcloud.com%252Ftracks%252F768560983%26show_artwork%3Dtrue&amp;display_name=SoundCloud&amp;url=https%3A%2F%2Fsoundcloud.com%2Flizrice%2Fbad-guy-comp-4-symphony&amp;image=https%3A%2F%2Fsoundcloud.com%2Fimages%2Ffb_placeholder.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=soundcloud" width="800" height="166" frameborder="0" scrolling="no"><a href="https://medium.com/media/0470aba1d7e9c27be17d2a44611d7dcc/href">https://medium.com/media/0470aba1d7e9c27be17d2a44611d7dcc/href</a></iframe><p>At this point I started to think that maybe the <em>Bad Guy</em> riff wasn’t such a good choice as a melody. DeepComposer comes with a few well-known pieces like <em>Twinkle Twinkle</em> or <em>New World Symphony</em> to get you started, and these all have slower-tempo, more easily hummable tunes. Maybe I needed something similar? I came up with something, but I’m not sure my AI musicians really grasped what I was aiming for with this piece.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fw.soundcloud.com%2Fplayer%2F%3Furl%3Dhttps%253A%252F%252Fapi.soundcloud.com%252Ftracks%252F768587656%26show_artwork%3Dtrue&amp;display_name=SoundCloud&amp;url=https%3A%2F%2Fsoundcloud.com%2Flizrice%2Fcomp-8-symphony&amp;image=https%3A%2F%2Fsoundcloud.com%2Fimages%2Ffb_placeholder.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=soundcloud" width="800" height="166" frameborder="0" scrolling="no"><a href="https://medium.com/media/8cdb53680482a8c654af7ec01c7e3710/href">https://medium.com/media/8cdb53680482a8c654af7ec01c7e3710/href</a></iframe><p>In my first few attempts the input was monophonic, but the <em>New World Symphony</em> option inspired me to try something different. What would happen if I put in some harmonies of my own as part of the melody? I don’t know if you agree, but to me this seemed to steer the AI in a better direction.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fw.soundcloud.com%2Fplayer%2F%3Furl%3Dhttps%253A%252F%252Fapi.soundcloud.com%252Ftracks%252F768591556%26show_artwork%3Dtrue&amp;display_name=SoundCloud&amp;url=https%3A%2F%2Fsoundcloud.com%2Flizrice%2Fcomp-9-pop&amp;image=https%3A%2F%2Fsoundcloud.com%2Fimages%2Ffb_placeholder.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=soundcloud" width="800" height="166" frameborder="0" scrolling="no"><a href="https://medium.com/media/b7493d48c1b392afc75456d0267a0bcf/href">https://medium.com/media/b7493d48c1b392afc75456d0267a0bcf/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/948/1*G9RG_7Uxr2WB9Q_sFTXOUw.png" /><figcaption>Piano-roll for the polyphonic input used to generate Comp-9-Pop</figcaption></figure><p>Based on today’s experiments I don’t think I’m about to generate the next global hit through DeepComposer any time soon, but it’s pretty interesting to play with. I haven’t as yet done anything to understand what’s going on behind the scenes other than skim over the introductions to the AI models and the <a href="https://github.com/aws-samples/aws-deepcomposer-samples">DeepComposer labs</a>. But here are a few few observations based on my initial experiments with the basic models:</p><ul><li>The generated drum tracks seem super-simplistic: lots of hi-hat on 8th notes for a few beats, then 16th notes for a few beats, but bass drum and snare seem very sparse even on the Rock model. This made me wonder whether a successful music generation algorithm needs a different model (or sub-model?) for drum beats, to understand the general need for more consistent repetition.</li><li>The most successful melodic tracks seem to echo the original melody pretty closely, which sounds OK but is not very creative. I wonder if this is because the <a href="https://github.com/aws-samples/aws-deepcomposer-samples/blob/master/Loss-functions.md">loss function</a> might tend to zero if the generated track closely copies the original?</li><li>Giving polyphonic input for the melody gives the algorithm a lot more clues about chord progression, and it seems to be able to take advantage of that.</li><li>I don’t know how much my timing on the input might affect the output. I’d like to be able to edit the Midi / piano roll to make sure the notes are happening at precisely the right time, and see whether that helps DeepComposer understand the structure of the piece better.</li></ul><p>So far I’ve only used the provided models. You can also generate your own — I’ve got one spinning up now, but I’ll come back to that later, as it takes ~8 hours to create. (During DeepComposer preview, AWS aren’t charging for the compute time it takes to create a model, thankfully!)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Pogd-u--JR8aCyesF1f9Gw.png" /><figcaption>My new model being generated</figcaption></figure><p>It will be interesting to see whether my model generates significantly different results from the provided ones. I’ll have to get back to you on that once my model is generated. Meanwhile, go listen to some better music!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FDyDfgMOUjCI%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DDyDfgMOUjCI&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FDyDfgMOUjCI%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/d6dfabce367c8a4f5a4462745e5d71ea/href">https://medium.com/media/d6dfabce367c8a4f5a4462745e5d71ea/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c8e43926c654" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Go slices, maps, pitfalls — and generics]]></title>
            <link>https://levelup.gitconnected.com/go-slices-maps-pitfalls-and-generics-f7ced963ced?source=rss-d9e5549e8e2c------2</link>
            <guid isPermaLink="false">https://medium.com/p/f7ced963ced</guid>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[generics]]></category>
            <category><![CDATA[golang-slice-and-map]]></category>
            <dc:creator><![CDATA[Liz Rice]]></dc:creator>
            <pubDate>Sat, 18 Jan 2020 14:48:05 GMT</pubDate>
            <atom:updated>2020-01-23T12:51:49.504Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*4GHWhfp0QJZh3MysgphcIw.png" /><figcaption>Don’t fall into a trap with slices</figcaption></figure><h3>Go slices, maps, pitfalls — and generics</h3><p>I don’t recall how, exactly — probably something in my Twitter feed or my overly cluttered Inbox — but I recently landed on <a href="https://medium.com/swlh/golang-tips-why-pointers-to-slices-are-useful-and-how-ignoring-them-can-lead-to-tricky-bugs-cac90f72e77b">this article</a> by <a href="https://medium.com/u/2b8679c5a2b0">Paolo Gallina</a> about using pointers to slices.</p><p>I like Go a lot, but it does have a few shortcoming where it sets traps for programmers, and this is a big and dangerous one. Take a look at Paolo’s article, and/or <a href="https://play.golang.org/p/tPt7A761yTa">the following code on the Go playground</a>, to see what I mean.</p><pre>func main() {<br>    slice:= []string{&quot;a&quot;,&quot;a&quot;}<br>    func(slice []string){<br>        slice[0]=&quot;b&quot;;<br>        slice[1]=&quot;b&quot;;<br>    }(slice)<br>    fmt.Print(slice)</pre><pre>    slice = []string{&quot;a&quot;,&quot;a&quot;} <br>    func(slice []string){<br>        slice = append(slice, &quot;a&quot;)<br>        slice[0]=&quot;b&quot;;<br>        slice[1]=&quot;b&quot;; <br>    }(slice)<br>    fmt.Print(slice)<br>}</pre><p>This code prints [b,b] after the first function call, as you would likely expect. If you know your slices, you won’t be so surprised that after the second function the output is [a, a]. Not very intuitive!</p><p>To use a slice effectively you have to know that:</p><ul><li>a slice is implemented as a structure containing a pointer</li><li>the pointer value can change.</li></ul><h3>A better way? Return the slice</h3><p>Paolo recommends using a pointer to the slice, which is perfectly acceptable solution to the problem, though I’d like to propose what I think is a slightly better approach: <em>if you’re writing a function that takes a slice as a parameter, include the slice as a return value</em>. You can take this as a general guideline, or only use it when the function might append to the slice, which is when the problem can occur.</p><p>I’ve adapted Paolo’s example (and you can find it <a href="https://play.golang.org/p/fY6KPIzxkTA">on the Go Playground here</a>).</p><pre>func main() {<br>    slice:= []string{&quot;a&quot;,&quot;a&quot;}<br> <br>    slice = func(slice []string) []string{<br>        slice= append(slice, &quot;a&quot;)<br>        slice[0]=&quot;b&quot;;<br>        slice[1]=&quot;b&quot;; <br>        return slice<br>    }(slice)</pre><pre>    fmt.Print(slice) <br>}</pre><p>I like this better because it’s absolutely explicit that you’re getting back the updated version of slice. And it avoids the extra pointer — I am keen on avoiding unnecessary pointers in general because they add cognitive overhead, and involve <a href="https://medium.com/@philpearl/bad-go-slices-of-pointers-ed3c06b8bb41">additional allocations</a> and subsequent garbage collection, which will impact performance.</p><h3>What about maps?</h3><p>In many respects maps and slices look (superficially) similar, what with the use of square braces [ and ], and the common use of make to allocate them in both cases. In practice the underlying implementation is really very different. For the purposes of this post, the difference I’m most interested in is that a map is implemented as a pointer.</p><p>From <a href="https://groups.google.com/forum/#!msg/golang-nuts/SjuhSYDITm4/jnrp7rRxDQAJ">this thread</a> <a href="https://medium.com/u/df2718043abd">Ian Lance Taylor</a> wrote</p><blockquote>In the very early days what we call maps now <br>were written as pointers, so you wrote *map[int]int. We moved away <br>from that when we realized that no one ever wrote `map` without <br>writing `*map`.</blockquote><p>I would never have found this illuminating quote were it not for <a href="https://dave.cheney.net/2017/04/30/if-a-map-isnt-a-reference-variable-what-is-it">this post</a> by <a href="https://medium.com/u/b702737d9239">Dave Cheney</a>, which you should dive into for more on how maps are implemented.</p><p>Given that a map is already a pointer, there is no need to worry about using a pointer to a map in case it changes underneath your feet.</p><h3>What have generics got to do with all this?</h3><p>Imagine that slices weren’t a fundamental part of the Go language, but instead they were a regular struct with methods like append(). As a Go programmer you would see the <a href="https://blog.golang.org/go-slices-usage-and-internals">struct, with its pointer, length and capacity field values</a>, and you wouldn’t have to be terribly experienced to recognise that all these field values might conceivably change when you called a method. And therefore, you’d be less likely to fall into the trap.</p><p>You might be thinking at this point “maybe I should just use the slice header directly in my code for extra transparency”, but it’s really not worth it. One big reason you won’t want to do this is (the absence of) generics. The nice thing about slices — and maps for that matter — is that Golang allows you to use them to store data of any type, whereas your hand-generated, artisanal slice header struct would need to specify a type for that pointer. And then you’re going to need a different set of methods for every different type you want to store in a slice. That’s going to get very dull very fast.</p><h3>(Re-)learning to love slices</h3><p>I still wish that Go didn’t require folks to understand the underlying implementation of slices. Perhaps I would feel better about it if there were some subtle visual clue, like the use of a different brace type, to help us all distinguish when we’re talking about a slice, an array, or a map.</p><p>I <em>may</em> be coming around to the idea of generics :-)</p><p><em>If you like this article you might also like this one on </em><a href="https://medium.com/@lizrice/variables-and-functions-in-go-oh-my-18b71297657?source=friends_link&amp;sk=492253deb2265879c2131e25a84e846a"><em>variables and functions in Go</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f7ced963ced" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/go-slices-maps-pitfalls-and-generics-f7ced963ced">Go slices, maps, pitfalls — and generics</a> was originally published in <a href="https://levelup.gitconnected.com/">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[SSH to Vagrant from VScode]]></title>
            <link>https://medium.com/@lizrice/ssh-to-vagrant-from-vscode-5b2c5996bc0e?source=rss-d9e5549e8e2c------2</link>
            <guid isPermaLink="false">https://medium.com/p/5b2c5996bc0e</guid>
            <category><![CDATA[vagrant]]></category>
            <category><![CDATA[ssh]]></category>
            <category><![CDATA[vscode]]></category>
            <dc:creator><![CDATA[Liz Rice]]></dc:creator>
            <pubDate>Thu, 02 Jan 2020 18:52:29 GMT</pubDate>
            <atom:updated>2020-01-02T18:52:29.598Z</atom:updated>
            <content:encoded><![CDATA[<p>I’ve just been introduced to the life-changing experience of connecting to a remote machine from inside VScode using the <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh">Remote-SSH extension</a> (thanks <a href="http://twitter.com/itaysk">Itay Shakury</a>!) But I needed one tiny extra bit of information so I could use this to connect to Vagrant VMs on my laptop.</p><p>I use Vagrant a lot for example, to run a VM with <a href="https://medium.com/@lizrice/kubernetes-in-vagrant-with-kubeadm-21979ded6c63?source=friends_link&amp;sk=c9dc2749b68d9c03de2b2bb5bdd9e91f">Kubernetes as installed by vanilla</a><a href="https://medium.com/@lizrice/kubernetes-in-vagrant-with-kubeadm-21979ded6c63?source=friends_link&amp;sk=c9dc2749b68d9c03de2b2bb5bdd9e91f">kubeadm</a>. By default Vagrant sets up some SSH config so that it’s super easy to get into the VMs you run with it — all you need to do iscd to the directory holding the Vagrantfile, and then simply run vagrant ssh.</p><p>This is great, but it obscures the parameters being used under the covers to open that SSH connection — and you’ll need that information in order to configure Remote-SSH. Turns out it’s really easy!</p><pre># Change to the directory containing the Vagrantfile<br>~$ cd vagrant/machine</pre><pre># Get the SSH config that Vagrant uses<br>~/vagrant/machine$ <strong>vagrant ssh-config</strong><br>Host default<br>  HostName 127.0.0.1<br>  User vagrant<br>  Port 2222<br>  UserKnownHostsFile /dev/null<br>  StrictHostKeyChecking no<br>  PasswordAuthentication no<br>  IdentityFile /Users/liz/vagrant/machine/.vagrant/machines/default/virtualbox/private_key<br>  IdentitiesOnly yes<br>  LogLevel FATAL</pre><p>Copy the output of this into an SSH config file — I added it to my default SSH config at ~/.ssh/config. In VScode you can easily open this file, or generate a custom config file for VSCode to use, by pressing ⌘⇧P and selecting <em>Remote-SSH: Open Configuration File…</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*DGjo70jAhzB1EgW56Um1-A.png" /></figure><p>Connect VScode to the machine with ⌘⇧P <em>Remote-SSH: Connect to Host… </em>and select default (where “default” is the machine name that Vagrant assigned). The first time you connect it will take a little while to download the VScode server onto the VM. Voilà, your files on the host available to view and edit inside VScode.</p><p><em>Bonus:</em> if you put the config in your default SSH config file, you can now also SSH into the box from your laptop terminal with ssh default, saving you the bother of moving into the Vagrant machine’s directory.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5b2c5996bc0e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Finding an intro to maths for cryptography]]></title>
            <link>https://medium.com/@lizrice/finding-an-intro-to-maths-for-cryptography-cc97ad6b04?source=rss-d9e5549e8e2c------2</link>
            <guid isPermaLink="false">https://medium.com/p/cc97ad6b04</guid>
            <category><![CDATA[x509]]></category>
            <category><![CDATA[cryptography]]></category>
            <category><![CDATA[security]]></category>
            <dc:creator><![CDATA[Liz Rice]]></dc:creator>
            <pubDate>Mon, 30 Dec 2019 21:12:37 GMT</pubDate>
            <atom:updated>2020-01-01T17:29:39.550Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*53xTR8e5CmR9Y0oCjiQxLQ.jpeg" /><figcaption>Photo by <a href="https://www.freeimages.com/photographer/bigevil600-57066">ramzi hashisho</a> from <a href="https://freeimages.com/">FreeImages</a></figcaption></figure><p>If you’re looking for an introduction to the mathematics that make cryptography work, perhaps this list might help.</p><h3>Why I’m looking for cryptography maths resources</h3><p>I’m currently writing a book about Container Security for <a href="https://medium.com/u/fbfa235a954c">O’Reilly Media</a>, and one of my chapters will deal with how and why X.509 certificates are used to secure connections between containers (or other entities in a distributed system). X.509 certificates make use of public/private key pairs for both identity and encryption purposes.</p><p>Now, the maths (I’m British, so I put an ‘s’ on it) of how these key pairs work is beyond the scope of my book – not to mention that I’m far from an expert. But it seems like an interesting direction that some readers might like to take. So I put out a call on Twitter.</p><h3>🇪🇺Liz Rice 🎄 on Twitter</h3><p>If you were looking for an introduction to maths for cryptography, where would you go?</p><p>I got some great responses, including one from <a href="https://medium.com/u/b83996187192">Yiorgos Adamopoulos</a> suggesting I turn the results into a blog post. So here’s what I learned:</p><h3>Some classics don’t age well</h3><p>Quite a few folks told me that Applied Cryptography was on their reading list at university, but it’s now considered one to avoid as it’s outdated. (We actually have a copy of this at home, and I have a vague, and possibly incorrect, recollection that during the 1990’s <a href="https://en.m.wikipedia.org/wiki/Export_of_cryptography_from_the_United_States">US ban on the export of cryptography</a> this book wasn’t supposed to leave the country, so it was something of a badge of honour to own this book.)</p><h3>Recommended reads</h3><p>Instead, consider one of the following options that were recommended in response to my tweet:</p><ul><li><a href="https://amzn.to/2QyG73l">An Introduction to Mathematical Cryptography</a> by Hoffstein, Pipher &amp; Silverman seems to be popular undergrad reading.</li><li><a href="https://amzn.to/35g9dKo">Practical Cryptography</a> by Schneier &amp; Ferguson came up several times, but as per <a href="http://schneier.com/">schneier.com</a> this book is now superceded by <a href="https://www.schneier.com/books/cryptography_engineering/">Cryptography Engineering</a>.</li><li><a href="https://amzn.to/39mOXdj">Handbook of Applied Cryptography</a> by Menezes, Oorshot &amp; Vanstone (also available <a href="http://cacr.uwaterloo.ca/hac/">online</a>)</li><li>Stallings’ <a href="https://amzn.to/2MJHhbb">Cryptography &amp; Network Security</a> came up a few times, and is still on the reading list for some university courses</li><li>Aumasson’s <a href="https://nostarch.com/seriouscrypto">Serious Cryptography</a> was recommended a few times, with the caveat that it’s less theoretical so has less maths in it.</li><li>Holden’s <a href="https://wordpress.rose-hulman.edu/holden/the-mathematics-of-secrets/">Mathematics of Secrets</a> was also mentioned.</li></ul><h3>Online resources</h3><p>If you want something immediate and possibly interactive, here are some options that folks suggested.</p><ul><li><a href="https://www.crypto101.io/">Crypto 101</a></li><li><a href="http://cryptopals.com/">CryptoPals</a> looks like fun!</li><li><a href="https://ocw.mit.edu/courses/find-by-topic/#cat=engineering&amp;subcat=computerscience&amp;spec=cryptography">MIT OpenCourseWare</a></li><li>Talks by <a href="https://media.ccc.de/search?q=Tanja+Lange">Tanja Lange</a></li><li>The mere mention of the word “bitcoin” usually sets off my scepticism alarm, but I’m told that the section on Cryptography in <a href="https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch04.asciidoc">Mastering Bitcoin</a> is really good.</li></ul><p>If you try out any of these books and resources, let me know what you think of them – and tell me if something good is missing!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cc97ad6b04" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Variables and functions in Go, oh my!]]></title>
            <link>https://medium.com/@lizrice/variables-and-functions-in-go-oh-my-18b71297657?source=rss-d9e5549e8e2c------2</link>
            <guid isPermaLink="false">https://medium.com/p/18b71297657</guid>
            <category><![CDATA[golang]]></category>
            <dc:creator><![CDATA[Liz Rice]]></dc:creator>
            <pubDate>Fri, 30 Aug 2019 11:02:22 GMT</pubDate>
            <atom:updated>2019-08-30T11:02:22.002Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iCa9SEg7dNryFU2n7bZjCg.png" /><figcaption>Is your variable in scope? Photo by <a href="https://unsplash.com/@daniel_christie97?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Daniel Christie</a> on <a href="https://unsplash.com/search/photos/scope?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><em>This is a copy of an article previously published on write.as. Putting it here on Medium, as an experiment in seeing which platform gets the best reach. Will update on that later!</em></p><p>Pop quiz! What do you expect this code to do?</p><pre>func main() {<br>  x := 1<br>  f := func() {<br>    fmt.Printf(&quot;x is %d\n&quot;, x)<br>  }<br>  <br>  x = 2<br>  f()<br>}</pre><p><a href="https://play.golang.org/p/9eIDADrKeIq">Try it at the Go Playground</a></p><p><em>This is a super-simplified example of something that recently came up reviewing some code at </em><a href="https://aquasec.com/"><em>Aqua</em></a><em>. Some function and variable names have been changed to protect the innocent.</em></p><p>You can refer to <em>x</em> inside the function f()because it’s in scope. The value for <em>x</em> inside f() is whatever value it has at the point f() is invoked.</p><p>But you can’t do this:</p><pre>func main() {<br>  f := func() {<br>    fmt.Printf(&quot;x is %d\n&quot;, x)<br>  }<br>  <br>  x := 2<br>  f()<br>}</pre><p>You’re not allowed to use variables before they are declared, because the compiler needs to know what type of variables it’s dealing with. That code is not OK, in the same way that this isn’t OK:</p><pre>func main() {<br>  fmt.Printf(“x is %d\n”, x)<br>  x := 2<br>}</pre><p>The important point is that the compiler needs to know the <em>type</em> of the variable in advance of your function, but it doesn’t need the <em>value</em> in advance. You just need to declare it, you don’t need to define it. This is fine:</p><pre>func main() {<br>  var x int</pre><pre>  f := func() {<br>    fmt.Printf(&quot;x is %d\n&quot;, x)<br>  }<br>  <br>  x = 2<br>  f()<br>}</pre><p>We had a bug that was a much more complicated version of this:</p><pre>func main() {</pre><pre>  y := 1<br>  x := y</pre><pre>  f := func() {<br>    fmt.Printf(&quot;x is %d\n&quot;, x)<br>  }</pre><pre>  // Getting the right value for y<br>  y = 2</pre><pre>  f()<br>}</pre><p>We were setting the variable <em>x</em> too early, before we had the correct value (though in our real-world case the variables were nested structures, not just ints, so it was harder to see the problem).</p><p>The proposed fix looked more like this:</p><pre>func main() {</pre><pre>  y := 1</pre><pre>  f := func() {<br>    x := y<br>    fmt.Printf(&quot;x is %d\n&quot;, x)<br>  }</pre><pre>  // Getting the right value for y<br>  y = 2</pre><pre>  f()<br>}</pre><p>This works fine, but it made the definition of f()quite long (remember we are dealing with variables much more complex than ints). This made it harder to read — by the time you got to the end you had forgotten that it was a function definition being assigned to a variable, and not being executed until later.</p><p>Following the principle of <a href="https://link.medium.com/T8rEN0KJdZ">left-aligning the happy path</a>, I’m a fan of keeping inline definitions short for readability. So the final version looks more like this:</p><pre>func main() {</pre><pre>  var x int</pre><pre>  f := func() {<br>    fmt.Printf(&quot;x is %d\n&quot;, x)<br>  }</pre><pre>  // Getting the right value for y<br>  y := 2<br>  x = y</pre><pre>  f()<br>}</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=18b71297657" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Anyone for tennis?]]></title>
            <link>https://medium.com/@lizrice/anyone-for-tennis-74a79aaa82e3?source=rss-d9e5549e8e2c------2</link>
            <guid isPermaLink="false">https://medium.com/p/74a79aaa82e3</guid>
            <category><![CDATA[ibm-cloud]]></category>
            <category><![CDATA[cybersecurity]]></category>
            <category><![CDATA[ibm-watson]]></category>
            <category><![CDATA[tennis]]></category>
            <category><![CDATA[kubernetes]]></category>
            <dc:creator><![CDATA[Liz Rice]]></dc:creator>
            <pubDate>Sat, 06 Jul 2019 15:58:03 GMT</pubDate>
            <atom:updated>2019-07-06T15:58:03.911Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CsL7dO92UocemzAj3eqEBg.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dNDgXFzQj9MvAZGt9nQY4w.jpeg" /><figcaption>Inside the IBM Bunker</figcaption></figure><p>Who’d have realised there are 180 IBMers working in an underground bunker at Wimbledon?</p><p>IBM’s very excellent <a href="http://twitter.com/holly_cummins">Holly Cummins</a> invited me to take a look around and see more about the technology behind the scenes. Given my interest in cloud native, my first question was “Are you using Kubernetes?” And the answer is “yes”.</p><h3>Cloud native at Wimbledon</h3><p>To be honest, it’s a pretty straightforward use of Kubernetes: the <a href="http://wimbledon.com/">Wimbledon web site</a> is Apache / Java, running in four small clusters in the IBM cloud. Around 98% of the content gets served from cache by the CDN, so the load on the clusters themselves is actually pretty small.</p><p>But it‘s reassuring to see a familiar-looking Grafana dashboard, fed by Prometheus metrics. Cloud native technology quietly doing its job.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/994/1*TPgFi0TNl-kZHhHoZJ3caQ.png" /><figcaption>Stats from the Cori Gauff / Polona Hercog match</figcaption></figure><h3>Artificial intelligence applied to security</h3><p>Another area I was keen to hear about is security. Logs are collected by QRadar, and IBM’s Watson for Cybersecurity looks at these logs to recognize interesting patterns and anomalies that might indicate an unusual attack. Human security experts take it from there.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BWQGiAIzPht-xdfwVcq9fA.jpeg" /><figcaption>Physical schedule / score board. Despite all the technology, tradition is strong at Wimbledon.</figcaption></figure><p>This is essentially a perimeter defense — looking at the messages being sent from outside the system to detect potential attackers. Imagine the defence-in-depth you’d get by combining this alongside the sort of “shrink wrap” security we provide at <a href="http://aquasec.com/">Aqua</a>, where we’re detecting and preventing anomalous behaviour <em>within the containerized application</em>. If an attacker somehow manages to get past the outer defences, they’d still struggle to run their malicious payload.</p><p>There are some nice SOC-style screens showing world heat maps indicating where attacks are coming from, and live animations of suspicious events, but quite reasonably I’ve was asked not to share any of that information while the tournament is ongoing.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PY3_dEKHhe5712uFkTfwRw.jpeg" /><figcaption>Video feeds from each court</figcaption></figure><h3>Tennis statistics and video</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JNMRdUH2LwUFdGRdGSZC-g.jpeg" /><figcaption>Communications with the statisticians at each court</figcaption></figure><p>A lot of the interesting technology revolves around the interesting things you can do with video footage combined with data. Unlike, say, rugby or football, tennis is by its nature broken up point-by-point, and each point generates concrete statistics. Not just who won each point, but things like how long is the rally, what’s the service speed, whether the point was lost through an unforced error on a backhand, and so on.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*slofoyNEJDHHK3Z36oLBHQ.jpeg" /><figcaption>Tons of statistics available to players, coaches and commentators</figcaption></figure><p>If you’re an ex-tennis player looking to make some coin after your playing years are over, one option is to be a professional tennis statistician. This means watching matches, and recording a lot of these data points. Distance covered by each player is automatically generated from the video feed, and serve speed comes from radar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xIi3uKce7FvymY67J4AuhQ.jpeg" /><figcaption>“Match point: Zhang wins the point with a backhand volley winner”</figcaption></figure><p>These stats combined with the video footage enable Wimbledon to offer useful video tools to players and coaches. For example, you could look back at the match you just played and easily pull out and view, say, all the points you lost through unforced errors.</p><p>Here’s another screen that not everyone gets to see, and that takes some of these statistics into account: automatically generated recommendations for the most exciting points of the day so far. The system considers factors like crowd noise, player gesticulations, and the stats about how each point is won.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Pw3-XO5UvWndvvf_YuMX5g.jpeg" /><figcaption>Cori Gauff</figcaption></figure><p>Human editors use this to help them put together an hour of highlights from the day’s play. By my calculation that’s something like 1% of the total footage, so it’s making that editorial job considerably more manageable.</p><h3>A special atmosphere</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9XFeK9iPyYLa7M9IIIDWAw.jpeg" /><figcaption>Polona Hercog</figcaption></figure><p>I was lucky enough to be in Centre Court watching Cori Gauff win her terrifically exciting match against Polona Hercog. (If you didn’t already hear about this game: she turned it around from being behind in the second set, having already lost the first 6–3. And she’s 15 years old.) The atmosphere was fantastic — and it makes total sense that the crowd noise would be a great indicator for how exciting a point can be.</p><p>The Tour de France starts today. Anyone know if they’re using Kubernetes?</p><p><em>A </em><strong><em>giant</em></strong><em> thank you to </em><a href="https://medium.com/u/de2f9363914"><em>Holly K Cummins</em></a><em>, </em><a href="http://twitter.com/justinagilbert"><em>Justina Gilbert</em></a><em> and the </em><a href="http://twitter.com/ibm_uk_news"><em>IBM UK team</em></a><em> for the opportunity to see behind the scenes — not to mention watching some fabulous tennis and witnessing the unique Wimbledon atmosphere!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=74a79aaa82e3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A single-node Openshift 3.10 cluster]]></title>
            <link>https://medium.com/@lizrice/a-single-node-openshift-3-10-cluster-aaa63e2deed7?source=rss-d9e5549e8e2c------2</link>
            <guid isPermaLink="false">https://medium.com/p/aaa63e2deed7</guid>
            <category><![CDATA[openshift]]></category>
            <category><![CDATA[vagrant]]></category>
            <category><![CDATA[vagrantfile]]></category>
            <dc:creator><![CDATA[Liz Rice]]></dc:creator>
            <pubDate>Thu, 07 Mar 2019 16:26:01 GMT</pubDate>
            <atom:updated>2020-01-20T15:24:03.499Z</atom:updated>
            <content:encoded><![CDATA[<p>I need to try running <a href="http://github.com/aquasecurity/kube-bench">kube-bench</a> on Openshift and the easiest way seemed to me to run a single-node cluster in a Vagrant machine. It was really easy, but here are the steps.</p><h3>Vagrant machine running Centos</h3><p>Here’s my Vagrantfile:</p><pre>Vagrant.configure(&quot;2&quot;) do |config|<br>  config.vm.provider &quot;virtualbox&quot; do |v|<br>    v.memory = 16384<br>    v.cpus = 2<br>  end</pre><pre>config.vm.box = &quot;bento/centos-7.6&quot;<br>  config.vm.network &quot;private_network&quot;, type: &quot;dhcp&quot;<br>  config.vm.network &quot;forwarded_port&quot;, guest: 8443, host: 8443<br>  config.vm.provision &quot;docker&quot;<br>end</pre><p>Put this in an empty directory and run vagrant up</p><p>Once it’s up and running, get shell access to it with vagrant ssh</p><h3>Add insecure registries settings</h3><p>As per the instructions on this page you need to have Docker running with an insecure registry parameter. Create a file at /etc/docker/daemon.json (you’ll need to sudo) with the following contents:</p><pre>{<br>   &quot;insecure-registries&quot;: [<br>     &quot;172.30.0.0/16&quot;<br>   ]<br>}</pre><p>Restart Docker:</p><pre>$ sudo systemctl daemon-reload<br>$ sudo systemctl restart docker</pre><h3>Download Openshift binaries</h3><p>Download the version you want (I’m going for 3.10.0) from the <a href="https://github.com/openshift/origin/releases">Openshift releases page on GitHub</a>, and unpack it.</p><pre>$ wget <a href="https://github.com/openshift/origin/releases/download/v3.10.0/openshift-origin-client-tools-v3.10.0-dd10d17-linux-64bit.tar.gz">https://github.com/openshift/origin/releases/download/v3.10.0/openshift-origin-client-tools-v3.10.0-dd10d17-linux-64bit.tar.gz</a></pre><pre>$ tar xvf openshift-origin-client-tools-v3.10.0-dd10d17-linux-64bit.tar.gz</pre><p>I like to tidy this up:</p><pre>$ mv openshift-origin-client-tools-v3.10.0-dd10d17-linux-64bit openshift</pre><pre>$ rm openshift-origin-client-tools-v3.10.0-dd10d17-linux-64bit.tar.gz<br></pre><p>Now I have a directory called openshift</p><pre>$ ls openshift<br>LICENSE  oc  README.md</pre><h3>Add oc to your path</h3><p>If you’re using Openshift you’ll be running oc all the time (it’s roughly the equivalent of kubectl in Openshift-land) so you’ll want it in your path.</p><pre>$ export PATH=$PATH:~/openshift</pre><h3>Start the cluster</h3><p>Red Hat made this super simple!</p><pre>$ oc cluster up</pre><h3>Open the console</h3><p>Because of the port forwarding line in the Vagrantfile, you’ll be able to view the console in your browser at <a href="https://localhost:8443/">https://localhost:8443</a> (once you have pushed your way through a number of browser certificate warnings). You can log in as “developer” with any password.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oOZUZ0NegeIFnMffs6qKlw.png" /><figcaption>The OKD console</figcaption></figure><h3>All-in-one Vagrantfile</h3><p>To make this even easier, here’s a <a href="https://gist.github.com/lizrice/9107a625d17ad1bd3a5b9f770a62f984">Vagrantfile</a> with all the installation steps included. You’ll just need to vagrant up and then oc cluster start</p><p><em>If you’re using VS Code you might find it convenient to </em><a href="https://medium.com/@lizrice/ssh-to-vagrant-from-vscode-5b2c5996bc0e?source=friends_link&amp;sk=18ff608f93c4dc311d150c5cacc843e6"><em>SSH into Vagrant machines directly</em></a><em> from there.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aaa63e2deed7" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>