<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Scott</title>
    <description>The latest articles on Forem by Scott (@rusty_sys_dev).</description>
    <link>https://forem.com/rusty_sys_dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F177162%2F873081e7-9c68-44ea-9098-acb77a7aa2a9.jpeg</url>
      <title>Forem: Scott</title>
      <link>https://forem.com/rusty_sys_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rusty_sys_dev"/>
    <language>en</language>
    <item>
      <title>Important thing to remember about recovering panic'ed code in Go</title>
      <dc:creator>Scott</dc:creator>
      <pubDate>Mon, 13 Sep 2021 13:12:29 +0000</pubDate>
      <link>https://forem.com/rusty_sys_dev/important-thing-to-remember-about-recovering-panic-ed-code-in-go-2pe0</link>
      <guid>https://forem.com/rusty_sys_dev/important-thing-to-remember-about-recovering-panic-ed-code-in-go-2pe0</guid>
      <description>&lt;p&gt;When recovering from panic in golang, I have often found myself troubled by potentially not knowing where the error originated...&lt;/p&gt;

&lt;p&gt;This was because the stack doesn't get passed along with the message when you recover... or so I thought.&lt;/p&gt;

&lt;p&gt;Go's runtime actually handles recovery from panic in an interesting way.  Stack trace wise, it allows deferred functions the ability to call &lt;code&gt;debug.Stack()&lt;/code&gt; as if from the location of the panic.&lt;/p&gt;

&lt;p&gt;for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"runtime/debug"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;recover&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="n"&gt;f1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;f1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;f2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f3&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;f3&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"some error"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the stack trace output from the above code produces the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2021/09/13 22:00:07 some error: goroutine 1 [running]:
runtime/debug.Stack(0xc00009bdb8, 0x4acd60, 0x4e5168)
        /home/rustysysdev/go/src/runtime/debug/stack.go:24 +0x9f
main.main.func1()
        /home/rustysysdev/Documents/panic-test/cmd/panic/main.go:11 +0x5b
panic(0x4acd60, 0x4e5168)
        /home/rustysysdev/go/src/runtime/panic.go:965 +0x1b9
main.f3(...)
        /home/rustysysdev/Documents/panic-test/cmd/panic/main.go:27
main.f2(...)
        /home/rustysysdev/Documents/panic-test/cmd/panic/main.go:23
main.f1(...)
        /home/rustysysdev/Documents/panic-test/cmd/panic/main.go:19
main.main()
        /home/rustysysdev/Documents/panic-test/cmd/panic/main.go:15 +0x5e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this is very useful for troubleshooting and I feel stupid only figuring this out now. XD&lt;/p&gt;

&lt;p&gt;source: &lt;a href="https://groups.google.com/g/golang-nuts/c/MB8GyW5j2UY"&gt;https://groups.google.com/g/golang-nuts/c/MB8GyW5j2UY&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Setup Recent Xiaomi Phones on Rakuten Mobile</title>
      <dc:creator>Scott</dc:creator>
      <pubDate>Sun, 12 Sep 2021 07:31:19 +0000</pubDate>
      <link>https://forem.com/rusty_sys_dev/setup-recent-xiaomi-phones-on-rakuten-mobile-1hka</link>
      <guid>https://forem.com/rusty_sys_dev/setup-recent-xiaomi-phones-on-rakuten-mobile-1hka</guid>
      <description>&lt;p&gt;Warning: Before you bring a phone into japan you should check whether it is supported by your carrier's network bands at the below link.&lt;/p&gt;

&lt;p&gt;注意：携帯を日本に輸入する前にちゃんと自分が使いたいネットワークの周波数を対応していることを下記のリンクから確認してください。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gajeota.com/search"&gt;https://gajeota.com/search&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dqRhlyaa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bsko0ksy3qk3riltifw9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dqRhlyaa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bsko0ksy3qk3riltifw9.png" alt="gajeota"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So it took me some work to get my new Redmi K40 Gaming working with Rakuten Mobile here in Japan.  It was a pain so I want to share the procedure that worked for me.&lt;/p&gt;

&lt;p&gt;最近買った Xiaomi Redmi K40 Gaming を楽天モバイルに使えるように設定するのが苦労した。面倒だったなので使った手順を共有したい。&lt;/p&gt;

&lt;p&gt;The procedure itself is rather simple, and is comprised of hidden settings.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manually specify network protocols&lt;/li&gt;
&lt;li&gt;Unlock VoLTE (Voice over LTE)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;手順自体はかなりシンプルで、二つの隠し設定を開かないといけない。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ネットワークプロとコールを手動設定&lt;/li&gt;
&lt;li&gt;VoLTE を解放&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1 / 隠し設定1
&lt;/h2&gt;

&lt;p&gt;The first step of the solution I stumbled across, and was pretty lucky, otherwise it might have been much more difficult. That being said, if your phone happens to properly connect to the network after inserting the sim card you can skip this step.&lt;/p&gt;

&lt;p&gt;最初の隠し設定を混乱のなかで偶然に見つけちゃった。。そうではなければ今までも解決してないだろう。。ところでシムを本体にさしてネットワークは最初から動くのならこの設定はしなくても良いとおもう。&lt;/p&gt;

