forked from cerner/cerner.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
2059 lines (1538 loc) · 189 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Engineering Health]]></title>
<link href="http://engineering.cerner.com/atom.xml" rel="self"/>
<link href="http://engineering.cerner.com/"/>
<updated>2019-01-08T10:10:38-06:00</updated>
<id>http://engineering.cerner.com/</id>
<author>
<name><![CDATA[Cerner]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[2^5 Coding Competition 2018]]></title>
<link href="http://engineering.cerner.com/blog/2-to-the-5th-coding-competition-2018/"/>
<updated>2018-12-14T00:00:00-06:00</updated>
<id>http://engineering.cerner.com/blog/2-to-the-5th-coding-competition-2018</id>
<content type="html"><![CDATA[<p>At Cerner, associates are always encouraged to develop tools and methods to improve their productivity. With this year’s theme being “Engineering Productivity,” Cerner’s fourth annual <a href="https://engineering.cerner.com/blog/2-to-the-5th-coding-competition-2017/">2<sup>5</sup> Coding Competition</a> provided associates another opportunity to dive into this subject and get involved in <a href="https://engineering.cerner.com/culture/">Cerner’s development culture</a>.</p>
<p>As usual, this year’s 2<sup>5</sup> Coding Competition was kicked off alongside Programmer’s Day festivities on September 13th. The competition lasts 32 days, and associates are encouraged to submit code every day. During this year’s competition, over 200 code snippet submissions in a total of 59 different languages marked another successful run of the competition. This year the participants were judged based on the following categories:</p>
<ul>
<li><strong>Best Representation</strong>: What captures the concept of “engineering productivity” the best?</li>
<li><strong>Most Obfuscated</strong>: Which code snippet was the most difficult to understand?</li>
<li><strong>Greatest Variety in Languages</strong>: Which repository contained the most variety in programming languages across submissions?</li>
</ul>
<p>Even though each submission had to be 32 lines of code or less, it didn’t stop the participants from brainstorming and executing great ideas ranging from <a href="https://jenkins.io/doc/book/pipeline/">Jenkins Pipelines</a>, creating shell commands, and automating tasks for the tools we use every day. The many entries received exemplified how easy it is to increase productivity in an engineer’s daily life with just a few lines of code.</p>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-12-14-2-to-the-5th-coding-competition-2018/2-to-the-5th-2018-1.jpeg"></p>
<h2>My Experience</h2>
<p>As a participant, my biggest takeaway from this event was the learning experience it provided me. I was able to not only expand my skill set by working on the projects that I was passionate about, but also learn about different technologies. I found myself often inspired by reading through other participants’ submissions. The restriction of 32 lines of code drove all of us as participants to write clean and concise solutions. It also made learning from each other’s code snippets fun and straightforward. This event also helped me understand how easy it is to find new project ideas. Some ways participants could easily get inspired include discovering a new library heard about in a <a href="https://www.youtube.com/user/CernerEng">Tech Talk</a>, a cool new framework that your team started using, or even a complaint about how difficult it is to use a tool. All these things can inspire and drive participants to develop projects that are going to enhance their own personal knowledge about the new technologies or even help improve other people’s work efficiency.</p>
<p>By combining the newly learned technologies and the inspirations I found, I was able to develop tools that make my daily work easier. By learning how to develop chrome extensions, I automated some steps in our timesheet submission system including automatically adding holiday timecode. Furthermore, by researching the ins and outs of shell scripting, I simplified various tasks in command line that would otherwise be complicated to execute. During the competition, I benefited from code snippets submitted by other 2<sup>5</sup> participants such as a bat file that enables users to open the GitHub repository URL from the local git repo. 2<sup>5</sup> provides a platform for anyone who wants to learn and share ideas, and it doesn’t require big time commitments. I believe it is a perfect opportunity for our engineers to get involved and innovate.</p>
<h3>The Winners</h3>
<h4>Best Representation: <a href="https://github.com/saqiurila">Jenny Saqiurila</a></h4>
<p>The judges agreed that Jenny’s collection of submissions were most closely aligned to the 2018 2<sup>5</sup> theme of “Engineering Productivity.” Specifically, the judges noted the high usability of her automated timesheet submission tool.</p>
<h4>Most Obfuscated: <a href="https://github.com/mithuns">Mithun Singh</a></h4>
<p>Mithun captured the award for the Most Obfuscated submission using an esoteric programming language that was comprised of symbols that outputted “Hello World.” None of our judges were familiar with this language and found his submission impressive, yet confusing.</p>
<h4>Greatest Variety in Languages: <a href="https://github.com/susmitha-anandarao">Susmitha Anandarao</a></h4>
<p>As the 2<sup>5</sup> competition runs for 32 days, the maximum number of languages that could be used by a participant is 32 languages. Susmita was named this category winner because she submitted all 32 days worth of code and used 32 different languages.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[ShipIt XIII]]></title>
<link href="http://engineering.cerner.com/blog/shipit-xiii/"/>
<updated>2018-11-16T00:00:00-06:00</updated>
<id>http://engineering.cerner.com/blog/shipit-xiii</id>
<content type="html"><![CDATA[<h2>What does it take to be awarded the ShipIt Day Golden Keyboard?</h2>
<div align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-16-shipit-xiii/shipit-xiii-1.jpg" width="300">
</div>
<p>ShipIt Day XIII concluded last week after an intense 24-hours of brainstorming, building, and presenting. Various projects were completed by Cerner associates across twelve diverse organizations. ShipIt Day XIII’s projects were some of the most technically advanced this competition has ever seen.</p>
<p>Awarding the Golden Keyboard is no easy job for our judges. Back in 2014, the trophy was created to provide the winning team with a memento that was unique and grew with the competition. Every competition the new winning team adds a trinket to the golden keyboard, so their ShipIt Day victory carries on forever. If you are wondering what it takes to bring home the golden keyboard, look no further than ShipIt Day XIII’s first place team, Dreamy Cloudy People.</p>
<h2>Learn from the Winners!</h2>
<p>Dreamy Cloudy People is a team of five individuals: Brett Heroux, Murtuza Syed, Niranjan Kumar, Abhijit Rao, and Swati Kode. The team spent the 24-hour hackathon on a real time push notification mechanism for patient chart web application views using the WebSocket API. Traditionally, data retrieval had been on demand, using AJAX and XMLHttpRequest. Previously, clinicians had to refresh their browser to receive updates to clinical data when reviewing a patient’s chart.</p>
<p>With this project, the WebSocket API was leveraged to allow a server to push updates to clients as events were triggered. The web application then updated its views without needing a user to manually refresh the page. They stood up a Java service for web clients to create WebSocket connections and send/receive data. It was also used to broadcast events involving patient data, such as new lab results or orders. The client application uses an existing JavaScript framework, part of Cerner <em>Millennium</em> MPages, to create socket connections and update the state of the application in real time.</p>
<div align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-16-shipit-xiii/shipit-xiii-2.jpg" width="600">
</div>
<p>During their presentation, Dreamy Cloudy People successfully pitched their improvement to the judges. After the presentation, one of our judges mentioned:</p>
<blockquote><p>Improving communication is always impactful in a clinical setting and improving to near real time is a great enhancement!</p></blockquote>
<p>There are several criteria that teams must showcase to prove their project is worthy of the Golden Keyboard:</p>
<ol>
<li>The project is well designed and captured everything that needed to be included.</li>
<li>The project is technically difficult and tested the team’s technical knowledge, often leading to learning a new skill.</li>
<li>The presentation shares the value potential and impact that the improvement/creation has to Cerner, associates, or our stakeholders.</li>
</ol>
<p>Last but not least, a winning ShipIt Day team always makes sure to enjoy the event. One Dreamy Cloudy People team member, Niranjan Kumar, stated his favorite part of ShipIt Day was having “the opportunity to focus on projects not directly related to my primary role” and the “collaboration with peers.” Congrats to our first-place team!</p>
<h2>Additional ShipIt XIII Winners</h2>
<h3>2nd Place: No amount of Pepto can stop this ingestion!</h3>
<p><strong>Team members</strong>: Kevin Dunn, Scott Levander, Jeff Koehler, Dave Morgan, Rushabh Shah</p>
<div align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-16-shipit-xiii/shipit-xiii-6.jpg" width="600">
</div>
<p>This team designed a MS SQL Server database to track files received from clients into <em><a href="https://www.cerner.com/solutions/population-health-management">HealtheIntent</a></em> and determine the latency since the last file arrived, as well as file size. They also created configuration tables to define expected file latency, acceptable thresholds before triggering an alert, and tables to track the people who want to receive an alert. Feeding off of that data, the team also developed an email alerting service (in C#), <a href="https://www.tableau.com/">Tableau visualization</a> dashboards for internal project investigations, and a Web UI to manage configurations (using PHP/SQL Server).</p>
<h3>3rd Place: Overnight Shippers!</h3>
<p><strong>Team Members</strong>: Varun Kumar Chepuri, Tejaswi Gade, Ed Jalili, Neil Pathare</p>
<div align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-16-shipit-xiii/shipit-xiii-5.jpg" width="600">
</div>
<p>Currently, there are issues that are being reported on <a href="https://www.splunk.com/">Splunk</a> and there is a lot of manual effort to log <a href="https://www.atlassian.com/software/jira">JIRAs</a> for them and then, developers need to track those issues while making any code changes. The JIRA backlog is building up and there is very little to no effort in cleaning up that backlog or working on fixing those issues. Issues logged in Splunk are not being fixed and these errors or defects are not caught early in the lifecycle. These errors or defects are shipped out to clients impacting their workflow. Therefore, Overnight Shippers! created a service bot which uses Splunk to find errors or exceptions and creates an issue in GitHub. This service bot creates a comment on a Pull Request if a Splunk issue exists for the files that are changed. Other capabilities include the capability to configure the bot per Github repository, log <a href="https://help.github.com/articles/about-issues/">GitHub issues</a> periodically, and support various project types.</p>
<h3>People Choice Awards</h3>
<div align="center">
<table>
<tr>
<td align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-16-shipit-xiii/shipit-xiii-4.jpg" width="300">
<sub>Best Project: Centurions</sub>
</td>
<td align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-16-shipit-xiii/shipit-xiii-3.jpg" width="300">
<sub>Best Presentation: Team Rhinos</sub>
</td>
<td align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-16-shipit-xiii/shipit-xiii-5.jpg" width="300">
<sub>Best Team Name: Overnight Shippers!</sub>
</td>
</tr>
</table>
</div>
<p></p>
<p>Time to start preparing for ShipIt Day 2019! Thank you to our talented judges Chuck Schneider, Justin Morrison, and Jim Dwyer for serving as our judges.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Our DevCulture Team: Connecting Communities & Empowering Teams to Invent the Future]]></title>
<link href="http://engineering.cerner.com/blog/devculture-team/"/>
<updated>2018-11-07T00:00:00-06:00</updated>
<id>http://engineering.cerner.com/blog/devculture-team</id>
<content type="html"><![CDATA[<p>The tech industry is constantly evolving; for better or worse, there’s no way around it. Now, more than ever, having a culture that fosters collaboration, empowers associates, and supports innovation is vital to a company’s success in the face of such constant change. However, an effective culture must be grown organically while being supported by senior leadership. At Cerner, we recognize the challenges involved in growing an effective, rewarding, and fun culture.With this in mind, we’ve made intentional strategic investments to overcome them. We’ve taken a unique approach by establishing a team that focuses on growing our culture across dev and ops specifically. Our team is called the DevCulture Team.</p>
<div align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-07-devculture-team/culture-1.jpg" width="450">
</div>
<h4>Our Mission</h4>
<blockquote><p>We exist as a strategic lever to establish Cerner as a destination for top tech talent, helping shift workforce behavior to catalyze the change Cerner needs for the Next.</p></blockquote>
<p>Cerner associates consider themselves privileged to work on challenging problems in an important space, healthcare. In 2010-2011, associates across dev and ops began to realize how much more they could learn from and contribute to the broader tech industry. We started attending conferences and bringing back new insights on the opportunities available when companies focused on culture as a driver for hiring, retaining, and leveling up associates working on software.</p>
<p>This led to establishing <a href="https://engineering.cerner.com/2013/08/devcon">DevCon</a> (our internal Developers Conference) in 2011, sponsoring local tech meetups as well as large scale tech conferences, sharing our work through this Engineering Health blog platform, and establishing the DevCulture Team officially in 2012. Prior to 2012, all efforts were completed by our first team member as extra projects while gaining the justification for a full time position on this new team. Not long after, we shifted our focus from awareness to associate industry engagement, encouraging associates to speak at conferences and to contribute to open source. As the work continued to increase, the DevCulture Team and our Culture Councils (described in more detail below) have grown around the globe as we work to align our values and advance together.</p>
<div align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-07-devculture-team/culture-2.jpg" width="450">
<sub>Currently, we focus on 10,495 associates across Cerner globally which represents a third of the company.</sub>
</div>
<br />
<p>So who do we target and how do we develop our strategies? We focus our programs and work on both sides of the Dev/Ops equation, including user experience and product strategy. We also uniquely report through development executives which gives us the ability to advocate for their perspectives, represent engineering, and align strategies as we partner with other organizations (such as Recruiting, Talent Development, Learning, Finance, etc.) to implement our programs and values.</p>
<p><strong>Culture Councils</strong></p>
<p>In effort to have buy-in, perspectives, and engagement from all sides of the business, we established Culture Councils to help us define our strategic direction. Each year, members are selected from an open application process. These Councils around the globe meet regularly to discuss where we are, where we are going, and where we need to be in order to be successful culturally. From existing programs to identifying cultural gaps, the Councils’ support of our team makes all of our work possible.</p>
<p>Curious about what type of programs we run? We thought you might be. Check out some of our favorites!</p>
<p><strong>DevCon</strong></p>
<p>Embodying our values, DevCon is the foundation of our development culture. Providing opportunities to learn, share, network, and grow, DevCon is an internal conference and now takes place in three locations each year: Kansas City, Philadelphia, and Bangalore.</p>
<p>From industry leader keynote speakers to hours of associate led sessions and a geek trivia night, associates look forward to DevCon all year round. Watch <a href="https://www.youtube.com/watch?v=8FR0tO1-1rk">DevCon highlight videos</a>, <a href="https://www.youtube.com/watch?v=QFfmTLmn3Ow&list=PLSti19ysyJtBJqtXDxtlSFdA1herhJecj">keynote sessions</a>, and some <a href="https://www.youtube.com/watch?v=aZZCZpc0AcY">associate sessions</a> on YouTube to get a feel for what this awesome conference entails.</p>
<div align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-07-devculture-team/culture-3.jpg" width="450">
<div style="width: 600px;">
<sub>Each year, the DevCulture team partners with associates from various organizations and roles to form the Core Planning Team that guides the overall direction of the conference, decides the theme, selects the talks, and plans engaging activities for associates to participate in at the conference.</sub>
</div>
</div>
<br />
<p><strong>Engaging with the Industry</strong></p>
<p>We believe we have a lot to learn from and share back with the industry and local tech community. From agile methodologies to big data processing, we bring in industry experts on a monthly basis in our Tech Talk Series to share their knowledge and perspectives that help our associates learn and grow. You can subscribe to our <a href="https://www.youtube.com/user/CernerEng?sub_confirmation=1">YouTube Channel</a> to get notified anytime we post one!</p>
<p>While attending and sponsoring conferences helps us bring essential knowledge back to Cerner, we’re privileged to send associates out to speak at conferences each year around the world. Being accepted to these conferences recognizes our associates for their complex work and talent while sharing more about what we’re working on at Cerner. Follow us on <a href="https://twitter.com/CernerEng">Twitter</a> to find out what conferences we’re attending, sponsoring, or speaking at and come say hello! As a fun example of one of our talks, check out Kevin Shekleton’s talk at Strange Loop 2017 on ‘<a href="https://www.youtube.com/watch?v=s0XmiXs8iRw">The Security of Classic Game Consoles</a>’.</p>
<div align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-07-devculture-team/culture-4.jpg" width="450">
<sub>Engineering Director Jenni Syed and Engineering Vice President Kevin Shekleton present at FHIR DevDays 2018.</sub>
</div>
<br />
<p>When we consume open source in our software, we have the opportunity to leverage the talent from a broad cross section of the industry to make our solutions better. We also encourage associates to contribute to open source software both internally and externally. Learn more about the work we’re doing in Open Source on our <a href="http://bit.ly/2Oj5DeL">Blog</a>.</p>
<p><strong>ShipIt Day</strong></p>
<p>Modeled after <a href="https://www.atlassian.com/company/shipit">Atlassian’s ShipIt Day</a>, we frequently host these 24 hour hackathons throughout the year in Kansas City, Malvern, Bangalore, and Brasov. We believe this encourages ingenuity and collaboration by promoting cross-pollination of ideas and teams as they solve problems together. Teams in KC compete for the coveted Golden Keyboard and Golden Mouse trophies that travel the campus, each winning team adding a trinket to the trophy representing their unique winning project. Learn about our most recent ShipIt Day winners on this <a href="http://bit.ly/2PQXprk">Engineering Health blog</a>.</p>
<div align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-07-devculture-team/culture-5.jpg" width="450">
<sub>Teams present their projects to a panel of judges at the conclusion of the hackathon to determine the winners.</sub>
</div>
<br />
<p><strong>Our Work Can Sometimes Be Quite Odd.</strong></p>
<p>Amidst the strategic work in advancing our culture, we have found ourselves completing work for things most people would never consider to be a small part of their full time adult day job. Some of our favorite odd job memories from the past six years include:</p>
<ul>
<li>Ordering over 34,000 Lego bricks for <a href="https://www.youtube.com/watch?v=E-TcZBTCZdo">DevCon 2014</a> (following multiple strategy meetings and spreadsheets to determine how many would be necessary for our 3,000+ attendees)</li>
<li>Researching backstories on Marvel characters for DevCon 2017</li>
<li>Watching Doctor Who, Star Trek, Star Wars, Harry Potter, Lord of the Rings, etc. as part of our Training Requirements. We’re also required to pass a test covering Marvel vs. DC Characters. This is all to help ensure our team understand various cultural reference points that are popular amongst our target audience.</li>
<li>Building an elaborate patchwork of Lego shapes on a giant Lego board to serve as a background for an all company meeting
Renting a uHaul to transport old couches, coffee tables, TV stands, and TV’s we purchased from thrift stores in order to create retro living room spaces at <a href="https://www.youtube.com/watch?v=cE0YoFg-hkE">DevCon 2013</a> where associates played video games between sessions.</li>
</ul>
<div align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-11-07-devculture-team/culture-6.jpg" width="450">
<div style="width: 600px;">
<sub>Prior to moving into our brand new Kansas City <a href="http://bit.ly/2GP1vuU">Innovations Campus</a> in 2017, our team made a video to demonstrate all the ways the desks can be configured to showcase the new setup. To avoid it being boring, we dressed up with various costumes we had on hand from other programs.</sub>
</div>
</div>
<br />
<p>We believe culture is a journey, not a destination, and something we will always have to invest in and improve upon. These programs and efforts mentioned just scratch the surface of what we’re working on, with other projects ranging from how we can increase manager effectiveness to influencing our growth in continuous delivery models. Culture doesn’t change overnight, we’re iterating over ours with new programs based on regular feedback, that must be supported from within, and/or that we feel it’s important enough to truly invest in it.</p>
<p>Interested in starting your own culture team? Great idea! We started out with smaller programs and projects to prove their effect and as they grew, documented the amount of work and any measurements we could to provide justification to have our first full time team member in 2012. Measuring cultural advancement can be challenging. We have done this by pulling engagement rates across different roles and organizations to gauge what is or isn’t effective, surveys following program events, and collecting anecdotal evidence of effect of programs (i.e. our team implemented these new SRE approaches/strategies because of Dave Rensin’s keynote at DevCon last month).</p>
<p>Join us on <a href="https://twitter.com/CernerEng">Twitter</a> to stay up to date with all our cultural programs.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Infusing a Culture of Cybersecurity Within Cerner Engineering]]></title>
<link href="http://engineering.cerner.com/blog/culture-of-cybersecurity/"/>
<updated>2018-10-29T00:00:00-05:00</updated>
<id>http://engineering.cerner.com/blog/culture-of-cybersecurity</id>
<content type="html"><![CDATA[<p>With October being <a href="https://www.dhs.gov/national-cyber-security-awareness-month">Cybersecurity Awareness month</a>, we thought it would be a good time to reflect on some of the things we do in engineering to educate our associates and infuse security into our culture. We have over 28,000 associates worldwide supporting hundreds of solutions with millions of lines of code. Each associate has a specialization, such as software development, system support, and consulting. Keeping everyone up to date on the latest in security is a difficult task.</p>
<p>So how do we do it? We have teams dedicated to security that work directly within engineering. These teams have various responsibilities such as ownership of scanning tools and vulnerability tracking. My team’s goal is to bridge the gap by injecting security as a first-class citizen in the software development lifecycle. When working with developers, you have to make the right thing to do the easy thing to do. This is no different when it comes to security. In order to make security easy, we scan, assess, and create a plan for our developers to remediate their vulnerabilities. We promote the tools for scanning, help teams understand the results, and identify fixes for vulnerabilities. We run a monthly cybersecurity meetup which we use as a venue for associates to speak and learn about varying security topics.</p>
<div align="center">
<table>
<tr>
<td align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-10-29-culture-of-cybersecurity/cybersecurity-1.jpg" width="450">
</td>
<td align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-10-29-culture-of-cybersecurity/cybersecurity-2.jpg" width="450">
</td>
</tr>
</table>
<sub>Andy Nelson opening the September edition of the Cybersecurity meetup and Sebastian Brown presenting at the July edition.</sub>
</div>
<p>We also take advantage of opportunities like Cybersecurity Awareness month. We bridge organizational gaps to host a variety of security focused events, engaging associates in development, security, and operations to facilitate better relationships and collaboration. Events like these lower the barrier to entry for our developers to learn more secure practices, and embrace and celebrate the progress we are making in our security journey. We kicked off the activities this month with an external tech talk from <a href="https://twitter.com/bhommertzheim">Britney Hommertzheim</a>. Britney, the Director of Information Security at <a href="https://www.amctheatres.com">AMC Theatres</a>, presented on how we can better integrate security teams and developers. It was a great talk and you can watch the talk on our <a href="https://youtu.be/DTYiNidFjzM">YouTube</a> channel. We invited another external speaker for our Cybersecurity meetup a few weeks ago too. Caleb Christopher, a Technical Business Adviser at <a href="https://www.allegianttechnology.com">Allegiant Technology</a>, gave a great talk titled “Defeating Email Fraud with DMARC”. Along side those 2 events, we have held lunch and learns throughout the month, and are wrapping it all up with an hour of security focused lightning talks tomorrow.</p>
<div align="center">
<table>
<tr>
<td align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-10-29-culture-of-cybersecurity/cybersecurity-3.jpg" width="450">
</td>
<td align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-10-29-culture-of-cybersecurity/cybersecurity-4.jpg" width="450">
</td>
</tr>
</table>
<sub>Britney Hommertzheim giving an external tech talk about integrating security across organizations</sub>
</div>
<p>Security is not easy and we always have to strive to get better. Our development, operations, and security teams must work together, so we are doing our best to provide a forum for collaboration and sharing.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Girl Scouts Earn Cybersecurity Badge at Cerner]]></title>
<link href="http://engineering.cerner.com/blog/girl-scouts-cybersecurity/"/>
<updated>2018-10-05T00:00:00-05:00</updated>
<id>http://engineering.cerner.com/blog/girl-scouts-cybersecurity</id>
<content type="html"><![CDATA[<p>As a software engineering executive from Colombia, I thought that the best way to honor <a href="https://www.hispanicheritagemonth.gov">Hispanic Heritage Month</a> (September 15-October 15) was to help the local Girl Scout Hispanic troops earn one of the new cybersecurity badges. October is Cybersecurity Awareness Month, having the activities nearing October seemed very fitting.</p>
<p><a href="https://www.girlscouts.org/en/about-girl-scouts/girl-scouts-and-stem.html">Girl Scouts has been focusing on STEM badges</a> for all ages with several new initiatives in the past couple of years. The cybersecurity badges are some of the latest additions to the growing list of STEM badges that girls can earn. I was excited to help the troops earn their badge and I wanted to make it very special and appealing to these girls, so I decided to run the event entirely in Spanish. I thought that this approach would be a great way not only to engage the girls, but also their family members who often accompany them to the events.</p>
<p>The badge was designed to be very interactive and engaging. The first activity was a game that helped the girls think about all the different kinds of electronic devices that exist, such as Fitbits, iPads, cell phones, TVs, etc, and how they interact with them in their daily life. The activity then focused on how security in everyday life can translate to security in cyberspace.</p>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-10-05-girl-scouts-cybersecurity/girl-scouts-1.jpg" width="600"></p>
<p>The next part of the event focused on helping the girls understand how much of our life is connected to the internet and how different our life would be if it wasn’t so. The girls had fun describing how they would live without internet. They all agreed that life without internet would be challenging but they would still be able to read and go camping!</p>
<p>To help illustrate the concept of how layers of security are important, the girls drew on whiteboards how they could defend a castle. The girls were quite inventive on this interactive activity!</p>
<div align="center">
<table>
<tr>
<td align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-10-05-girl-scouts-cybersecurity/girl-scouts-2.jpg" width="650">
</td>
<td align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-10-05-girl-scouts-cybersecurity/girl-scouts-3.jpg" width="250">
</td>
</tr>
</table>
<sub>The girls secured their “castles” effectively. One of the most technologically advanced castles included dragons, a force-field and a keypad for the password.</sub>
</div>
<p>The subsequent area of emphasis was regarding how electronic devices communicate. It was interesting to break down networking concepts like TCP/IP, network topology, and firewalls to a group of 1<sup>st</sup> and 2<sup>nd</sup> graders, but I made these concepts relatable. IP packets were explained by building key chains using beads that spelled “brownies.” The activity involved the girls acting as senders, messengers and receivers, along with individual beads acting as packets with headers, contents, and other metadata.</p>
<div align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-10-05-girl-scouts-cybersecurity/girl-scouts-4.jpg" width="600">
<sub>One scout displays her finished IP packet keychain!</sub>
</div>
<p>Safety rules were an integral part of the badge; the Brownies formed groups and made posters to help others understand the importance of the following internet rules:</p>
<ul>
<li>Don’t talk to strangers</li>
<li>Stop and think before you act</li>
<li>Don’t believe everything that you see or everything that people say</li>
</ul>
<p>We wrapped up by touring <a href="https://engineering.cerner.com/blog/one-year-calling-innovations-home">our Innovations campus</a> and highlighting how technology helps us improve our health and the health of our communities. Overall, this was another phenomenal opportunity for the Girl Scouts to engage with Cerner. It exposed them to key technology concepts and it expanded the prevalence of STEM education throughout the community.</p>
<p><em>To see more about Denisse’s involvement in the Hispanic Girl Scout community, <a href="https://engineering.cerner.com/blog/influencing-the-young-spanish-seaking-female-generation">check out this blog from 2017</a>. Denisse has played a vital role in bringing STEM opportunities to the local troops. In fact, she was recently recognized by the Hispanic Chamber of Commerce of Greater Kansas City for her philanthropic efforts by receiving the STEM and Education Nuestra Latina 2018 Award. Congratulations, Denisse!</em></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[SSH Steps for Jenkins Pipeline]]></title>
<link href="http://engineering.cerner.com/blog/ssh-steps-for-jenkins-pipeline/"/>
<updated>2018-09-20T00:00:00-05:00</updated>
<id>http://engineering.cerner.com/blog/ssh-steps-for-jenkins-pipeline</id>
<content type="html"><![CDATA[<p><strong>Pipeline-as-code</strong> or defining the deployment pipeline through code rather than manual job creation through UI, provides tremendous benefits for teams automating builds and deployment infrastructure across their environments.</p>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-09-20-ssh-steps-for-jenkins-pipeline/jenkins-pipeline.png" width="800"></p>
<p><em>Source of image: <a href="https://jenkins.io/doc/book/pipeline/">https://jenkins.io/doc/book/pipeline/</a></em></p>
<h1>Jenkins Pipelines</h1>
<p><a href="https://jenkins.io/">Jenkins</a> is a well-known open source continuous integration and continuous deployment automation tool. With the latest 2.0 release, Jenkins introduced the Workflow plugin that implements Pipeline-as-code. This plugin lets you define delivery pipelines using concise scripts which deal elegantly with jobs involving persistence and asynchrony.</p>
<p>The Pipeline-as-code’s script is also known as a <em>Jenkinsfile</em>.</p>
<p>Jenkinsfiles uses a domain specific language syntax based on the <a href="http://groovy-lang.org/">Groovy</a> programming language. They are persistent files which can be checked in and version-controlled along with the rest of their project source code. This file can contain the complete set of encoded steps (steps, nodes, and stages) necessary to define the entire application life-cycle, becoming the intersecting point between development and operations.</p>
<h2>Missing piece of the puzzle</h2>
<p>One of the most common steps defined in a basic pipeline workflow is the <em>Deploy</em> step. The deployment stage encompasses everything from publishing build artifacts to pushing code into pre-production and production environments. This deployment stage usually involves both development and operations teams logging onto various remote nodes to run commands and/or scripts to deploy code and configuration. While there are a couple of existing ssh plugins for Jenkins, they currently don’t support the functionality such as logging into nodes for pipelines. Thus, there was a need for a plugin that supports these steps.</p>
<h1>Introducing SSH Steps</h1>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-09-20-ssh-steps-for-jenkins-pipeline/jenkins-ssh-steps-plugin.png"></p>
<p>Recently, our team consisting of <a href="https://github.com/ghenkes">Gabe Henkes</a>, <a href="https://github.com/wuchenwang">Wuchen Wang</a> and <a href="https://github.com/nrayapati">myself</a> started working on a project to automate deployments through Jenkins pipelines to help facilitate running commands on over one thousand nodes. We looked at several options including existing plugins, internal shared Jenkins libraries, and others. In the end, we felt it was best to create and open source a plugin to fill this gap so that it can be used across Cerner and beyond.</p>
<p>The initial version of this new plugin SSH Steps supports the following:</p>
<ul>
<li><code>sshCommand</code>: Executes the given command on a remote node.</li>
<li><code>sshScript</code>: Executes the given shell script on a remote node.</li>
<li><code>sshGet</code>: Gets a file/directory from the remote node to current workspace.</li>
<li><code>sshPut</code>: Puts a file/directory from the current workspace to remote node.</li>
<li><code>sshRemove</code>: Removes a file/directory from the remote node.</li>
</ul>
<h2>Usage</h2>
<p>Below is a simple demonstration on how to use above steps. More documentation can be found on <a href="https://github.com/jenkinsci/ssh-steps-plugin/blob/master/README.adoc">GitHub</a>.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='groovy'><span class='line'><span class="kt">def</span> <span class="n">remote</span> <span class="o">=</span> <span class="o">[:]</span>
</span><span class='line'><span class="n">remote</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="s2">"node"</span>
</span><span class='line'><span class="n">remote</span><span class="o">.</span><span class="na">host</span> <span class="o">=</span> <span class="s2">"node.abc.com"</span>
</span><span class='line'><span class="n">remote</span><span class="o">.</span><span class="na">allowAnyHosts</span> <span class="o">=</span> <span class="kc">true</span>
</span><span class='line'>
</span><span class='line'><span class="n">node</span> <span class="o">{</span>
</span><span class='line'> <span class="n">withCredentials</span><span class="o">([</span><span class="n">usernamePassword</span><span class="o">(</span><span class="nl">credentialsId:</span> <span class="s1">'sshUserAcct'</span><span class="o">,</span> <span class="nl">passwordVariable:</span> <span class="s1">'password'</span><span class="o">,</span> <span class="nl">usernameVariable:</span> <span class="s1">'userName'</span><span class="o">)])</span> <span class="o">{</span>
</span><span class='line'> <span class="n">remote</span><span class="o">.</span><span class="na">user</span> <span class="o">=</span> <span class="n">userName</span>
</span><span class='line'> <span class="n">remote</span><span class="o">.</span><span class="na">password</span> <span class="o">=</span> <span class="n">password</span>
</span><span class='line'>
</span><span class='line'> <span class="n">stage</span><span class="o">(</span><span class="s2">"SSH Steps Rocks!"</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="n">writeFile</span> <span class="nl">file:</span> <span class="s1">'test.sh'</span><span class="o">,</span> <span class="nl">text:</span> <span class="s1">'ls'</span>
</span><span class='line'> <span class="n">sshCommand</span> <span class="nl">remote:</span> <span class="n">remote</span><span class="o">,</span> <span class="nl">command:</span> <span class="s1">'for i in {1..5}; do echo -n \"Loop \$i \"; date ; sleep 1; done'</span>
</span><span class='line'> <span class="n">sshScript</span> <span class="nl">remote:</span> <span class="n">remote</span><span class="o">,</span> <span class="nl">script:</span> <span class="s1">'test.sh'</span>
</span><span class='line'> <span class="n">sshPut</span> <span class="nl">remote:</span> <span class="n">remote</span><span class="o">,</span> <span class="nl">from:</span> <span class="s1">'test.sh'</span><span class="o">,</span> <span class="nl">into:</span> <span class="s1">'.'</span>
</span><span class='line'> <span class="n">sshGet</span> <span class="nl">remote:</span> <span class="n">remote</span><span class="o">,</span> <span class="nl">from:</span> <span class="s1">'test.sh'</span><span class="o">,</span> <span class="nl">into:</span> <span class="s1">'test_new.sh'</span><span class="o">,</span> <span class="nl">override:</span> <span class="kc">true</span>
</span><span class='line'> <span class="n">sshRemove</span> <span class="nl">remote:</span> <span class="n">remote</span><span class="o">,</span> <span class="nl">path:</span> <span class="s1">'test.sh'</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>
<h2>Configuring via YAML</h2>
<p>At Cerner, we always strive to have simple configuration files for CI/CD pipelines whenever possible. With that in mind, my team built a wrapper on top of these steps from this plugin. After some design and analysis, we came up with the following YAML structure to run commands across various remote groups:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
</pre></td><td class='code'><pre><code class='yaml'><span class='line'><span class="l-Scalar-Plain">config</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="l-Scalar-Plain">credentials_id</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">sshUserAcct</span>
</span><span class='line'>
</span><span class='line'><span class="l-Scalar-Plain">remote_groups</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="l-Scalar-Plain">r_group_1</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">name</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">node01</span>
</span><span class='line'> <span class="l-Scalar-Plain">host</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">node01.abc.net</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">name</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">node02</span>
</span><span class='line'> <span class="l-Scalar-Plain">host</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">node02.abc.net</span>
</span><span class='line'> <span class="l-Scalar-Plain">r_group_2</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">name</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">node03</span>
</span><span class='line'> <span class="l-Scalar-Plain">host</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">node03.abc.net</span>
</span><span class='line'>
</span><span class='line'><span class="l-Scalar-Plain">command_groups</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="l-Scalar-Plain">c_group_1</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">commands</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="s">'ls</span><span class="nv"> </span><span class="s">-lrt'</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="s">'whoami'</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">scripts</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="s">'test.sh'</span>
</span><span class='line'> <span class="l-Scalar-Plain">c_group_2</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">gets</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">from</span><span class="p-Indicator">:</span> <span class="s">'test.sh'</span>
</span><span class='line'> <span class="l-Scalar-Plain">to</span><span class="p-Indicator">:</span> <span class="s">'test_new.sh'</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">puts</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">from</span><span class="p-Indicator">:</span> <span class="s">'test.sh'</span>
</span><span class='line'> <span class="l-Scalar-Plain">to</span><span class="p-Indicator">:</span> <span class="s">'.'</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">removes</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="s">'test.sh'</span>
</span><span class='line'>
</span><span class='line'><span class="l-Scalar-Plain">steps</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="l-Scalar-Plain">deploy</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">remote_groups</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">r_group_1</span>
</span><span class='line'> <span class="l-Scalar-Plain">command_groups</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">c_group_1</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">remote_groups</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">r_group_2</span>
</span><span class='line'> <span class="l-Scalar-Plain">command_groups</span><span class="p-Indicator">:</span>
</span><span class='line'> <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">c_group_2</span>
</span></code></pre></td></tr></table></div></figure>
<p>The above example runs commands from <code>c_group_1</code> on remote nodes within <code>r_group_1</code> in parallel before it moves on to the next group using <code>sshUserAcct</code> (from the <a href="https://jenkins.io/doc/book/using/using-credentials/">Jenkins Credentials</a> store) to logon to nodes.</p>
<h2>Shared Pipeline Library</h2>
<p>We have created a shared pipeline library that contains a <code>sshDeploy</code> step to support the above mentioned YAML syntax. Below is the code snippet for the sshDeploy step from the library. The full version can be found <a href="https://github.com/nrayapati/ssh-deploy-library">here</a> on Github.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
</pre></td><td class='code'><pre><code class='groovy'><span class='line'><span class="err">#</span><span class="o">!</span><span class="s">/usr/</span><span class="n">bin</span><span class="o">/</span><span class="n">groovy</span>
</span><span class='line'><span class="kt">def</span> <span class="nf">call</span><span class="o">(</span><span class="n">String</span> <span class="n">yamlName</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="kt">def</span> <span class="n">yaml</span> <span class="o">=</span> <span class="n">readYaml</span> <span class="nl">file:</span> <span class="n">yamlName</span>
</span><span class='line'> <span class="n">withCredentials</span><span class="o">([</span><span class="n">usernamePassword</span><span class="o">(</span><span class="nl">credentialsId:</span> <span class="n">yaml</span><span class="o">.</span><span class="na">config</span><span class="o">.</span><span class="na">credentials_id</span><span class="o">,</span> <span class="nl">passwordVariable:</span> <span class="s1">'password'</span><span class="o">,</span> <span class="nl">usernameVariable:</span> <span class="s1">'userName'</span><span class="o">)])</span> <span class="o">{</span>
</span><span class='line'> <span class="n">yaml</span><span class="o">.</span><span class="na">steps</span><span class="o">.</span><span class="na">each</span> <span class="o">{</span> <span class="n">stageName</span><span class="o">,</span> <span class="n">step</span> <span class="o">-></span>
</span><span class='line'> <span class="n">step</span><span class="o">.</span><span class="na">each</span> <span class="o">{</span>
</span><span class='line'> <span class="kt">def</span> <span class="n">remoteGroups</span> <span class="o">=</span> <span class="o">[:]</span>
</span><span class='line'> <span class="kt">def</span> <span class="n">allRemotes</span> <span class="o">=</span> <span class="o">[]</span>
</span><span class='line'> <span class="n">it</span><span class="o">.</span><span class="na">remote_groups</span><span class="o">.</span><span class="na">each</span> <span class="o">{</span>
</span><span class='line'> <span class="n">remoteGroups</span><span class="o">[</span><span class="n">it</span><span class="o">]</span> <span class="o">=</span> <span class="n">yaml</span><span class="o">.</span><span class="na">remotes</span><span class="o">.</span><span class="s2">"$it"</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'>
</span><span class='line'> <span class="kt">def</span> <span class="n">commandGroups</span> <span class="o">=</span> <span class="o">[:]</span>
</span><span class='line'> <span class="n">it</span><span class="o">.</span><span class="na">command_groups</span><span class="o">.</span><span class="na">each</span> <span class="o">{</span>
</span><span class='line'> <span class="n">commandGroups</span><span class="o">[</span><span class="n">it</span><span class="o">]</span> <span class="o">=</span> <span class="n">yaml</span><span class="o">.</span><span class="na">commands</span><span class="o">.</span><span class="s2">"$it"</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="kt">def</span> <span class="n">isSudo</span> <span class="o">=</span> <span class="kc">false</span>
</span><span class='line'> <span class="n">remoteGroups</span><span class="o">.</span><span class="na">each</span> <span class="o">{</span> <span class="n">remoteGroupName</span><span class="o">,</span> <span class="n">remotes</span> <span class="o">-></span>
</span><span class='line'> <span class="n">allRemotes</span> <span class="o">+=</span> <span class="n">remotes</span><span class="o">.</span><span class="na">collect</span> <span class="o">{</span> <span class="n">remote</span> <span class="o">-></span>
</span><span class='line'> <span class="k">if</span><span class="o">(!</span><span class="n">remote</span><span class="o">.</span><span class="na">name</span><span class="o">)</span>
</span><span class='line'> <span class="n">remote</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="n">remote</span><span class="o">.</span><span class="na">host</span>
</span><span class='line'> <span class="n">remote</span><span class="o">.</span><span class="na">user</span> <span class="o">=</span> <span class="n">userName</span>
</span><span class='line'> <span class="n">remote</span><span class="o">.</span><span class="na">password</span> <span class="o">=</span> <span class="n">password</span>
</span><span class='line'> <span class="n">remote</span><span class="o">.</span><span class="na">allowAnyHosts</span> <span class="o">=</span> <span class="kc">true</span>
</span><span class='line'> <span class="n">remote</span><span class="o">.</span><span class="na">groupName</span> <span class="o">=</span> <span class="n">remoteGroupName</span>
</span><span class='line'> <span class="n">remote</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="k">if</span><span class="o">(</span><span class="n">allRemotes</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="k">if</span><span class="o">(</span><span class="n">allRemotes</span><span class="o">.</span><span class="na">size</span><span class="o">()</span> <span class="o">></span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="kt">def</span> <span class="n">stepsForParallel</span> <span class="o">=</span> <span class="n">allRemotes</span><span class="o">.</span><span class="na">collectEntries</span> <span class="o">{</span> <span class="n">remote</span> <span class="o">-></span>
</span><span class='line'> <span class="o">[</span><span class="s2">"${remote.groupName}-${remote.name}"</span> <span class="o">:</span> <span class="n">transformIntoStep</span><span class="o">(</span><span class="n">stageName</span><span class="o">,</span> <span class="n">remote</span><span class="o">.</span><span class="na">groupName</span><span class="o">,</span> <span class="n">remote</span><span class="o">,</span> <span class="n">commandGroups</span><span class="o">)]</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="n">stage</span><span class="o">(</span><span class="n">stageName</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="n">parallel</span> <span class="n">stepsForParallel</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
</span><span class='line'> <span class="kt">def</span> <span class="n">remote</span> <span class="o">=</span> <span class="n">allRemotes</span><span class="o">.</span><span class="na">first</span><span class="o">()</span>
</span><span class='line'> <span class="n">stage</span><span class="o">(</span><span class="n">stageName</span> <span class="o">+</span> <span class="s2">"\n"</span> <span class="o">+</span> <span class="n">remote</span><span class="o">.</span><span class="na">groupName</span> <span class="o">+</span> <span class="s2">"-"</span> <span class="o">+</span> <span class="n">remote</span><span class="o">.</span><span class="na">name</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'> <span class="n">transformIntoStep</span><span class="o">(</span><span class="n">stageName</span><span class="o">,</span> <span class="n">remote</span><span class="o">.</span><span class="na">groupName</span><span class="o">,</span> <span class="n">remote</span><span class="o">,</span> <span class="n">commandGroups</span><span class="o">).</span><span class="na">call</span><span class="o">()</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>By using the step (as described in the snippet above) from this shared pipeline library, a Jenkinsfile can be reduced to:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='groovy'><span class='line'><span class="nd">@Library</span><span class="o">(</span><span class="s1">'ssh_deploy'</span><span class="o">)</span> <span class="n">_</span>
</span><span class='line'>
</span><span class='line'><span class="n">node</span> <span class="o">{</span>
</span><span class='line'> <span class="n">checkout</span> <span class="n">scm</span>
</span><span class='line'> <span class="nf">sshDeploy</span><span class="o">(</span><span class="s1">'dev/deploy.yml'</span><span class="o">);</span>
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>An example execution of the above pipeline code in Blue Ocean looks like this:</p>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-09-20-ssh-steps-for-jenkins-pipeline/jenkins-ssh-deploy.png" width="600"></p>
<h2>Wrapping up</h2>
<p>Steps from the <a href="https://github.com/jenkinsci/ssh-steps-plugin">SSH Steps Plugin</a> are deliberately generic enough that they can be used for various other use-cases as well, not just for deploying code. Using SSH Steps has significantly reduced the time we spend on deployments and has given us the possibility of easily scaling our deployment workflows to various environments.</p>
<p>Help us make this <a href="https://github.com/jenkinsci/ssh-steps-plugin">plugin</a> better by contributing. Whether it is adding or suggesting a new feature, bug fixes, or simply improving documentation, contributions are always welcome.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[ShipIt XII]]></title>
<link href="http://engineering.cerner.com/blog/shipit-xii/"/>
<updated>2018-08-30T00:00:00-05:00</updated>
<id>http://engineering.cerner.com/blog/shipit-xii</id>
<content type="html"><![CDATA[<p><img class="center" src="http://engineering.cerner.com/assets/2018-08-30-shipit-xii/shipitxii-logo.png" width="400"></p>
<p>This month we held our quarterly hackathon event- called ShipIt Day. We would like to thank all the participants for making ShipIt Day XII a huge success. With 75 participants, we had associates representing 13 different organizations across Cerner. These associates were given 24-hours to meet the requirements of this hackathon which included making something that was innovative, usable, and value-adding. As the clock ticked down, our associates worked in their teams to complete a project while taking some time to enjoy the fun activities happening throughout ShipIt day.</p>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-08-30-shipit-xii/shipitxii-1.jpg" width="640"></p>
<p>It is an unwritten rule that the balance between fun and project time during ShipIt days should remain even. Associates are encouraged to enjoy the collaborative spaces of Cerner’s Innovations campus and participate in various activities such as ping-pong, eating snacks, playing games, and building relationships with other Cerner associates. Participants were given vouchers to use in the Innovations Café for breakfast and lunch. They were also served a fully-catered taco bar to stay energized for dinner.</p>
<p>This year, <a href="https://www.imdb.com/title/tt0086567/">WarGames</a> and <a href="https://en.wikipedia.org/wiki/ColecoVision">ColecoVision</a> gameplay were brought in for participants to enjoy throughout the evening. As said best by Cerner associate, Carl Chesser (<a href="https://twitter.com/che55er">@che55er</a>):</p>
<blockquote><p>Software creation requires additional breaks… ShipIt at Cerner is no exception of this software craftmanship approach.</p></blockquote>
<p>The morning crept up on the teams quickly, and they had to begin preparing for their 4-minute presentation in the Assembly at Innovations campus. The goal of the team presentations is to explain the project, how it was implemented, and show a brief demo to the judges and audience. All the teams delivered competitive pitches, which made judging very difficult.</p>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-08-30-shipit-xii/shipitxii-2.jpg" width="640"></p>
<p>Huge thanks to Micah Whitacre, Nick Smith, Jon Miller, and Jared Moore for serving as our rockstar judges!</p>
<h2>Overall Winners</h2>
<p>The judges gathered together after the completion of the presentations to decide the top three performing teams. Congratulations to the following teams on your outstanding performance!</p>
<h3>First Place: Let’s Take Suggestions</h3>
<p>Team Members: Scott Grissom, Alex Harder, and Matt Nelson</p>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-08-30-shipit-xii/shipitxii-8.jpg" width="400"></p>
<p>This team was awarded the Golden Keyboard for their first-place achievement. They will defend the traveling trophy for the upcoming months and add a symbolic trinket to the collection for their team to be remembered in ShipIt history.</p>
<p>The focus of this project was to provide a mechanism for customized cloud-based ACL testing. Utilizing serverless functions through the <a href="https://www.openfaas.com/">OpenFaaS framework</a>, the team enabled rapid development and deployment of serverless functions which test a specific type of network access, e.g. using <a href="https://en.wikipedia.org/wiki/CURL">cURL</a> to access a ReST endpoint or a JDBC client to access a database instance. Deploying these functions to the same cloud instance which hosts services provides a more accurate testing of network dependencies from the perspective of a service as opposed to testing from a developer machine.</p>
<h3>Second Place: #crowdercrowd</h3>
<p>Team Members: Ian Kottman, Heather Boveri, Robert Ryterski, and David Crowder</p>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-08-30-shipit-xii/shipitxii-6.jpg" width="400"></p>
<p>#crowdercrowd created a dashboard showing cluster utilization of applications across both on-premise and public cloud clusters. The metrics show how much CPU and memory an application is using versus how much it is requesting, along with an estimated yearly cost to run the application. This dashboard will be used to identify what applications can be scaled down to better fit their actual resource needs.</p>
<h3>Third Place: Bravo Avocado</h3>
<p>Team Members: Jan Monterrubio, Maximilian Schroeder, and Jacob Zimmermann</p>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-08-30-shipit-xii/shipitxii-7.jpg" width="400"></p>
<p>Bravo Avocado created a <a href="https://maven.apache.org/index.html">Maven plugin</a> that starts a <a href="https://www.docker.com/">Docker container</a> of a ReST service. It also allows the integration tests to dynamically connect to the correct URL and port of the container. This lets users run integration tests directly against the working code as part of the Maven lifecycle. Before the team wrote the plugin, they had to manually stand up the service and update the test configuration to validate any changes. By tying these eight steps to an existing command, users can streamline development for ReST services.</p>
<h3>People’s Choice</h3>
<p>Aside from our talented official judges, many associates join in on the ShipIt Day fun to act as peer judges in the People’s Choice category. The large audience during the ShipIt presentations was asked to get involved and vote for their favorite teams in certain categories.</p>
<ul>
<li><p><strong>Favorite Team Name</strong>: Chef BoyarDeployments could be better (Steven Goldberg, Ryan Neff)</p></li>
<li><p><strong>Favorite Project</strong>: Audio Bot (Mitali Paygude, Kunal Suryavanshi, Vinay Datta Pinnaka)</p></li>
<li><p><strong>Best Presentation</strong>: Team Rhinos (Venkata Adusumilli, Veda Bhaskar Bhamidipati, Naga Prashanth Chanda, Sunand Kumar Matam, Prashanth Gajula)</p></li>
</ul>
<div align="center">
<table>
<tr>
<td align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-08-30-shipit-xii/shipitxii-4.jpg" width="300">
<sub>Favorite Team Name</sub>
</td>
<td align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-08-30-shipit-xii/shipitxii-5.jpg" width="300">
<sub>Favorite Project</sub>
</td>
<td align="center">
<img class="center" src="http://engineering.cerner.com/assets/2018-08-30-shipit-xii/shipitxii-3.jpg" width="300">
<sub>Best Presentation</sub>
</td>
</tr>
</table>
</div>
<p></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Summer of Engineering Health: A Software Intern's Story]]></title>
<link href="http://engineering.cerner.com/blog/summer-of-engineering-health-intern-story/"/>
<updated>2018-07-26T00:00:00-05:00</updated>
<id>http://engineering.cerner.com/blog/summer-of-engineering-health-intern-story</id>
<content type="html"><![CDATA[<p><em>Pratik will be starting his Junior year at the University of Michigan this Fall studying Computer Science and Biomedical Engineering. This summer he’s a Software Intern on Cerner’s LightsOn Network team. This is the story of his summer experience:</em></p>
<p>As a college student, it’s not every day that you get to work on cutting edge technology to transform healthcare as we know it. Every morning, I walk past a wall on the way to the elevator: “Health care is too important to stay the same.” Simple enough, huh?</p>
<p>Healthcare has been one of the few fields that has yet to fully embrace the possibilities new technology has afforded. Throughout my internship, there’s been an overall culture where associates understand they wouldn’t be working on something unless it was important. As a result, associates are visibly passionate and driven about the problems they’re working on, constantly striving to improve and add value. In my experience thus far, the environment at Cerner has been both engaging and supportive, allowing me to grow both personally and professionally as I strive to help improve healthcare and better the lives of others.</p>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-07-26-summer-of-engineering-health-intern-story/summer-2018-intern-1.jpg"></p>
<p>As interns, we had the opportunity to attend our two-day developer conference (<a href="https://engineering.cerner.com/2013/08/devcon/">DevCon</a>) where we learned from <a href="https://www.youtube.com/user/CernerEng/featured">talks</a> on topics ranging from development technologies, innovating for maximum value, and understanding the perspectives of our clients when they use our solutions. I found it interesting to reflect on the differences between the “best solution” from a technology/development standpoint versus that of the end-user, maneuvering the product every day. More importantly, we discussed how we as engineers can provide users with opportunities to streamline their workflow and increase efficacy, without causing frustration among clients accustomed to a more traditional process. Changes need to be implemented gradually and seamlessly in order to get the most buy-in. Introduce change too fast and the users will be frustrated, regardless of the overall improvement.</p>
<h3>Small Data, Big Picture</h3>
<p>This summer, I have had the opportunity to work as a Software Intern on the <a href="https://www.cerner.com/solutions/lights-on-network">LightsOn Network</a> team, which develops a solution that provides both internal associates and external clients with the pertinent information necessary to make organizational decisions, whether that be in workforce experience, system configuration optimization, or organizational value. I’ve been contributing to a project aimed at providing users with additional clarity about the status of their data at the metric, dashboard, and data source levels. The status indicators update in real-time to provide clients with the most up to date information about their data. Users can then examine the dashboards with this information in mind or drill down to identify what specific feed may be causing the issue to troubleshoot. The ability to immediately make such a large impact on clients around the world as an intern has been a humbling experience.</p>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-07-26-summer-of-engineering-health-intern-story/summer-2018-intern-3.jpg"></p>
<p>The internship experience thus far has not only helped me learn about useful development languages including <a href="https://www.djangoproject.com/">Django</a>, <a href="https://angular.io/">Angular</a>, and <a href="https://jquery.com/">JQuery</a>, but also opened my eyes to the considerations taken into account when delivering a successful analytics product and software application in general. I’ve experienced the importance of breaking down the product into individual problems to target and then working on telling a clear story in the final product. All around me, the decisions made are not based on technology alone, but first truly consider the value added to the individual providers we aim to serve. By reducing inefficiencies in healthcare, we allow providers to do their jobs more effectively and in turn, allow more people access to healthcare.</p>
<h3>Key Takeaways</h3>
<ul>
<li>Built great connections with our team members and fellow interns</li>
<li>Learned new programming languages, but more importantly, became more experienced with engineering practices in a highly regulated industry, as well as, the agile development framework</li>
<li>Improved time management skills, especially optimizing my time usage when managing code reviews and future development tasks</li>
<li>Learned first-hand the value of diving in deep and taking advantage of every opportunity possible</li>
<li>Became inspired to continue applying computer science to the field of healthcare and constantly look for avenues to strengthen our solutions to ultimately benefit each patient</li>
<li>Realized that improvements to healthcare technology doesn’t only affect a specific group of people, but each and every one of us – the impact is enormous.</li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Scalable Data Science With FHIR]]></title>
<link href="http://engineering.cerner.com/blog/data-engineering-with-bunsen/"/>
<updated>2018-07-02T00:00:00-05:00</updated>
<id>http://engineering.cerner.com/blog/data-engineering-with-bunsen</id>
<content type="html"><![CDATA[<p>The <a href="https://www.hl7.org/fhir/overview.html">FHIR standard</a> started as a better way to exchange healthcare data, but it also provides a solid basis for deep analytics and Machine Learning at scale. This post looks at an example from the recent <a href="https://www.fhirdevdays.com/">FHIR DevDays</a> conference that does just that. You can also run the interactive <a href="https://github.com/cerner/bunsen-tutorial">FHIR data engineering tutorial</a> used in the conference yourself.</p>
<p>Our first step is to bring FHIR data into a data lake — a computational environment where our analysis can easily and efficiently work through petabytes of data. We’ll look at some patterns for doing so, with concrete examples using the open source <a href="http://engineering.cerner.com/bunsen">Bunsen</a> and <a href="https://spark.apache.org/">Apache Spark</a> projects.</p>
<h3>FHIR StructureDefinitions Define the Schema</h3>
<p>The schema for every dataset you see here was generated from a <a href="https://www.hl7.org/fhir/stu3/structuredefinition.html">FHIR StructureDefinition</a>. There is a big gap between building a FHIR-based schema by hand and generating it directly from the source. Every field in every query here is fully documented as a <a href="https://www.hl7.org/fhir/stu3/resourcelist.html">FHIR resource</a>, making the FHIR documentation itself the primary reference to our datasets. This means the data is well-defined, curated, and familiar to those who have used FHIR.</p>
<h3>Data Catalogs over Filesystems</h3>
<p>Organizing data in files and directories is convenient, but it becomes unwieldy when working with a large number of complex datasets. Data catalogs can meet this need — and to offer a foundation for further data governance. The <a href="https://hive.apache.org/">Apache Hive metastore</a> is the most common way to catalog data in Hadoop-based environments and has native integration with Spark, so we organize data as one FHIR resource per table. Here’s an example from the <a href="https://github.com/cerner/bunsen-tutorial/blob/fhirdevdays2018/data_engineering_tutorial.ipynb">tutorial used at FHIR DevDays</a>:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">spark</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="s">'use tutorial_small'</span><span class="p">)</span>
</span><span class='line'><span class="n">spark</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="s">'show tables'</span><span class="p">)</span><span class="o">.</span><span class="n">toPandas</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>
<p>Which prints a table like this:</p>
<table>
<thead>
<tr>
<th></th>
<th align="left">database </th>
<th align="left">tableName </th>
<th align="left">isTemporary </th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td align="left">tutorial_small </td>
<td align="left">allergyintolerance </td>
<td align="left">false</td>
</tr>
<tr>
<td></td>
<td align="left">tutorial_small </td>
<td align="left">careplan </td>
<td align="left">false</td>
</tr>
<tr>
<td></td>
<td align="left">tutorial_small </td>
<td align="left">claim </td>
<td align="left">false</td>
</tr>
<tr>
<td></td>
<td align="left">tutorial_small </td>
<td align="left">condition </td>
<td align="left">false</td>
</tr>
</tbody>
</table>
<p>…and so on. This makes it trivial to use intuitive database metaphors like <code>use tutorial_small</code> and <code>select * from condition</code>.</p>
<h3>First-class ValueSet Support</h3>
<p><a href="https://www.hl7.org/fhir/stu3/valueset.html">FHIR ValueSets</a> — collections of code values for a specific purpose — are essential to querying or working with FHIR data. Therefore they should be a first-class construct in our healthcare data lake. Here’s a look at using some FHIR valuesets in our queries as supported by <a href="https://engineering.cerner.com/bunsen/0.4.0/">Bunsen</a>.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">bunsen.stu3.valuesets</span> <span class="kn">import</span> <span class="n">push_valuesets</span><span class="p">,</span> <span class="n">valueset</span><span class="p">,</span> <span class="n">isa_loinc</span><span class="p">,</span> <span class="n">isa_snomed</span>
</span><span class='line'>
</span><span class='line'><span class="n">push_valuesets</span><span class="p">(</span><span class="n">spark</span><span class="p">,</span>
</span><span class='line'> <span class="p">{</span><span class="s">'ldl'</span> <span class="p">:</span> <span class="n">isa_loinc</span><span class="p">(</span><span class="s">'18262-6'</span><span class="p">),</span> <span class="c"># Loads LOINC descendants </span>
</span><span class='line'> <span class="s">'hdl'</span> <span class="p">:</span> <span class="n">isa_loinc</span><span class="p">(</span><span class="s">'2085-9'</span><span class="p">),</span>
</span><span class='line'> <span class="s">'hypertension'</span> <span class="p">:</span> <span class="n">isa_snomed</span><span class="p">(</span><span class="s">'38341003'</span><span class="p">),</span> <span class="c"># Loads SNOMED descendants</span>
</span><span class='line'> <span class="c"># Loaded from a FHIR ValueSet resource</span>
</span><span class='line'> <span class="s">'chd'</span> <span class="p">:</span> <span class="n">valueset</span><span class="p">(</span><span class="s">'http://engineering.cerner.com/bunsen/example/chd'</span><span class="p">,</span> <span class="s">'201806001'</span><span class="p">)});</span>
</span></code></pre></td></tr></table></div></figure>
<p>Now we can use these valuesets in our SQL queries via the <em>in_valueset</em> user-defined function:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">spark</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="s">"""</span>
</span><span class='line'><span class="s">select subject.reference,</span>
</span><span class='line'><span class="s"> code.coding[0].system system,</span>
</span><span class='line'><span class="s"> code.coding[0].code code,</span>
</span><span class='line'><span class="s"> onsetDateTime</span>
</span><span class='line'><span class="s">from condition</span>
</span><span class='line'><span class="s">where in_valueset(code, 'chd')</span>
</span><span class='line'><span class="s">"""</span><span class="p">)</span><span class="o">.</span><span class="n">limit</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span><span class="o">.</span><span class="n">toPandas</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>
<table>
<thead>
<tr>
<th></th>
<th align="left">reference </th>
<th align="left">system </th>
<th align="left">code </th>
<th align="left">onsetDateTime </th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td align="left">urn:uuid:f88c… </td>
<td align="left"><a href="http://snomed.info/sct">http://snomed.info/sct</a> </td>
<td align="left">53741008 </td>
<td align="left">2014-09-14T07:45:47</td>
</tr>
<tr>
<td></td>
<td align="left">urn:uuid:d9ac… </td>
<td align="left"><a href="http://snomed.info/sct">http://snomed.info/sct</a> </td>
<td align="left">53741008 </td>
<td align="left">2017-05-22T06:56:19</td>
</tr>
<tr>
<td></td>
<td align="left">urn:uuid:7460… </td>
<td align="left"><a href="http://snomed.info/sct">http://snomed.info/sct</a> </td>
<td align="left">53741008 </td>
<td align="left">1974-08-06T06:50:32</td>
</tr>
<tr>
<td></td>
<td align="left">urn:uuid:5a28… </td>
<td align="left"><a href="http://snomed.info/sct">http://snomed.info/sct</a> </td>
<td align="left">53741008 </td>
<td align="left">2015-08-28T01:17:20</td>
</tr>
</tbody>
</table>
<p>It’s worth looking at what’s going on here: in a few lines of SQL, we are going from the rich (but somewhat complicated) FHIR Condition data model to a simple table of onset times of Coronary Heart Disease conditions.</p>
<h3>FHIR Data in Columnar Storage</h3>
<p>Users see a clear catalog of FHIR datasets, but something important is happening behind the scenes. Most data stores or serialization encodings like JSON keep data in a row-wise format. This means all columns from a given record are physically adjacent on disk, like this:</p>
<p> <img class="center" src="http://engineering.cerner.com/assets/2018-07-02-data-engineering-with-bunsen/row-wise.png" width="600"></p>
<p>This is a good fit for many workloads, but often not for analysis at scale. For instance, we may want to query the “code” column of several billion observation rows, and retrieve only those in a certain valueset. This is more efficient if columns are grouped together, like this:</p>
<p><img class="center" src="http://engineering.cerner.com/assets/2018-07-02-data-engineering-with-bunsen/columnar.png" width="600"></p>
<p>This is completely transparent to the user; she simply sees FHIR data from the specification.</p>
<p>So while users see the FHIR data model, it is encoded in a columnar file like Parquet. In such files, all of these “code” columns next to one another, allowing the queries to do tight scans over columns of interest without expensive seeking past unneeded data.</p>
<h3>Creating For-Purpose Views</h3>
<p>These are the building blocks that simplify otherwise complex analysis. For instance, if we want to identify people with diabetes-related risks, we can create a collection of simple views of the underlying data customized for that purpose. You can see the full example in the <a href="https://github.com/cerner/bunsen-tutorial/blob/fhirdevdays2018/data_engineering_tutorial.ipynb">Bunsen data engineering tutorial</a>, but we’ll start with a dataframe of people with diabetes-related conditions as defined by a provided ValueSet:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">diabetes_conditions</span> <span class="o">=</span> <span class="n">spark</span><span class="o">.</span><span class="n">sql</span><span class="p">(</span><span class="s">"""</span>
</span><span class='line'><span class="s">select id condition_id,</span>
</span><span class='line'><span class="s"> subject.reference person_ref,</span>
</span><span class='line'><span class="s"> coding.system,</span>
</span><span class='line'><span class="s"> coding.code,</span>
</span><span class='line'><span class="s"> coding.display</span>
</span><span class='line'><span class="s">from condition</span>
</span><span class='line'><span class="s"> lateral view explode(code.coding) nested as coding</span>
</span><span class='line'><span class="s">where in_valueset(code, 'diabetes_risks')</span>
</span><span class='line'><span class="s">"""</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<table>
<thead>
<tr>
<th></th>
<th align="left">condition_id </th>
<th align="left">person_ref </th>