&lt;p&gt;First open your settings and click on &lt;code&gt;My Device&lt;/code&gt; &lt;br&gt;
先ず設定を開いて &lt;code&gt;My Device&lt;/code&gt; をクリック&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bSFW3tz8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2dot8hw7adq0w2p2uz4l.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bSFW3tz8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2dot8hw7adq0w2p2uz4l.jpeg" alt="settings_top_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next open your device's &lt;code&gt;All Specs&lt;/code&gt; page&lt;br&gt;
次は `All Specs のページを開く&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6qtsnyLK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uymgmz644vf4dwqdzwat.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6qtsnyLK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uymgmz644vf4dwqdzwat.jpeg" alt="my device"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where our hidden setting is located.  Click on the &lt;code&gt;Internal Storage&lt;/code&gt; field 5 to 10 times.. or until you move to the &lt;code&gt;Testing page&lt;/code&gt;&lt;br&gt;
ここで隠し設定はある、&lt;code&gt;Internal Storage&lt;/code&gt; を &lt;code&gt;Testing&lt;/code&gt; ページに移動するまで連続クリック（5〜10かい程度）&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LI1fyQyO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/59cf88i2txh0bj4ipx4v.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LI1fyQyO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/59cf88i2txh0bj4ipx4v.jpeg" alt="all specs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the &lt;code&gt;Phone Information1&lt;/code&gt; button.&lt;br&gt;
ここでは &lt;code&gt;Phone Information1&lt;/code&gt; をクリック&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0QLrbNZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/shfrvoyvx2coajqxwife.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0QLrbNZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/shfrvoyvx2coajqxwife.jpeg" alt="testing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Set Prefered Network Type&lt;/code&gt; to &lt;code&gt;NR/LTE&lt;/code&gt; If the phone doesn't connect in 10 seconds try some other protocol combinations until it does. &lt;/p&gt;

&lt;p&gt;NOTE: this may lock your phone to certain protocols so just know that NR = 5G and LTE = 4G. Everything else is typically 3G and below!&lt;/p&gt;

&lt;p&gt;注目：NR は 5G と LTE は 4G のネットワークをしめしているその他のは3Gとその以下&lt;/p&gt;

&lt;p&gt;ここでは &lt;code&gt;Set Prefered Network Type&lt;/code&gt; を &lt;code&gt;NR/LTE&lt;/code&gt; に設定、10秒程度で携帯が接続するはずが、接続できなかった場合、上記の注目を認識したの上で他の組み合わせを試すといい&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F-ro66Eo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4kdj1nasqhs6u8euhdup.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F-ro66Eo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4kdj1nasqhs6u8euhdup.jpeg" alt="phone1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 / 隠し設定2
&lt;/h2&gt;

&lt;p&gt;The second step is pretty simple, and I found on a youtube video, and seems to be the universal way of locking and unlocking VoLTE on phones.&lt;/p&gt;

&lt;p&gt;隠し設定2のも大した難しくはないけどしらないと。。youtube で答えを見つけたところにどんな Xiaomi 機種でも VoLTE を有無の一般的な設定方法らしい。&lt;/p&gt;

&lt;p&gt;Simply open your the phone app and input the following phone code.&lt;br&gt;
電話アプリを開いて下記のコードを入力&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
*#*#86583#*#*&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As soon as you input the code you should see a message similar to &lt;code&gt;VoLTE has been enabled&lt;/code&gt; or possibly &lt;code&gt;VoLTE has been disabled&lt;/code&gt;.  This message is apparently buggy... so don't worry about it quite yet.&lt;br&gt;
入力だけで &lt;code&gt;VoLTE は有効になった&lt;/code&gt; または &lt;code&gt;VoLTE は有効になった&lt;/code&gt; のようなメッセージは表示される。無効になったと言っても取り敢えず進んでください。&lt;/p&gt;

&lt;p&gt;First we need to find the VoLTE setting which should now be available in your sim card's settings menu. Open your settings.&lt;br&gt;
先ず上記の手順で現れた VoLTE 設定をみつけよう。携帯の設定を開く&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p52IjvCs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/69uvyvrg988w5xis3ppi.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p52IjvCs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/69uvyvrg988w5xis3ppi.jpeg" alt="settings_top_2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select your &lt;code&gt;Rakuten&lt;/code&gt; sim card.&lt;br&gt;
&lt;code&gt;Rakuten&lt;/code&gt; のシムを選択&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4jQhmc29--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pj0qp6ytk6wmp9opltf8.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4jQhmc29--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pj0qp6ytk6wmp9opltf8.jpeg" alt="sim cards"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check that you have a VoLTE Setting here, and that it is enabled.  If the setting doesn't exist then go back and enter the code again.&lt;br&gt;
この辺で VoLTE 設定は存在すると有効になっていることを確認してください。存在しなかった場合先ほどのコードをもう一度入力してみるがよい&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r-240ZaD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j903o67267gbdtw3j12t.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r-240ZaD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j903o67267gbdtw3j12t.jpeg" alt="sim settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion / 最後に
&lt;/h2&gt;

&lt;p&gt;From here you should be able to install &lt;code&gt;Rakuten Link&lt;/code&gt; and perform the necessary setup.&lt;/p&gt;

&lt;p&gt;上記が終わったら、SMS と電話は両方使用可能になったはずので &lt;code&gt;Rakuten Link&lt;/code&gt; のダウンロードと設定は可能なはす。。。&lt;/p&gt;

</description>
      <category>english</category>
      <category>japanese</category>
      <category>memo</category>
    </item>
    <item>
      <title>Understanding Yew Part 1</title>
      <dc:creator>Scott</dc:creator>
      <pubDate>Thu, 07 Jan 2021 14:05:15 +0000</pubDate>
      <link>https://forem.com/rusty_sys_dev/understanding-yew-part-1-3cfn</link>
      <guid>https://forem.com/rusty_sys_dev/understanding-yew-part-1-3cfn</guid>
      <description>&lt;p&gt;Hello! I am learning Yew for writing SPA's in Rust!  I found some of the concepts difficult to understand at first and decided to take notes (simplifying the concepts for my stupid brain)..&lt;/p&gt;

&lt;p&gt;I am planning on making this a series with the following.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Yew component and lifecycle overview
2. Yew router overview
3. Yew fetch service overview
4. Yew agents overview
5. Debugging (maybe)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Without further ado, lets get into part 1!&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;p&gt;Are semi-arbitrary Rust structures that~&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Represent pecies of reusable HTML&lt;/li&gt;
&lt;li&gt;Utilized by name in HTML&lt;/li&gt;
&lt;li&gt;Have a defined lifecycle&lt;/li&gt;
&lt;li&gt;Contain their own state&lt;/li&gt;
&lt;li&gt;Recieve props from parent component&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Components can contain many child components, but logically speaking have only one parent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mermaid-js.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZXJEaWFncmFtXG4gIFBhcmVudENvbXBvbmVudCB8fC0tb3sgQ2hpbGRDb21wb25lbnQgOiBcIlVzZXMgQ2hpbGRDb21wb25lbnQgaW4gSFRNTFwiIiwibWVybWFpZCI6e30sInVwZGF0ZUVkaXRvciI6ZmFsc2V9" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FeyJjb2RlIjoiZXJEaWFncmFtXG4gIFBhcmVudENvbXBvbmVudCB8fC0tb3sgQ2hpbGRDb21wb25lbnQgOiBcIlVzZXMgQ2hpbGRDb21wb25lbnQgaW4gSFRNTFwiIiwibWVybWFpZCI6e30sInVwZGF0ZUVkaXRvciI6ZmFsc2V9"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Parent Component --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Main Component Text&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Child Component with 2 properties --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ChildComponent1&lt;/span&gt; &lt;span class="na"&gt;cc1prop1=&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt; &lt;span class="na"&gt;cc1prop2=&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Another Child Component with 1 property --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ChildComponent2&lt;/span&gt; &lt;span class="na"&gt;cc2prop1=&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data relationships between parent and child are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parents may pass data as Props to Child Components&lt;/li&gt;
&lt;li&gt;Parents may pass callbacks as Props&lt;/li&gt;
&lt;li&gt;Child may update parent state using callback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the above said, as an example if you have many child components that need to manage a common state, that state should be stored in a parent element.&lt;/p&gt;

&lt;h4&gt;
  
  
  Common Component Structure Properties
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;struct&lt;/code&gt; created to define your component tends to have a couple of important and common parameters. For example~&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This is another arbitrary struct containing data&lt;/span&gt;
    &lt;span class="c1"&gt;// that YOU require for your application's state. &lt;/span&gt;
    &lt;span class="c1"&gt;// You need to create this State struct, or whatever&lt;/span&gt;
    &lt;span class="c1"&gt;// you want to call it.&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// You will need to add this property if you intend&lt;/span&gt;
    &lt;span class="c1"&gt;// to interact with the Component API, i.e. adding &lt;/span&gt;
    &lt;span class="c1"&gt;// callbacks to modify this component's state, or&lt;/span&gt;
    &lt;span class="c1"&gt;// sending update messages to call update() actions&lt;/span&gt;
    &lt;span class="c1"&gt;// on the component.&lt;/span&gt;
    &lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ComponentLink&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// Used in relation to calling external API's&lt;/span&gt;
    &lt;span class="c1"&gt;// I will follow up on this in a new article.&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// This is yet another arbitrary struct that you will&lt;/span&gt;
    &lt;span class="c1"&gt;// need to create in order to define properties sent&lt;/span&gt;
    &lt;span class="c1"&gt;// by a parent component.&lt;/span&gt;
    &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Component Implemetation
&lt;/h4&gt;

&lt;p&gt;A components are implemented suprisingly enough by &lt;code&gt;impl yew::Component for YOUR_COMPONENT {}&lt;/code&gt; required methods and types to implement are as follows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kind&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;td&gt;Properties&lt;/td&gt;
&lt;td&gt;Properties to the component during lifecycle events.  If none are to be passed this should be &lt;code&gt;()&lt;/code&gt;. Otherwise you will need to define your &lt;code&gt;Props&lt;/code&gt; struct.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;td&gt;Message&lt;/td&gt;
&lt;td&gt;An &lt;code&gt;enum&lt;/code&gt; containing actions to process during a component lifecycle &lt;code&gt;update()&lt;/code&gt;.  &lt;code&gt;enum&lt;/code&gt; members may contain parameters.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Method&lt;/td&gt;
&lt;td&gt;create()&lt;/td&gt;
&lt;td&gt;Initializes state and stores props from the parent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Method&lt;/td&gt;
&lt;td&gt;update()&lt;/td&gt;
&lt;td&gt;Called for whenever an update message is sent.  &lt;code&gt;update()&lt;/code&gt; should take appropriate action depending on the message sent.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Method&lt;/td&gt;
&lt;td&gt;change()&lt;/td&gt;
&lt;td&gt;This method conditionally re-renders the child component if props have changed during re-rendering of the parent.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Method&lt;/td&gt;
&lt;td&gt;rendered()&lt;/td&gt;
&lt;td&gt;This method is called after &lt;code&gt;view()&lt;/code&gt; and performs functions that require the component to already be rendered.  I.E. shift screen focus to element. (NOT REQUIRED)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Method&lt;/td&gt;
&lt;td&gt;destroy()&lt;/td&gt;
&lt;td&gt;Performs cleanup operations for a component (NOT REQUIRED)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Method&lt;/td&gt;
&lt;td&gt;veiw()&lt;/td&gt;
&lt;td&gt;Creates the HTML to render for the component.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Component Lifecycle
&lt;/h4&gt;

&lt;p&gt;A components life begins when it its &lt;code&gt;create()&lt;/code&gt; method is called.  This typically happens in an &lt;code&gt;html!()&lt;/code&gt; macro.  &lt;/p&gt;

&lt;p&gt;TODO: I feel I should give an example of this&lt;/p&gt;

&lt;p&gt;Next its &lt;code&gt;view()&lt;/code&gt; method is called and the component is rendered as HTML.&lt;/p&gt;

&lt;p&gt;A component will be re-rendered on the following conditions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A re-render is requested by the &lt;code&gt;change()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;A re-render is requested by the &lt;code&gt;update()&lt;/code&gt; method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A component will be destroyed when simply enough, its &lt;code&gt;destroy()&lt;/code&gt; method is called.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I will revisit this for to update any errors or missing information, but for now I feel I have summed up yew components to my satisfaction.  If anyone has any questions or notices any mistakes please let me know in the comments! &lt;/p&gt;

</description>
      <category>rust</category>
      <category>yew</category>
      <category>webassembly</category>
    </item>
    <item>
      <title>Creating service account IAM roles on EKS</title>
      <dc:creator>Scott</dc:creator>
      <pubDate>Thu, 17 Dec 2020 14:22:32 +0000</pubDate>
      <link>https://forem.com/rusty_sys_dev/creating-service-account-roles-on-eks-gj7</link>
      <guid>https://forem.com/rusty_sys_dev/creating-service-account-roles-on-eks-gj7</guid>
      <description>&lt;p&gt;As of the time of this writing AWS still seems to be working on their not so streamlined IAM for Service Accounts feature.&lt;/p&gt;

&lt;p&gt;Its not difficult to get running but you have to jump through quite a few hoops especially when it comes to the command line.&lt;/p&gt;

&lt;p&gt;If you do everything with &lt;code&gt;eksctl&lt;/code&gt; or the AWS Console, then its really easy.  If you didn't use &lt;code&gt;eksctl&lt;/code&gt; to build your cluster and would like to make things simple and script it... well that's a different story.&lt;/p&gt;

&lt;h2&gt;
  
  
  What needs to happen
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create an OpenIDConnect Provider in IAM based off your EKS cluster's issuer URL.  This requires the following.

&lt;ul&gt;
&lt;li&gt;EKS cluster's issuer URL&lt;/li&gt;
&lt;li&gt;ClientID string: "sts.amazonaws.com"&lt;/li&gt;
&lt;li&gt;EKS cluster's domain footprint&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Role for attaching to a service account.  This requires the following.

&lt;ul&gt;
&lt;li&gt;IAM Policy(s)&lt;/li&gt;
&lt;li&gt;trust relationship document&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Create/Annotate your pod's service account&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Whats the problem
&lt;/h2&gt;

&lt;p&gt;Some of the requirements listed above are not so straightforward to obtain or setup.  In particular two of them come to mind.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EKS cluster's domain footprint&lt;/li&gt;
&lt;li&gt;Role trust relationship document&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;lets take a look at these.&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain Footprint
&lt;/h3&gt;

&lt;p&gt;This was the biggest issue I faced... and purely because the &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html"&gt;documentation for obtaining this&lt;/a&gt; in anyway other than the AWS Console is incorrect.  In particular (2) in the linked document returns the following error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Missing Authentication Token"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I tried for sometime to accomplish (2) but I eventually gave up and searched for another way.  In my search I came across an &lt;a href="https://github.com/hashicorp/terraform-provider-aws/issues/10104#issuecomment-659892848"&gt;issue in terraforms-provider-aws&lt;/a&gt; That gave me the clue I needed and I was finally able to move on after writing a function to not only grab the footprint but create the IAM provider if not exists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;create_provider_if_not_exists&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;PROVIDER_LIST PROVIDER_ARN THUMBPRINT
    &lt;span class="nv"&gt;PROVIDER_LIST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws iam list-open-id-connect-providers &lt;span class="nt"&gt;--query&lt;/span&gt; OpenIDConnectProviderList &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;PROVIDER_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;PROVIDER &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROVIDER_LIST&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROVIDER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROVIDER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="k"&gt;return
        fi
    done&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROVIDER_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nv"&gt;FOOTPRINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; | openssl s_client &lt;span class="nt"&gt;-servername&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-showcerts&lt;/span&gt; &lt;span class="nt"&gt;-connect&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;:443 2&amp;gt;&amp;amp;- &lt;span class="se"&gt;\&lt;/span&gt;
            | &lt;span class="nb"&gt;tac&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'/-----END CERTIFICATE-----/,/-----BEGIN CERTIFICATE-----/p; /-----BEGIN CERTIFICATE-----/q'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
            | &lt;span class="nb"&gt;tac&lt;/span&gt; | openssl x509 &lt;span class="nt"&gt;-fingerprint&lt;/span&gt; &lt;span class="nt"&gt;-sha1&lt;/span&gt; &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
            | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/://g'&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'{print tolower($2)}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
        aws iam create-open-id-connect-provider &lt;span class="se"&gt;\&lt;/span&gt;
            &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
            &lt;span class="nt"&gt;--client-id-list&lt;/span&gt; &lt;span class="s2"&gt;"sts.amazonaws.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
            &lt;span class="nt"&gt;--thumbprint-list&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FOOTPRINT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
            &lt;span class="nt"&gt;--query&lt;/span&gt; OpenIDConnectProviderArn
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Role Trust Relationship
&lt;/h3&gt;

&lt;p&gt;This wasn't particularly hard, just annoying if not automated.  I used &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html"&gt;AWS documentation here&lt;/a&gt; and created a function to create and destroy the required document.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;create_trust_relationship_file&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;TRUST_RELATIONSHIP
    &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; TRUST_RELATIONSHIP &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;#*/&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;:sub": "system:serviceaccount:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"
        }
      }
    }
  ]
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TRUST_RELATIONSHIP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; trust.json
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;delete_trust_relationship_file&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; trust.json
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complete Script
&lt;/h2&gt;

&lt;p&gt;With that finished I just needed to fill in the blanks and got the following which creates required resources and gives you the service annotation to add to your service account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;create_eks_pod_role&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;CLUSTER_NAME ROLE_NAME ROLE_DESCRIPTION CONTAINER_POLICY_ARN SERVICE_ACCOUNT_NAME
    &lt;span class="nb"&gt;local &lt;/span&gt;ISSUER_ADDRESS ISSUER_ID ISSUER_DOMAIN PROVIDER_ARN ROLE_ARN NAMESPACE
    &lt;span class="k"&gt;function &lt;/span&gt;usage&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Outputs rendered files for specified chart into current directory.
           &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FUNCNAME&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; -
                   [-h] print this help
                   -c   Name of the EKS Cluster
                   -r   Name of the IAM role to create
                   -d   Description for IAM role
                   -p   IAM policy ARN of to attach to the role
                   -s   Name of the service account
                   -n   Namespace of the service account"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;function &lt;/span&gt;check_policy_exists&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;local &lt;/span&gt;POLICY_LIST POLICY
        &lt;span class="nv"&gt;POLICY_LIST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws iam list-policies &lt;span class="nt"&gt;--query&lt;/span&gt; Policies[].Arn &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;for &lt;/span&gt;POLICY &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;POLICY_LIST&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
            if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;POLICY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
                return &lt;/span&gt;0
            &lt;span class="k"&gt;fi
        done
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"INVALID: your policy arn seems to be invalid please verify"&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;1
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;function &lt;/span&gt;create_provider_if_not_exists&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;local &lt;/span&gt;PROVIDER_LIST PROVIDER_ARN THUMBPRINT
        &lt;span class="nv"&gt;PROVIDER_LIST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws iam list-open-id-connect-providers &lt;span class="nt"&gt;--query&lt;/span&gt; OpenIDConnectProviderList &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;PROVIDER_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;PROVIDER &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROVIDER_LIST&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
            if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROVIDER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
                &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROVIDER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
                &lt;span class="k"&gt;return
            fi
        done&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROVIDER_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nv"&gt;FOOTPRINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; | openssl s_client &lt;span class="nt"&gt;-servername&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-showcerts&lt;/span&gt; &lt;span class="nt"&gt;-connect&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;:443 2&amp;gt;&amp;amp;- &lt;span class="se"&gt;\&lt;/span&gt;
                | &lt;span class="nb"&gt;tac&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'/-----END CERTIFICATE-----/,/-----BEGIN CERTIFICATE-----/p; /-----BEGIN CERTIFICATE-----/q'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                | &lt;span class="nb"&gt;tac&lt;/span&gt; | openssl x509 &lt;span class="nt"&gt;-fingerprint&lt;/span&gt; &lt;span class="nt"&gt;-sha1&lt;/span&gt; &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/://g'&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'{print tolower($2)}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
            aws iam create-open-id-connect-provider &lt;span class="se"&gt;\&lt;/span&gt;
                &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                &lt;span class="nt"&gt;--client-id-list&lt;/span&gt; &lt;span class="s2"&gt;"sts.amazonaws.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                &lt;span class="nt"&gt;--thumbprint-list&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FOOTPRINT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                &lt;span class="nt"&gt;--query&lt;/span&gt; OpenIDConnectProviderArn
        &lt;span class="k"&gt;else
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROVIDER_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;fi&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;function &lt;/span&gt;create_trust_relationship_file&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;local &lt;/span&gt;TRUST_RELATIONSHIP
        &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; TRUST_RELATIONSHIP &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;#*/&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;:sub": "system:serviceaccount:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"
        }
      }
    }
  ]
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TRUST_RELATIONSHIP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; trust.json
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;function &lt;/span&gt;delete_trust_relationship_file&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; trust.json
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;# Set options&lt;/span&gt;
    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;getopts&lt;/span&gt; &lt;span class="s1"&gt;':c:r:d:p:s:n:'&lt;/span&gt; OPTION&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OPTION&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in
            &lt;/span&gt;c&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nv"&gt;CLUSTER_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPTARG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;;;&lt;/span&gt;
            r&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nv"&gt;ROLE_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPTARG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;;;&lt;/span&gt;
            d&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nv"&gt;ROLE_DESCRIPTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPTARG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;;;&lt;/span&gt;
            p&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nv"&gt;CONTAINER_POLICY_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPTARG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;;;&lt;/span&gt;
            s&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nv"&gt;SERVICE_ACCOUNT_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPTARG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;;;&lt;/span&gt;
            n&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nv"&gt;NAMESPACE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPTARG&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;;;&lt;/span&gt;
            &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                usage&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;return &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;;;&lt;/span&gt;
        &lt;span class="k"&gt;esac&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ROLE_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ROLE_DESCRIPTION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_POLICY_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SERVICE_ACCOUNT_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAMESPACE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; usage&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; check_policy_exists &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_POLICY_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        return &lt;/span&gt;1
    &lt;span class="k"&gt;fi

    &lt;/span&gt;&lt;span class="nv"&gt;ISSUER_ADDRESS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws eks describe-cluster &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"cluster.identity.oidc.issuer"&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;ISSUER_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ISSUER_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;#https&lt;/span&gt;://&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nv"&gt;ISSUER_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ISSUER_ID&lt;/span&gt;&lt;span class="p"&gt;%%/*&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nv"&gt;PROVIDER_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;create_provider_if_not_exists &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ISSUER_ADDRESS&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ISSUER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ISSUER_DOMAIN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    create_trust_relationship_file &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROVIDER_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SERVICE_ACCOUNT_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAMESPACE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nv"&gt;ROLE_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws iam create-role &lt;span class="nt"&gt;--role-name&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ROLE_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                        &lt;span class="nt"&gt;--assume-role-policy-document&lt;/span&gt; file://trust.json &lt;span class="se"&gt;\&lt;/span&gt;
                        &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ROLE_DESCRIPTION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                        &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="nt"&gt;--query&lt;/span&gt; Role.Arn&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    delete_trust_relationship_file
    aws iam attach-role-policy &lt;span class="nt"&gt;--role-name&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ROLE_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--policy-arn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_POLICY_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"コンテナーのサービスアカウントの annotations に下記を追加"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"    eks.amazonaws.com/role-arn: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ROLE_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ AWS_DEFAULT_REGION=us-east-1 create_eks_pod_role -c TestCluster -r loki-s3-role-test-2 -d "test role for loki s3 integration" -p arn:aws:iam::aws:policy/AmazonS3FullAccess -s a9t-loki -n monitoring-system
コンテナーのサービスアカウントの annotations に下記を追加
    eks.amazonaws.com/role-arn: arn:aws:iam::636082426924:role/loki-s3-role-test-2

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't mind the Japanese it just states that the below is to be added to the annotations of your pods service account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, it was kind of a pain to create this script.. but its definitely simplifies my work-flow when creating roles for my pods.  Feel free to use it if you like, and don't hesitate to let me know if you have any questions or concerns!&lt;/p&gt;

</description>
      <category>eks</category>
      <category>kubernetes</category>
      <category>iam</category>
      <category>relax</category>
    </item>
    <item>
      <title>Using KinD with Podman (kinp)</title>
      <dc:creator>Scott</dc:creator>
      <pubDate>Sat, 12 Dec 2020 12:07:37 +0000</pubDate>
      <link>https://forem.com/rusty_sys_dev/using-kind-with-podman-kinp-2064</link>
      <guid>https://forem.com/rusty_sys_dev/using-kind-with-podman-kinp-2064</guid>
      <description>&lt;p&gt;I've been using kind on ec2 for a while now because I was too lazy to work around issues I was having locally.  I finally go around to writing a shell wrapper for kind today and would like to share.&lt;/p&gt;

&lt;p&gt;If you have any issues please let me know!&lt;/p&gt;

&lt;p&gt;Disclaimer: This has been tested to work on Fedora 33 only but should work on other systems (provided you have podman installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install kinp
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/rustysys-dev/kinp.git
&lt;span class="nb"&gt;cd &lt;/span&gt;kinp

&lt;span class="c"&gt;# install main script to /usr/bin/kinp&lt;/span&gt;
&lt;span class="c"&gt;# installs library script to /usr/lib/kinp/libkinp&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using kinp
&lt;/h2&gt;

&lt;p&gt;kinp is used exactly as you would kind. That being said, kinp will download all dependencies before running (provided they do not already exist).&lt;/p&gt;

&lt;p&gt;Dependencies include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;kubectl&lt;/li&gt;
&lt;li&gt;kind&lt;/li&gt;
&lt;li&gt;awscli (if AWS_ACCOUNT_ID env_var is set)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create cluster
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kinp create cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Check cluster
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Destroy cluster
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kinp delete cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There you have it Kubernetes in Podman! If you have any questions or comments please let me know!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>kind</category>
      <category>podman</category>
      <category>kinp</category>
    </item>
    <item>
      <title>Create/Expose Test Kubernetes Cluster on EC2 with kind </title>
      <dc:creator>Scott</dc:creator>
      <pubDate>Sat, 05 Sep 2020 08:53:37 +0000</pubDate>
      <link>https://forem.com/rusty_sys_dev/create-expose-test-kubernetes-cluster-on-ec2-with-kind-16c3</link>
      <guid>https://forem.com/rusty_sys_dev/create-expose-test-kubernetes-cluster-on-ec2-with-kind-16c3</guid>
      <description>&lt;h1&gt;
  
  
  WHY???! 😂
&lt;/h1&gt;

&lt;p&gt;Well first off, there may have been better solutions for standing up a test cluster cheaply on EC2, but my thought process didn't lead me there.  What was my thought process?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Need to test grafana dashboard on a test cluster..&lt;/li&gt;
&lt;li&gt;Install Kind locally..&lt;/li&gt;
&lt;li&gt;Kind doesn't work with experimental backend podman&lt;/li&gt;
&lt;li&gt;Lets install kind on EC2.. Install Kind on EC2..&lt;/li&gt;
&lt;li&gt;I want to work seamlessly from my workstation..&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point in the thought process I was too focused on how to force Kind to meet my expectations than "Maybe there is a better way"... in anycase I got it to work, and wanted to record my process so that I wouldn't forget what I learned.&lt;/p&gt;

&lt;h1&gt;
  
  
  How I did it?
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Install Kind&lt;/li&gt;
&lt;li&gt;Configure EC2&lt;/li&gt;
&lt;li&gt;Configure Local Environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I had to run through a couple of hoops when configuring the local environment, but other than that it was pretty straight forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Kind
&lt;/h2&gt;

&lt;p&gt;In order to install Kind with exposed ports (for connecting with kubectl from local pc) a Kind configuration file is necessary to override the default settings during the deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Kind Configuration File
&lt;/h3&gt;

&lt;p&gt;The following configuration file &lt;code&gt;kind.yaml&lt;/code&gt; changes the bind address:port for the Kubernetes API server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cluster&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kind.x-k8s.io/v1alpha4&lt;/span&gt;
&lt;span class="na"&gt;networking&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;apiServerAddress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0"&lt;/span&gt;
  &lt;span class="na"&gt;apiServerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7443&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a foot-note, you should never use a setup like this in production.  Aside from the fact that Kind shouldn't ever be used in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy Kind
&lt;/h3&gt;

&lt;p&gt;Deploying the cluster is as easy as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kind create cluster --config kind.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure EC2
&lt;/h2&gt;

&lt;p&gt;Now that we have Kind deployed and bound to &lt;code&gt;0.0.0.0:7433&lt;/code&gt; we need to open that port on the node's security group.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure Security Group
&lt;/h3&gt;

&lt;p&gt;Create an ingress rule similar to the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmely667wh6r66v9rk2dw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmely667wh6r66v9rk2dw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have taken this screenshot using the IP &lt;code&gt;0.0.0.0&lt;/code&gt; to hide my actual IP.  In practice this Ingress rule should be limited to the IP from which you will be accessing the cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Local Environment
&lt;/h2&gt;

&lt;p&gt;We now that we have our cluster created, and enabled access through our security groups we can configure our local environment to connect to the API.&lt;/p&gt;

&lt;p&gt;The API certificates generated by Kind will not support your EC2 instance's domain name or IP so we will need to define a hostname supported by the certificate in your &lt;code&gt;/etc/hosts&lt;/code&gt; file to be used for connecting to the API.  Additionally unless you have used an Elastic-IP you will need to take some precautions to make connecting to the API easy between each stop / start of the EC2 Instance.  &lt;/p&gt;

&lt;p&gt;To help with this, we will define two functions to assign/update the current IP of your EC2 instance to the name &lt;code&gt;kind-control-plane&lt;/code&gt; (which is supported by the certificates generated by Kind) in your &lt;code&gt;/etc/hosts&lt;/code&gt; file. &lt;/p&gt;

&lt;h3&gt;
  
  
  Create Helper Aliases
&lt;/h3&gt;

&lt;p&gt;Adds current public IP of your EC2 instance to the name &lt;code&gt;kind-control-plane&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;add-dev-machine-ip &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
    &lt;span class="nb"&gt;sudo &lt;/span&gt;bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws ec2 describe-instances &lt;span class="nt"&gt;--instance-ids&lt;/span&gt; &amp;lt;your-instance-id&amp;gt; &lt;span class="nt"&gt;--query&lt;/span&gt; Reservations[0].Instances[0].PublicIpAddress&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; kind-control-plane &amp;gt;&amp;gt; /etc/hosts"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Updates current public IP of your EC2 instance to the entry made by the previous command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;update-dev-machine-ip &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
    &lt;span class="nb"&gt;sudo sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"s/^.* kind-control-plane.*&lt;/span&gt;&lt;span class="nv"&gt;$/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws ec2 describe-instances &lt;span class="nt"&gt;--instance-ids&lt;/span&gt; &amp;lt;your-instance-id&amp;gt; &lt;span class="nt"&gt;--query&lt;/span&gt; Reservations[0].Instances[0].PublicIpAddress&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; kind-control-plane/"&lt;/span&gt; /etc/hosts
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Realistically you will probably only run the first command once and then never need it... but I felt the need to make it a function anyway.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update &lt;code&gt;/etc/hosts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Add IP to &lt;code&gt;/etc/hosts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;add-dev-machine-ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo cat /etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[rustysysdev@localhost ~]$ sudo cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
54.99.142.93 kind-control-plane
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure Kubectl
&lt;/h3&gt;

&lt;p&gt;Lastly, with our networking fixed we can configure kubectl to connect to our API server.&lt;/p&gt;

&lt;p&gt;We will need to splice the &lt;code&gt;~/.kube/config&lt;/code&gt; generated by Kind on the EC2 instance with our local &lt;code&gt;~/.kube/config&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  EC2 Instance
&lt;/h4&gt;

&lt;p&gt;Output the &lt;code&gt;~/.kube/config&lt;/code&gt; generated by Kind.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.kube/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will look similar to the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: XXXXXXXXXXXXXX
    server: https://0.0.0.0:7443
  name: kind-kind
contexts:
- context:
    cluster: kind-kind
    user: kind-kind
  name: kind-kind
current-context: kind-kind
kind: Config
preferences: {}
users:
- name: kind-kind
  user:
    client-certificate-data: XXXXXXXXXXXXXX
    client-key-data: XXXXXXXXXXXXXX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Local PC
&lt;/h4&gt;

&lt;p&gt;If you already have a local &lt;code&gt;~/.kube/config&lt;/code&gt; you will need to splice the above configuration into your local file. &lt;/p&gt;

&lt;p&gt;In this example you would need to modify the following elements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clusters:&lt;/li&gt;
&lt;li&gt;contexts:&lt;/li&gt;
&lt;li&gt;users:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add to the &lt;code&gt;clusters:&lt;/code&gt; element in your local file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- cluster:
    certificate-authority-data: XXXXXXXXXXXXXX
    server: https://kind-control-plane:7443
  name: kind-kind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;be mindful to change the &lt;code&gt;0.0.0.0&lt;/code&gt; portion of the server address to the &lt;code&gt;kind-control-plane&lt;/code&gt; hostname we defined earlier.&lt;/p&gt;

&lt;p&gt;Add to the &lt;code&gt;context:&lt;/code&gt; element in your local file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- context:
    cluster: kind-kind
    user: kind-kind
  name: kind-kind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add to the &lt;code&gt;users:&lt;/code&gt; element in your local file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: kind-kind
  user:
    client-certificate-data: XXXXXXXXXXXXXX
    client-key-data: XXXXXXXXXXXXXX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you do not have a local &lt;code&gt;~/.kube/config&lt;/code&gt; file you can create one and copy/paste the file from your EC2 instance.  Mindful of course that you change the &lt;code&gt;https://0.0.0.0:7443&lt;/code&gt; to &lt;code&gt;https://kind-control-plane:7443&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing your setup
&lt;/h2&gt;

&lt;p&gt;Switch to your &lt;code&gt;kind-kind&lt;/code&gt; context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl config use-context kind-kind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get node information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is configured properly you should see output similar to the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME                 STATUS   ROLES    AGE   VERSION
kind-control-plane   Ready    master   26h   v1.18.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;And there you have it, your own Kind cluster running in EC2 with local access.  If anyone has any questions, please let me know!! &lt;/p&gt;

</description>
      <category>ec2</category>
      <category>kubernetes</category>
      <category>kind</category>
    </item>
    <item>
      <title>Deploy Zulip messaging using podman play</title>
      <dc:creator>Scott</dc:creator>
      <pubDate>Thu, 03 Sep 2020 11:39:42 +0000</pubDate>
      <link>https://forem.com/rusty_sys_dev/deploy-zulip-messaging-using-podman-play-143e</link>
      <guid>https://forem.com/rusty_sys_dev/deploy-zulip-messaging-using-podman-play-143e</guid>
      <description>&lt;h1&gt;
  
  
  What is Zulip?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://zulipchat.com/why-zulip/"&gt;Zulip&lt;/a&gt; is like Slack or Mattermost, a messaging server for teams to communicate on a project. Overview of Zulip features is out of scope for this article, but for those interested you can find more information &lt;a href="https://zulipchat.com/features/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  My reasons for writing this article
&lt;/h1&gt;

&lt;p&gt;My reasons for writing this article are two-fold. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dissatisfaction with the &lt;a href="https://mattermost.com/"&gt;Mattermost&lt;/a&gt; interface.. particularly threads being hard to read.&lt;/li&gt;
&lt;li&gt;My daily driver being Fedora 32, which utilizies cgroups version 2 doesn't support Docker out of the box.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Mattermost interface has many great things and its integrations are amazing, but it handles threads in a dis-satisfactory manner.&lt;/p&gt;

&lt;p&gt;Without Docker I have to translate projects to podman as I go my local environment.  I use various tools to do this &lt;a href="https://github.com/containers/podman-compose"&gt;podman-compose&lt;/a&gt;, &lt;a href="https://github.com/kubernetes/kompose"&gt;Kompose&lt;/a&gt;, &lt;code&gt;podman generate&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h1&gt;
  
  
  Deploying Zulip with podman
&lt;/h1&gt;

&lt;p&gt;This morning with a lot of work translating &lt;a href="https://github.com/zulip/docker-zulip"&gt;docker-zulip&lt;/a&gt;, I was able to create the &lt;code&gt;zulip-deployment.yaml&lt;/code&gt; file &lt;a href="https://github.com/rustysys-dev/zulip-podman-play/blob/master/zulip-deployment.yaml"&gt;here&lt;/a&gt; to deploy Zulip. &lt;/p&gt;

&lt;h2&gt;
  
  
  Presumptions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You have an email server supporting TLS and user login.&lt;/li&gt;
&lt;li&gt;You have a GitLab account / Server&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Defaults are fairly secure but for a production environment there are still some things that require tightening.  With that warning out of the way to get &lt;code&gt;zulip-deployment.yaml&lt;/code&gt; up and running the following substitutions are required.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Substitution Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;__POSTGRE_SECURE_PASSWORD&lt;/td&gt;
&lt;td&gt;The password for the integrated postgresql database&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;__MEMCACHED_SECURE_PASSWORD&lt;/td&gt;
&lt;td&gt;The password for the integrated memcached cache&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;__RABBITMQ_SECURE_PASSWORD&lt;/td&gt;
&lt;td&gt;The password for the integrated rabbitmq server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;__REDIS_SECURE_PASSWORD&lt;/td&gt;
&lt;td&gt;The password for the integrated redis server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;__EXTERNAL_HOST_URL&lt;/td&gt;
&lt;td&gt;Zulip externally accessible URL e.g. message.myproject_zulip.com, Can also be set to IP or localhost, and port may be included as desired.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;__ZULIP_SECRET&lt;/td&gt;
&lt;td&gt;random string of characters (used internally) preferably 50 characters long.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;__EMAIL_SERVER_URL&lt;/td&gt;
&lt;td&gt;URL of your email server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;__EMAIL_USER_NAME&lt;/td&gt;
&lt;td&gt;User for authenticating your email server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;__EMAIL_USER_PASSWORD&lt;/td&gt;
&lt;td&gt;Password for above username&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;__GITLAB_URL&lt;/td&gt;
&lt;td&gt;Url of your GitLab instance, or of Gitlab.com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;__GITLAB_APPLICATION_KEY&lt;/td&gt;
&lt;td&gt;Application key generated as described &lt;a href="https://github.com/zulip/zulip/blob/master/zproject/prod_settings_template.py#L154"&gt;here&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;__GITLAB_APPLICATION_SECRET&lt;/td&gt;
&lt;td&gt;Application secret generated as described &lt;a href="https://github.com/zulip/zulip/blob/master/zproject/prod_settings_template.py#L154"&gt;here&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;__ADMIN_ERROR_EMAIL&lt;/td&gt;
&lt;td&gt;Email at which to recieve errors from Zulip&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Deploy
&lt;/h2&gt;

&lt;p&gt;Deployment should be as easy as running the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;podman play kube zulip-deployment.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[rustysysdev@localhost zulip-podman-play]$ podman play kube zulip-deployment.yaml 
Pod:
4c475bb55f6f05828d5cb7efe499b8e84722138f16df263320e541722003fe9b
Containers:
bd8762327b8ab970d6a0c7bc8e6f0ff9ea217751e42225ad207d21e82ae834cc
5567fccbadf943a744264deec4a1b2dfd53ec8e49239660ffaf0a2b0008ba8ee
d503c0b9944428a1849e400315ffdff49b2249de9340387e30e089c20f0a9d58
c06c4ea471de0cc72388fdbf69d6ebbceaddcb4535303a3e293cd6e21afe960f
39cdccdcb981802c3f7e6a1168d590452502aa7097857f8136b18ea5b96079d0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Verify the deployment is complete.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;podman logs zulip-pod-0-zulip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
2020-09-03 07:05:21,303 INFO success: zulip_events_embed_links entered RUNNING state, process has stayed up for &amp;gt; than 1 seconds (startsecs)
2020-09-03 07:05:21,303 INFO success: zulip_events_missedmessage_mobile_notifications entered RUNNING state, process has stayed up for &amp;gt; than 1 seconds (startsecs)
2020-09-03 07:05:21,303 INFO success: zulip_events_error_reports entered RUNNING state, process has stayed up for &amp;gt; than 1 seconds (startsecs)
2020-09-03 07:05:21,304 INFO success: zulip_events_digest_emails entered RUNNING state, process has stayed up for &amp;gt; than 1 seconds (startsecs)
2020-09-03 07:05:21,304 INFO success: zulip_events_email_senders entered RUNNING state, process has stayed up for &amp;gt; than 1 seconds (startsecs)
2020-09-03 07:05:21,305 INFO success: zulip_deliver_scheduled_messages entered RUNNING state, process has stayed up for &amp;gt; than 1 seconds (startsec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Post deploy setup
&lt;/h2&gt;

&lt;p&gt;After deploying the Zulip server and before using it, you will need to create a new organization.  This can be accomplished using the following commands.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;exec into your container.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;podman &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-ti&lt;/span&gt; zulip-pod-0-zulip bash
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;output:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[rustysysdev@localhost zulip-podman-play]$ podman exec -ti zulip-pod-0-zulip bash
root@zulip-pod-0:/#
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;run the following commands to get a realm creation link.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;su zulip &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /home/zulip/
&lt;span class="si"&gt;$(&lt;/span&gt;find ./ &lt;span class="nt"&gt;-name&lt;/span&gt; manage.py&lt;span class="si"&gt;)&lt;/span&gt; generate_realm_creation_link
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;output:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;root@zulip-pod-0:/# su zulip &amp;amp;&amp;amp; cd /home/zulip/
zulip@zulip-pod-0:~$ $(find ./ -name manage.py) generate_realm_creation_link
Please visit the following secure single-use link to register your 
new Zulip organization:

    https://localhost.localdomain:8443/new/4t1f3r0qet4eu0z0phyork8a

&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the resultant link in your browser and follow the steps to setup your administrator account and organization.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b6_rDnV2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wbdwias2reu5lxmb0tai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b6_rDnV2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wbdwias2reu5lxmb0tai.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Creating the zulip server is easy, once finished you can invite users, who can then login using GitLab OAuth!&lt;/p&gt;

&lt;p&gt;If you have any questions do not hesitate to ask!&lt;/p&gt;

</description>
      <category>podman</category>
      <category>zulip</category>
      <category>fedora</category>
      <category>kompose</category>
    </item>
    <item>
      <title>Keep DDD in mind when designing systems (ver1)</title>
      <dc:creator>Scott</dc:creator>
      <pubDate>Sat, 09 May 2020 02:43:38 +0000</pubDate>
      <link>https://forem.com/rusty_sys_dev/keep-ddd-in-mind-when-designing-systems-ver1-1f16</link>
      <guid>https://forem.com/rusty_sys_dev/keep-ddd-in-mind-when-designing-systems-ver1-1f16</guid>
      <description>&lt;p&gt;I created and will keep updating this mind map as I learn more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1IiwIvis--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yxnn52n1gvayws1tuk2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1IiwIvis--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yxnn52n1gvayws1tuk2s.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please let me know in the comments if there are any relations that are incorrect or missing.&lt;/p&gt;

</description>
      <category>ddd</category>
      <category>model</category>
      <category>pm</category>
    </item>
    <item>
      <title>Switching to KeePass and Syncthing for password management </title>
      <dc:creator>Scott</dc:creator>
      <pubDate>Sun, 12 Apr 2020 11:55:15 +0000</pubDate>
      <link>https://forem.com/rusty_sys_dev/switching-to-keepass-and-syncthing-for-password-management-1klh</link>
      <guid>https://forem.com/rusty_sys_dev/switching-to-keepass-and-syncthing-for-password-management-1klh</guid>
      <description>&lt;p&gt;I have wanted to become more secure with how I have handled my password management for a while now.  Before now, I had been using Firefox Lockwise, which is an amazing free service, by a similarly amazing company dedicated to OSS...  That being said, I wanted a solution that I owned, where my passwords are only ever stored on my devices.  &lt;/p&gt;

&lt;p&gt;When it comes to password security and open source.  KeePass tends to be the name you hear, and so I decided on that.  Using KeePass means that I own the db.  It also means that I had to find a way of syncing that db between devices...&lt;/p&gt;

&lt;h2&gt;
  
  
  My requirements:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Wholly self owned solution to sync my KeePass db file between multiple machines&lt;/li&gt;
&lt;li&gt;Sync/Recieve from anywhere&lt;/li&gt;
&lt;li&gt;Little to no maintenance&lt;/li&gt;
&lt;li&gt;Secure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Research/Thought Process:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A quick online search recommends using a service like Dropbox, or Google Drive.

&lt;ul&gt;
&lt;li&gt;I dismissed this, because it was a centralized service out of my control. If I was ok with that I might as well have stayed with Firefox Lockwise.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;I thought about a cron based rsync solution...

&lt;ul&gt;
&lt;li&gt;I dismissed this pretty quickly as there were too many logistical dependencies, and I couldn't find a way to make it work with a locked Android device.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;I considered setting up my own NextCloud (or similar) service...

&lt;ul&gt;
&lt;li&gt;I dismissed this because it was too much work from a security/maintenance standpoint, and would cost money to deploy&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Decided on Syncthing!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Syncthing
&lt;/h2&gt;

&lt;p&gt;I found Syncthing while searching for Nextcloud/alternatives and initially dismissed it, but came back to it after dissatisfaction with NextCloud/alternatives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syncthing in a nutshell
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Encrypts all traffic by default&lt;/li&gt;
&lt;li&gt;Monitors folders registered to Syncthing&lt;/li&gt;
&lt;li&gt;Notifies relay when changes occur&lt;/li&gt;
&lt;li&gt;Registers remote devices by device-id&lt;/li&gt;
&lt;li&gt;Assigns devices to folders&lt;/li&gt;
&lt;li&gt;Detects changes via relay&lt;/li&gt;
&lt;li&gt;Connects directly to devices via a relay&lt;/li&gt;
&lt;li&gt;Uploads or downloads directly to remote devices&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Installation on Fedora
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install &lt;/span&gt;syncthing
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Start the Fedora Instance
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="nb"&gt;enable &lt;/span&gt;syncthing
systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; start syncthing
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Installation Android
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Install via the Google Play Store, link available &lt;a href="https://syncthing.net/downloads/"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Get your Device IDs
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Android
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Open the app&lt;/li&gt;
&lt;li&gt;Click on the &lt;code&gt;≡&lt;/code&gt; and click &lt;code&gt;Show Device ID&lt;/code&gt; record the ID&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Fedora
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;localhost:8384&lt;/code&gt; in your browser&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Actions&lt;/code&gt;, then &lt;code&gt;Show ID&lt;/code&gt;, record the ID&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Configure Devices
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Android
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;From the main screen click on the &lt;code&gt;Devices&lt;/code&gt; tab, then on the &lt;code&gt;＋&lt;/code&gt; in the top right&lt;/li&gt;
&lt;li&gt;Input the Fedora system's &lt;code&gt;Device ID&lt;/code&gt; and add a &lt;code&gt;Name&lt;/code&gt;, tap &lt;code&gt;✔&lt;/code&gt; to save&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Fedora
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Click the &lt;code&gt;Add Remote Device&lt;/code&gt; button under the &lt;code&gt;Remote Devices&lt;/code&gt; heading.&lt;/li&gt;
&lt;li&gt;Input the Android &lt;code&gt;Device ID&lt;/code&gt; and add a &lt;code&gt;Name&lt;/code&gt;, then click &lt;code&gt;Save&lt;/code&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Adding Shared Folders
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Android
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;From the main screen click on the &lt;code&gt;Folders&lt;/code&gt; tab, then on the &lt;code&gt;＋&lt;/code&gt; in the top right&lt;/li&gt;
&lt;li&gt;Fill in the 🏷️ &lt;code&gt;Folder Label&lt;/code&gt;, 🔑 &lt;code&gt;Folder ID&lt;/code&gt;, and 📁 &lt;code&gt;Directory&lt;/code&gt;.  Remember your 🔑 &lt;code&gt;Folder ID&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Tap to enable the slider for your Fedora device name.&lt;/li&gt;
&lt;li&gt;Tap &lt;code&gt;✔&lt;/code&gt; to save&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Fedora
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Under the &lt;code&gt;Folders&lt;/code&gt; section, select &lt;code&gt;Add Folder&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Fill in &lt;code&gt;Folder Label&lt;/code&gt;, &lt;code&gt;Folder ID&lt;/code&gt;, and &lt;code&gt;Folder Path&lt;/code&gt;, where &lt;code&gt;Folder ID&lt;/code&gt; is the same as the 🔑 &lt;code&gt;Folder ID&lt;/code&gt; on Android.&lt;/li&gt;
&lt;li&gt;Click the &lt;code&gt;Sharing&lt;/code&gt; tab, and add a &lt;code&gt;✔&lt;/code&gt; to your Android device name.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Save&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once both devices configurations have been saved, I placed my kdb file in the &lt;code&gt;Folder Path&lt;/code&gt; on my Fedora installation, and watched it synced to the opposite device within short order.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notable Issues
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;.stfolder&lt;/code&gt; directory on my phone tends to be be deleted on restart causing an error.  Creating an empty &lt;code&gt;.stfolder&lt;/code&gt; in your sync directory seems to fix this.&lt;/li&gt;
&lt;li&gt;Modifying the same file from two different devices at the same time will result in conflicts.  Conflicts result in a loss of the oldest of the two changes. ( the conflicting version still exists but is not automatically merged )&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By switching to Keepass, and Syncthing I am able to securely sync my password database between my devices without ever storing it on a third-party server.  If I could just figure out the issue with the &lt;code&gt;.stfolder&lt;/code&gt; on android mysteriously disappearing I would be completely satisfied.&lt;/p&gt;

&lt;p&gt;Please feel free to leave any questions or concerns in the comments!&lt;/p&gt;

</description>
      <category>syncthing</category>
      <category>keepass</category>
      <category>passwords</category>
    </item>
    <item>
      <title>Using Cap'n Proto on Rust</title>
      <dc:creator>Scott</dc:creator>
      <pubDate>Mon, 23 Mar 2020 10:16:20 +0000</pubDate>
      <link>https://forem.com/rusty_sys_dev/using-cap-nproto-on-rust-53hj</link>
      <guid>https://forem.com/rusty_sys_dev/using-cap-nproto-on-rust-53hj</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Recently at work, I have been working a lot with gRPC and Golang, and I felt enjoy using gRPC as an application interface.  It is simple to implement and works well..  Anyway about 2 weeks ago while reading about various technologies related to my work.  I came across Cap'n Proto and was interested to learn that it was created by one of the primary authors of Protocol Buffers v2.  Since I was already using Protocol Buffers with gRPC at work, I decided to try out Cap'n Proto + Cap'n Proto RPC with Rust.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Cap'n Proto?
&lt;/h1&gt;

&lt;p&gt;Cap'n Proto is a incredibly fast data serialization format.  If you want to know more about Cap'n Proto in general, &lt;a href="https://capnproto.org/"&gt;please visit their website!&lt;/a&gt;.  If you are familiar with Protocol buffers, then a majority of the following concepts will be familiar to you.&lt;/p&gt;

&lt;h1&gt;
  
  
  My Goal
&lt;/h1&gt;

&lt;p&gt;My goal here is to create a simple API that accepts a list of parameters, and a source directory then return a job ID, or accepts a job ID and returns the results.  See the following diagrams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZgunMPQB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u8efc67a44hhbbczjzhj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZgunMPQB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u8efc67a44hhbbczjzhj.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--byMnOrf9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mctwnljk3mctoorgmcyn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--byMnOrf9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mctwnljk3mctoorgmcyn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: The example built in this article will be split into the following files. &lt;code&gt;main.rs&lt;/code&gt;, &lt;code&gt;server.rs&lt;/code&gt;, &lt;code&gt;client.rs&lt;/code&gt;, &lt;code&gt;build.rs&lt;/code&gt;, &lt;code&gt;service.capnp&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Cap'n Proto Interface Definition
&lt;/h1&gt;

&lt;p&gt;With a goal in mind, I set out and defined my &lt;code&gt;service.capnp&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@0xeb1bbbd418f18514;

interface Job {
    register @0 Request -&amp;gt; RegistryItem;
    getResult @1 RegistryItem -&amp;gt; Result;
    struct Request {
        parms @0 :List(Text);
        source @1 :Text;
    }
    struct Result {
        union {
            link @0 :Text;
            error @1 :Text;
        }
    }
    struct RegistryItem {
        # Single Job Identity
        id @0 :Text;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE: You can write your methods in a more verbose format, however this is not recommended as you will have to &lt;code&gt;pry!&lt;/code&gt; multiple times in your server implementation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Right away you can see we have defined a &lt;code&gt;Job&lt;/code&gt; interface with two methods &lt;code&gt;register&lt;/code&gt; and &lt;code&gt;getResults&lt;/code&gt;, and three data structures &lt;code&gt;Request&lt;/code&gt;, &lt;code&gt;Result&lt;/code&gt;, and &lt;code&gt;RegistryItem&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To actually use the defined RPC interface, we will need to generate Rust code from the above &lt;code&gt;service.capnp&lt;/code&gt; file.&lt;/p&gt;

&lt;h1&gt;
  
  
  Generate the Code
&lt;/h1&gt;

&lt;p&gt;In order to generate the code, you will need to create a &lt;code&gt;build.rs&lt;/code&gt; file as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;capnpc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;capnpc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;CompilerCommand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"service.capnp"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will generate the RPC code from the &lt;code&gt;service.capnp&lt;/code&gt; file defined in the previous section, it roughly translates into the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;interface Job {...}&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates &lt;code&gt;pub mod job&lt;/code&gt; for client/server communications&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;code&gt;register @0 Request -&amp;gt; RegistryItem&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adds &lt;code&gt;register&lt;/code&gt; method to &lt;code&gt;job::Server&lt;/code&gt; trait&lt;/li&gt;
&lt;li&gt;Implements &lt;code&gt;register_request&lt;/code&gt; for the &lt;code&gt;job::Client&lt;/code&gt; struct to generating a Cap'nProto Request object for the register method.&lt;/li&gt;
&lt;li&gt;Creates type &lt;code&gt;job::RegisterParams&lt;/code&gt; which controls access to incoming data on the server side.&lt;/li&gt;
&lt;li&gt;creates type &lt;code&gt;job::RegisterResults&lt;/code&gt; which controls access to outgoing data on the server side.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;code&gt;getResult @1 RegistryItem -&amp;gt; Result&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adds &lt;code&gt;get_result&lt;/code&gt; method to &lt;code&gt;job::Server&lt;/code&gt; trait&lt;/li&gt;
&lt;li&gt;Implements &lt;code&gt;get_result_request&lt;/code&gt; for the &lt;code&gt;job::Client&lt;/code&gt; struct to generating a Cap'nProto Request object for the get_result method.&lt;/li&gt;
&lt;li&gt;Creates type &lt;code&gt;job::GetResultParams&lt;/code&gt; which controls access to incoming data on the server side.&lt;/li&gt;
&lt;li&gt;creates type &lt;code&gt;job::GetResultResults&lt;/code&gt; which controls access to outgoing data on the server side.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;code&gt;struct Request {...}&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a &lt;code&gt;pub mod request&lt;/code&gt; (job::request) submodule&lt;/li&gt;
&lt;li&gt;Creates type &lt;code&gt;job::request::Reader&lt;/code&gt; containing getters for each capnp parameter&lt;/li&gt;
&lt;li&gt;Creates type &lt;code&gt;job::request::Builder&lt;/code&gt; containing setters for each capnp parameter&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;code&gt;struct Result {...}&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a &lt;code&gt;pub mod result&lt;/code&gt; (job::result) submodule&lt;/li&gt;
&lt;li&gt;Creates type &lt;code&gt;job::result::Reader&lt;/code&gt; containing getters for each capnp parameter&lt;/li&gt;
&lt;li&gt;Creates type &lt;code&gt;job::result::Builder&lt;/code&gt; containing setters for each capnp parameter&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;code&gt;struct RegistryItem {...}&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a &lt;code&gt;pub mod registry_item&lt;/code&gt; (job::registry_item) submodule&lt;/li&gt;
&lt;li&gt;Creates type &lt;code&gt;job::registry_item::Reader&lt;/code&gt; containing getters for each capnp parameter&lt;/li&gt;
&lt;li&gt;Creates type &lt;code&gt;job::registry_item::Builder&lt;/code&gt; containing setters for each capnp parameter&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Importing the Generated Code
&lt;/h1&gt;

&lt;p&gt;To use the code we just generated, we must import into our source as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;service_capnp&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To build our service we still need to create an RPC client and server.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating the Server
&lt;/h1&gt;

&lt;p&gt;The requires implementing 2 things.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the local implementation of your interface&lt;/li&gt;
&lt;li&gt;Create your interface methods&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implement the local interface
&lt;/h3&gt;

&lt;p&gt;First things first, we need to create a local &lt;code&gt;struct&lt;/code&gt; upon which we can implement our interface methods.  This is easy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once this is finished we get to the interesting part.  The implementation of our methods.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Implement the methods
&lt;/h3&gt;

&lt;p&gt;Cap'nProto methods will always follow the below signature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;imported_rpc_interface&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;local_struct&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;rpc_method_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;imported_rpc_interface&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;sentence_case_rpc_method_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;imported_rpc_interface&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;sentence_case_rpc_method_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;capnp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Do Something&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;or in our case, the following..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Job&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RegisterParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RegisterResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;capnp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Do Something&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;GetResultParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;GetResultResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;capnp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Do Something&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For the purposes of this article the business logic for the methods is scaled back to printing out received values, and sending back static responses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Job&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RegisterParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RegisterResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;capnp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing Register"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c"&gt;// get a reader object for the sent request&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;request_reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;pry!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="c"&gt;// get the value for the sent parms parameter&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;parms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request_reader&lt;/span&gt;&lt;span class="nf"&gt;.get_parms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c"&gt;// get the value for the sent source parameter&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request_reader&lt;/span&gt;&lt;span class="nf"&gt;.get_source&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;parms&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c"&gt;// print each parms value&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Parameter: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c"&gt;// print the source value&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DataSource: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c"&gt;// set return value for id&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.set_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"01E3S4Q9SN3VHVXB2KCAGD9P62"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nn"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;GetResultParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;GetResultResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;capnp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing Get Result"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c"&gt;// get a reader object for the sent request&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;request_reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;pry!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="c"&gt;// get the send ID&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request_reader&lt;/span&gt;&lt;span class="nf"&gt;.get_id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c"&gt;// print the sent ID&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ID: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c"&gt;// set return value for link&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.set_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://link.to.your/output.csv"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nn"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE: &lt;code&gt;pry!&lt;/code&gt; is a macro from the &lt;code&gt;capnp_rpc&lt;/code&gt; crate that acts like try!(), but for functions that return a Promise rather than a Result.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We wrap it all together and build our &lt;code&gt;server::main()&lt;/code&gt; with the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;capnp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;capability&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;capnp_rpc&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;pry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RpcSystem&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;capnp_rpc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;twoparty&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;VatNetwork&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;capnp_rpc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;rpc_twoparty_capnp&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Side&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;async_std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;net&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;TcpListener&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;AsyncReadExt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FutureExt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StreamExt&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;task&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LocalSpawn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;service_capnp&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Job&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RegisterParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RegisterResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;capnp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing Register"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c"&gt;// get a reader object for the sent request&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;request_reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;pry!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="c"&gt;// get the value for the sent parms parameter&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;parms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request_reader&lt;/span&gt;&lt;span class="nf"&gt;.get_parms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c"&gt;// get the value for the sent source parameter&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request_reader&lt;/span&gt;&lt;span class="nf"&gt;.get_source&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;parms&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c"&gt;// print each parms value&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Parameter: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c"&gt;// print the source value&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DataSource: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c"&gt;// set return value for id&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.set_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"01E3S4Q9SN3VHVXB2KCAGD9P62"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nn"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;GetResultParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;GetResultResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;capnp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing Get Result"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c"&gt;// get a reader object for the sent request&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;request_reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;pry!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="c"&gt;// get the send ID&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request_reader&lt;/span&gt;&lt;span class="nf"&gt;.get_id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c"&gt;// print the sent ID&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ID: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c"&gt;// set return value for link&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.set_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://link.to.your/output.csv"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nn"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg_addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;net&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ToSocketAddrs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c"&gt;// parse input address..&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arg_addr&lt;/span&gt;&lt;span class="nf"&gt;.to_socket_addrs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid Address"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;LocalPool&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;spawner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="nf"&gt;.spawner&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c"&gt;// Start Server&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="nf"&gt;.run_until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Initialize TCP listener @ addr&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;TcpListener&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c"&gt;// Initialize local interface defined above&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;job_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ToClient&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.into_client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;capnp_rpc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c"&gt;// Initialize and execute async handler&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;incoming&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="nf"&gt;.incoming&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;handle_incoming&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;incoming&lt;/span&gt;&lt;span class="nf"&gt;.next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket_result&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Accepted connection from {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="nf"&gt;.peer_addr&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
                &lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="nf"&gt;.set_nodelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="nf"&gt;.split&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;network&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;VatNetwork&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Side&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;rpc_system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;RpcSystem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job_client&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.client&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
                &lt;span class="n"&gt;spawner&lt;/span&gt;&lt;span class="nf"&gt;.spawn_local_obj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;pin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rpc_system&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;()))&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nn"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="n"&gt;handle_incoming&lt;/span&gt;&lt;span class="py"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Creating the Client
&lt;/h1&gt;

&lt;p&gt;Creating the client only requires creating the main loop for sending our requests as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;capnp_rpc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RpcSystem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;capnp_rpc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;twoparty&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;VatNetwork&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;capnp_rpc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;rpc_twoparty_capnp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Side&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;async_std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;net&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TcpStream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;AsyncReadExt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FutureExt&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;task&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LocalSpawn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;service_capnp&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg_addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;net&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ToSocketAddrs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c"&gt;// Resolve input server address&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arg_addr&lt;/span&gt;&lt;span class="nf"&gt;.to_socket_addrs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid Address"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c"&gt;// Create a pool for executing async requests&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;LocalPool&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;spawner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="nf"&gt;.spawner&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c"&gt;// Execute the client&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="nf"&gt;.run_until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Create RPC connection to the server&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;TcpStream&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="nf"&gt;.set_nodelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="nf"&gt;.split&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;network&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nn"&gt;VatNetwork&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Side&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;rpc_system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;RpcSystem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c"&gt;// Setup the client interface&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;job_client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rpc_system&lt;/span&gt;&lt;span class="nf"&gt;.bootstrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Side&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;spawner&lt;/span&gt;&lt;span class="nf"&gt;.spawn_local_obj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;pin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rpc_system&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|()))&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sending Register Job Request..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c"&gt;// Create a register request object&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;job_client&lt;/span&gt;&lt;span class="nf"&gt;.register_request&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c"&gt;// Set parms - list parameters require initialization&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;parms_setter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.init_parms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;parms_setter&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"dark"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;parms_setter&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c"&gt;// Set source - strings do not require prior initialization&lt;/span&gt;
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.set_source&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/link/to/the/path"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c"&gt;// Send request, and await response&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.promise.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received JobID: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.get_id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sending Get Result Request..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c"&gt;// Create get_result request object&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;job_client&lt;/span&gt;&lt;span class="nf"&gt;.get_result_request&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c"&gt;// Set JobID&lt;/span&gt;
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.set_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"01E3S4Q9SN3VHVXB2KCAGD9P62"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c"&gt;// Send request, and await response&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.promise.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c"&gt;// The result is of the union type, so we must determine which type it is&lt;/span&gt;
            &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="nf"&gt;.which&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;result&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                   &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received Link: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="nn"&gt;job&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;result&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
                   &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received Error: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Creating The main()
&lt;/h1&gt;

&lt;p&gt;For the purposes of this article, both the client and server will be part of the same binary.  As such, we have a dedicated &lt;code&gt;main.rs&lt;/code&gt; which looks as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;// Include capnp generated code&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;source_capnp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;include!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;concat!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;env!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OUT_DIR"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"/source_capnp.rs"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"client"&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
            &lt;span class="s"&gt;"server"&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;server&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
            &lt;span class="mi"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"usage: {} [client | server] ADDRESS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Running the server
&lt;/h1&gt;

&lt;p&gt;We will run our server on &lt;code&gt;localhost:2020&lt;/code&gt;, and should receive the following output (pre-client)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;16:46:22 🖎 export-rust master* ± cargo run server localhost:2020
   Compiling export-rust v0.1.0 (/home/procyclinsur/test/export-rust)
    Finished dev [unoptimized + debuginfo] target(s) in 2.90s
     Running `target/debug/export-rust server 'localhost:2020'`

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Running the client
&lt;/h1&gt;

&lt;p&gt;Similarly the client will run against the server running at &lt;code&gt;localhost:2020&lt;/code&gt;.  When the client is run however there should be output in both the server terminal and the client terminal as follows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;16:50:53 🖎 export-rust master* ± cargo run client localhost:2020
    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/export-rust client 'localhost:2020'`
Sending Register Job Request...
Received JobID: 01E3S4Q9SN3VHVXB2KCAGD9P62
Sending Get Result Request...
https://link.to.your/output.csv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Server
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;16:46:22 🖎 export-rust master* ± cargo run server localhost:2020
   Compiling export-rust v0.1.0 (/home/procyclinsur/test/export-rust)
    Finished dev [unoptimized + debuginfo] target(s) in 2.90s
     Running `target/debug/export-rust server 'localhost:2020'`
Accepted connection from Ok(V6([::1]:36374))
Processing Register
Parameter: dark
Parameter: world
DataSource: /link/to/the/path
Processing Get Result
ID: 01E3S4Q9SN3VHVXB2KCAGD9P62
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, we are able to send and receive data via our API powered by Cap'n Proto RPC.  If you love it, hate it, have any questions, or suggestions for improvement please let me know! &lt;/p&gt;

</description>
      <category>rust</category>
      <category>capnp</category>
    </item>
    <item>
      <title>Golang Dynamic Logging for Microservices</title>
      <dc:creator>Scott</dc:creator>
      <pubDate>Fri, 23 Aug 2019 10:51:03 +0000</pubDate>
      <link>https://forem.com/rusty_sys_dev/golang-dynamic-logging-3p7k</link>
      <guid>https://forem.com/rusty_sys_dev/golang-dynamic-logging-3p7k</guid>
      <description>&lt;p&gt;Dynamic logging is something I believe should be implemented in any micro-service environment.  I suppose I should start with I mean by dynamic logging..  Simply put the following point should be covered.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintainer should be able to change the log level of the application mid-execution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sample Application
&lt;/h2&gt;

&lt;p&gt;Using the &lt;code&gt;go.uber.org/zap&lt;/code&gt; library &lt;a href="https://godoc.org/go.uber.org/zap#LevelEnablerFunc" rel="noopener noreferrer"&gt;LevelEnablerFunc&lt;/a&gt; you should be able to implement the interface using any protocol you want? (Haven't tested this).. That being said, for my sample application I will be using an HTTP interface and so I will use the zap built-in &lt;a href="https://godoc.org/go.uber.org/zap#AtomicLevel.ServeHTTP" rel="noopener noreferrer"&gt;ServeHttp&lt;/a&gt; method.&lt;/p&gt;

&lt;p&gt;First we need to define our logger and build and build an http router to accept log level changes.  This is completed by utilizing the above mentioned &lt;code&gt;ServeHttp&lt;/code&gt; function built into the &lt;code&gt;zap.AtomicLevel&lt;/code&gt; object. &lt;/p&gt;

&lt;h4&gt;
  
  
  Setup Logger
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;zap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewProductionEncoderConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;encoder&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;zapcore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewJSONEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;atom&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;zap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewAtomicLevel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;logr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;zap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zapcore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zapcore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Dynamic log level interface
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;mux&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewServeMux&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/log_level"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":1065"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am running a simple loop that repeats various logging messages to allow us to see the expected output.  After building and running the application we can interact with it via curl.&lt;/p&gt;

&lt;h4&gt;
  
  
  Change logging levels
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; PUT &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"level":"debug"}'&lt;/span&gt; localhost:1065/log_level
curl &lt;span class="nt"&gt;-X&lt;/span&gt; PUT &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"level":"info"}'&lt;/span&gt; localhost:1065/log_level
curl &lt;span class="nt"&gt;-X&lt;/span&gt; PUT &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"level":"info"}'&lt;/span&gt; localhost:1065/  &lt;span class="c"&gt;# EXPECTED 404&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET localhost:1065/log_level
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE: GIF seems to be broken again... but clicking the link should show you... ill fix it later 😂&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FmSc5ET9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FmSc5ET9.gif" alt="DEMO"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample Application Code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;

    &lt;span class="s"&gt;"go.uber.org/zap"&lt;/span&gt;
    &lt;span class="s"&gt;"go.uber.org/zap/zapcore"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;undo&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;initLogger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;undo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;zap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test_logs"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;zap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test_logs_debug"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;initLogger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;zap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewProductionEncoderConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EncodeTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enc&lt;/span&gt; &lt;span class="n"&gt;zapcore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrimitiveArrayEncoder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;nanos&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnixNano&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;millis&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;nanos&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;enc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppendInt64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;millis&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;encoder&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;zapcore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewJSONEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;atom&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;zap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewAtomicLevel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;logr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;zap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zapcore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zapcore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;mux&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewServeMux&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/log_level"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":1065"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;zap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReplaceGlobals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>go</category>
      <category>zap</category>
    </item>
  </channel>
</rss>
