社内LTやって1年半が経ちました。

こんにちは!入社4年目、 女性 システムエンジニアのはまじですヾ(o´▽`)ノ
半年前からプライベートで動画配信をはじめて、なかなか調子が良さそうなのでそろそろYouTuberになろうかなぁとか思ってたり思ってなかったりする今日この頃です(o´▽`o)

会社では、アプリのサーバーサイドエンジニアとして開発業務を行う傍ら、 開発合宿や社内LT等、開発部署内のイベントの企画・運営も行っております。

今回はその中から開発部署の社内LTについてお話ししようと思います(´∀`*)。・゚+

f:id:AdwaysEngineerBlog:20170922132934j:plain

やることになったきっかけ


以前、1週間に1回知見を共有する会議があったのですが、某テクニカルマネージャーが、

「最近人数が多くなってきて発言しにくい感あるから、会議やめて、定期的にもっと気軽に技術情報を共有出来る場所をつくった方がええ気がしてきたな…。
あ、せっかく大きい会議室空いたし、LTでもやろうぜ。
その方が会議より気軽に話せるし!プレゼンの練習にもなるし!
え、それでええやん、うん、それがえry(ブツブツ…(1人で))」

的なノリで第1回を開催したのがきっかけだそうです。

現在は若手運営メンバーも増え、 情報共有・コミュニケーション・プレゼンの練習を目的に、 “毎月必ず開催する。” ことをルールとして運用しています。 (1回でもやらないとすぐやらなくなっちゃうので。)

内容


テーマ

f:id:AdwaysEngineerBlog:20170922133110p:plain

基本的にはありません。みんなのためになるような話であればOK。
少しマンネリ化してきたときは、開発部署内でテーマを募集して、テーマありでやったりします。

テーマ例

  • 「し○じり先生~俺みたいになるな~」
    • 後輩たちが自分と同じ失敗をしないよう、ベテランの大先輩方から過去の失敗経験を元にありがたい教訓をいただく会です。(これはとても盛り上がりました。)
  • 「Adways0○7『この秋に読んでほしい本』」
    • 自分が読んだ本の中で、是非読んでほしい!という本を紹介し、プレゼンする会です。(来月開催予定)

等々、某テレビ番組から拝借させていただいているネタばかりなのですが、 できるだけキャッチーなテーマにしてみんなが楽しめるようなテーマを日々模索しております。

発表時間

7分 + 質問2、3分。 はじめは5分だったのですが、"情報共有するには5分では足りない"ということで7分に変更しました。 どうしてもたくさん話したい!と言う方にはメイントーク枠もあります。 (発表15分~20分 + 質問5分ぐらい。)

事前準備


  • 発表者を集める
    • 運営担当者が声をかけに行く or 声をかけてもらう
    • やりたいって言いにくいシャイな人もいるかもしれないので、gitlabのissue登録からも応募できるようになっております。

f:id:AdwaysEngineerBlog:20170922133146p:plain

f:id:AdwaysEngineerBlog:20170922133204p:plain

issueが登録されたらslackに通知が飛ぶようにし、登録後すぐに声をかけに行きます。

  • 当日に出す飲み物、お菓子を買う(買いに行くの面倒なのでamazonで購入)
  • ATNDのページを作り観覧者を募る

当日の流れ


会場設営

前説
前説担当の人が台本を考えてきて、発表者が発表しやすいよう、場をあたためるようなとっておきのネタを話します。

発表
見逃してしまった人も見れるように動画撮影します。退勤している人はお酒を飲みながら参加するのも可。

投票+結果発表

投票


発表終了後、会場内にいる人でgoogleアンケートで投票します。得票数が1番多かった人がベストトーク賞 を受賞し、旗が授与されます。

半年に1回、「べすと おぶ べすと決定戦!」という、過去半年間でベストトーク賞を獲得した人の中から、NO.1を決める会もありますヽ(`・ω・´)ゝ

そこでベストトーク賞に輝くとお偉い方々から素敵なプレゼントがもらえたり…!!

発表例


  • CDNについて f:id:AdwaysEngineerBlog:20170922133229j:plain

  • フォントについて語ります f:id:yumi_h_7319_test:20170922103244j:plain

  • 動画編集用プラグイン(Particular)を実際に使ってみた話。 f:id:AdwaysEngineerBlog:20170922133256j:plain

  • 魔法のコード (Ruby大好き久保田君は大体consoleを開いて実演をしています。) f:id:AdwaysEngineerBlog:20170922133313j:plain

  • 海外へカンファレンスに参加したときの情報共有 f:id:AdwaysEngineerBlog:20170922133329j:plain

  • 入社してから学んだこと f:id:AdwaysEngineerBlog:20170922133340j:plain

  • 新年度なのでちょっとエモい話~達人プログラマー第二版より~ f:id:AdwaysEngineerBlog:20170922133350j:plain

等々、業務で学んだことから自分が興味のあることまで、 思い思いの発表方法でプレゼンをします(●ノ▽`)ノ

やってよかったこと


  • 入社前に学んだことを知ることができる。
    • 前の職場ではこんなことしてた、大学でこんな研究してた、等。
  • 発表の準備をキッカケに勉強する
  • アピールの場にもなる
    • 得意なこと、こんなこと勉強してます、等。
  • 仕事で関わらない人とも会話するキッカケができる。
  • 自分が行けなかったカンファレンスの話しを聞くことができる
  • 他の部署がどんなことをしているのかわかる

今後改善したいこと


  • 盛り上がってる感が出にくい
    • みんなちょいちょいリアクションするけど、控えめで盛り上がってる感が出にくいので、もっとリアクションしやすい環境をつくりたい(改善策実施中)
  • 発表者の固定化
    • バラけるようにはしているけど、発表者が固定化されてきているので、もっといろんな人が発表しやすいような環境をつくりたい

社内LTをする際の参考に少しでもなればなと思います。 改善策をを試した結果はいつか当ブログの編集者である奥村君が投稿してくれると思います。 ではでは(o´ω`o)♪

VagrantとAnsibleでScalaの環境構築

こんにちは!入社2年目、広告サービスチームの山﨑です!
この頃ダイエット食品試しまくって5kg痩せました!!!毎日がリバウンドの恐怖&食欲との戦いです!☆
そんな私は業務ではずっとPerl を使って開発をしていたのですが、今後Scalaを導入していくということで環境構築を行いました。
実際は手動で行ったのですが、VagrantとAnsibleを使ったことがなかったのでこの二つを使ってもう一つ環境を作ってみました!

環境

ansible実行ホスト

  • CentOS7.3
  • Ansible 2.3.2.0

セットアップ対象

  • CentOS7.3

仕事で使用しているPCがWindowsでAnsibleを簡単に実行できないのでLinuxの仮想マシンを2つ用意しました。

VagrantでCentOS7 インストール

$ mkdir centos

Vagrantfileを作成
$ vagrant init CentOS7/

ネットワーク、共有フォルダ設定を追記
$ vim Vagrantfile

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.vm.network :private_network, ip: "192.168.33.10" #任意のip
  config.vm.synced_folder ".", "/vagrant", type: "virtualbox" 
end

$ vagrant up

$ vagrant ssh

Windows環境だとrsyncが見つからないよとエラーがでたので
config.vm.synced_folder ".", "/vagrant", type: "virtualbox"
を追記しました。
Windowsのコマンドプロンプトではsshログインできないので、ssh接続できるツールを使用してください。今回は同期におすすめされたGit Bashを使っています!

これでCentOSのインストールは完了です!

Ansible

今回作成したplaybookがこちら!

- hosts: all
  become: yes
  tasks:
    - name: install common package
      yum: name={{ item }}
      with_items:
        - unzip
        - wget

    - name: download JDK
      get_url:
        url: http://download.oracle.com/otn-pub/java/jdk/8u144-b01/090f390dda5b47b9b721c7dfaa008135/jdk-8u144-linux-x64.rpm
        headers: "Cookie:oraclelicense=accept-securebackup-cookie"
        dest: /home/vagrant/jdk-8u144-linux-x64.rpm

    - name: import rpm
      yum:
        name: /home/vagrant/jdk-8u144-linux-x64.rpm
        state: present

    - name: get Scala
      get_url:
        url: http://downloads.typesafe.com/scala/2.11.7/scala-2.11.7.tgz
        dest: /home/vagrant/

    - name: unarchive scala.tgz
      unarchive:
        src: /home/vagrant/scala-2.11.7.tgz
        dest: /home/vagrant
        remote_src: True

    - name: scala path
      become: False
      lineinfile:
        path: /home/vagrant/.bash_profile
        regexp: 'export PATH%'
        insertbefore: 'export PATH'
        line: 'export PATH=$PATH:/home/vagrant/scala-2.11.7/bin'

実行!

$ ansible-playbook -i hosts main.yml

完了してscalaコマンドを打つと、scalaconcoleが立ち上がるはずです!!
ではではそのまんまって感じなのですが実行内容を解説させて頂きます!

install common package

必要なパッケージをインストール

download JDK & import rpm

scalaを動かすのに必要なJDKのダウンロードです。サイトを見ていただくと分かるのですが、ラジオボタンでライセンス認証を行わなければなりません。 CUIから行うにはCookieのオプションをつけてあげればダウンロードできます!

get Scala & unarchive scala.tgz

Scalaのインストール。バージョンは適宜選択してください。 任意のパスに解凍します。

scala path

パスを通す為に.bash_profileに scala.taz を解凍したパスを追記します。

まとめ

本当はActivatorやIntelliJをインストールするところまでいきたかったのですが・・・今後の展望と致します。
途中エラーがでまくったりしてましたが、Ansibleを実行して全部のtaskが上手くいくととっても気持ちよいですね!
最後まで読んで頂きありがとうございました!

jsxでデザイナー向けにphotoshopデータのチェッカーを作った

こんにちは、相原です。

自分がデザイナー出身ということもあり、
どうにかデザイナーの作業を効率化出来ないかと考え、チェッカーを作ってみました。

photoshopでデザインを作り込んでいるとレイヤー数が増え、
また不要なレイヤーを消し忘れて非表示にしたまま放置している人が多いかと思います。
そんな時に自動で非表示のレイヤーを探し、確認あるいは削除してくれるチェッカーです。

JSXとは

JavaScriptでPhotoshopを制御するファイルのことを「JSX」といいます。
昔からPhotoshopに搭載されていて、機能追加や自動化をすることが出来ます。

チェッカーの主な機能

非表示のまま放置しているレイヤーがあるとします。
レイヤー
f:id:AdwaysEngineerBlog:20170907153755p:plain

(いるレイヤーまで1個非表示になっちゃってますね)

ファイル > スクリプト > 参照 でチェッカーのjsxファイルを読み込みます。
読み込み
f:id:AdwaysEngineerBlog:20170907153811p:plain

するとチェックが始まり、アラートが表示されます。
削除対象
f:id:AdwaysEngineerBlog:20170907153833p:plain

削除方法
f:id:AdwaysEngineerBlog:20170907153847p:plain

■手動で削除
そのまま終了するか、対象のレイヤーに黄色のカラーラベルをつけるか選択できます。
画像はカラーラベルをつけたものです。
これでどのレイヤーが削除対象か分かり易いですね。
ラベル付き
f:id:AdwaysEngineerBlog:20170907154637p:plain

■1つずつ確認
非表示のレイヤー1つずつアラートで確認し、削除したいものだけ「はい」を押すと削除されます。
削除確認
f:id:AdwaysEngineerBlog:20170907154648p:plain

■一括削除
非表示のレイヤーは自動ですべて削除されます。

コード

カラーラベルの付け方はこちらのサイトを参考にしています。

var document;
var targetCnt = 0; // 削除対象のレイヤーを数える変数
var howToDeleteFlg; // 0=手動, 1=確認, 2=一括

function start(){
  alert('チェックを開始します。');
  document = app.activeDocument;
  searchLayer(document.layers);
  if(targetCnt == 0){
    alert('削除対象のレイヤーがないので終了します。');
    return; // 削除対象がなければ終了する
  }
  howToDelete(document.layers);
  alert('チェックを終了します。');
}

// 非表示レイヤーの検索 -------------------->
function searchLayer(obj){
  var i;
  switch(obj.typename){
    case "Layers":
      var visiblities = [];
      for(i = obj.length - 1; i >= 0; i--){
        var rep = searchLayer(obj[i]);
        if(rep == false) targetCnt++;
      }
      break;
    case "LayerSet":
      if(!obj.visible){
        processingBranch(obj);
        return false;
      }
      for(i = obj.layers.length - 1; i >= 0; i-- ){
        var rep = searchLayer(obj.layers[i]);
        if(rep == false) targetCnt++;
      }
      break;
    default:
      if(!obj.visible){
        processingBranch(obj);
        return false;
      }
      break;
  }
}

// 削除方法選択用のダイアログ -------------------->
function howToDelete(obj){
  alert('削除対象のレイヤーが' + targetCnt + '個あります。');
  deleteWin = new Window("dialog", "削除方法を選択してください。");
  manualBtn = deleteWin.add("button", { width: 150, height: 25, x: 25, y: 25 }, "手動で削除");
  confirmationBtn = deleteWin.add("button", { width: 150, height: 25, x: 115, y: 25 }, "1つずつ確認");
  bulkBtn = deleteWin.add("button", { width: 150, height: 25, x: 205, y: 25 }, "一括削除");
  manualBtn.onClick = function(){
    howToDeleteFlg = 0;
    deleteWin.close();
    var result = confirm('カラーラベル(黄色)で印をつけますか?');
    if(result) searchLayer(obj); // カラーラベルをつける処理へ
  }
  confirmationBtn.onClick = function(){
    // 1つずつ確認する処理へ移動
    howToDeleteFlg = 1;
    deleteWin.close();
    searchLayer(obj);
  }
  bulkBtn.onClick = function(){
    var result = confirm('本当に一括削除してよろしいですか?');
    if(result){
      // 一括削除する処理へ移動
      howToDeleteFlg = 2;
      deleteWin.close();
      searchLayer(obj);
    }
  }
  deleteWin.show();
}

// 削除方法が手動、確認、一括かによって処理の分岐 -------------------->
function processingBranch(obj){
  if(howToDeleteFlg == 0){
    app.activeDocument.activeLayer = obj;
    var util = new PSLayerUtil();
    util.setLayerColor(PSLayerUtil.LayerColors.None);
    util.setLayerColor(PSLayerUtil.LayerColors.Yellow);
    return false;
  }else if(howToDeleteFlg == 1){
    confirmationDelete(obj);
    return false;
  }else if(howToDeleteFlg == 2){
    obj.remove();
    return false;
  }else{
    return false;
  }
}

// レイヤーの選択 -------------------->
function selectLayer(obj){
  app.activeDocument.activeLayer = obj;
  obj.visible = false;
}

// カラーラベル設定 -------------------->
var PSLayerUtil = function(){
  this._colorRef = new ActionReference();
  this._colorRef.putEnumerated(charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));
}
PSLayerUtil.LayerColors = {
  Yellow: 'Ylw ',
  None: 'None'
};
PSLayerUtil.prototype = {
  _colorRef: null,
  setLayerColor: function(layerColor) {
    var colorDescriptor = new ActionDescriptor();
    colorDescriptor.putEnumerated(charIDToTypeID('Clr '), charIDToTypeID('Clr '), charIDToTypeID(layerColor));
    var desc = new ActionDescriptor();
    desc.putReference(charIDToTypeID('null'), this._colorRef);
    desc.putObject(charIDToTypeID('T   '), charIDToTypeID('Lyr '), colorDescriptor);
    executeAction(charIDToTypeID('setd'), desc, DialogModes.NO);
    return this.layerColor();
  },
  layerColor: function() {
    var desc = executeActionGet(this._colorRef);
    var charID = typeIDToCharID(desc.getEnumerationValue(charIDToTypeID('Clr ')));
    for(var key in PSLayerUtil.LayerColors) {
      var value = PSLayerUtil.LayerColors[key];
      if(value === charID) return key;
    }
    return 'None';
  },
}

// 削除方法が1つずつ確認する場合のダイアログ -------------------->
function confirmationDelete(obj){
  selectLayer(obj);
  var result = confirm('削除対象【' + obj.name + '】を削除しますか?');
  if(result){
    obj.remove();
  }
}
start();

さいごに

jsxは少し特殊な書き方もしますが、簡単に自動化出来るので活用していけそうです。
このチェッカーも2時間半ほどで作れました。
今後もデザイナーの作業を効率化出来るようなものを作ってみたいと思います╰(✿´⌣`✿)╯

ファイアウォール、Slackからでも対応できる?!

はじめまして、中川です。 3年目ということもあって、丁度自分の立ち位置が分からない時期にさしかかり、日々迷走しております。

早速ですが、皆様の企業では、どのFWを使用して社内ネットワークを守っていますでしょうか?
また、どのようなクラウドサービスを利用しておりますでしょうか?

弊社では、Paloalto社のPAシリーズを使用しております。
また、利用しているクラウドサービスの1つにAWS EC2があります。
AWS EC2への通信許可設定はFW上で行っていますが、
「AWSって次々とIPアドレスレンジ増やしていくから大変っっ(◎_◎;)」でした・・

そこで、“panxapi”という便利なAPIを利用したscriptを活用した事で【大変】が解消されたので、
今回は"panxapi"とは何か、弊社での活用方法を簡単に説明させて頂きます。

■"panxapi"とは・・・・

簡単に言うと、"FWにログインしなくても、コマンド上から設定編集したり、情報収集出来るPaloalto限定の便利ツール"です。

■どのような【大変】を抱えていたのか・・・

  1. 弊社ではAWS EC2への通信許可設定をFW上で行っておりますが、皆さんもご存知のように
    AWSは次々と新しいIPアドレスレンジが追加されたり、新リージョンが出来たり、時にはIPアドレスレンジの変更・削除もあります。
    その度にFW上にIPアドレスレンジ追加して、アドレスグループに追加してました。
    ↑この次々とあるのが、FW上で通信許可設定を行ってる身からしたら結構手間・・・(地味に時間がかかる)

  2. 例えば休日等にエンジニアが新しくサーバを立てて、そのサーバがまだFWに追加設定していない新しいIPアドレスレンジの中からIPを取ってしまったら・・
    折角休日にサーバ立てても作業出来ません・・通信許可設定してよ~。と言われてもこちらが出先だったら?勿論対応出来ません。

何とか解消出来ればな~・・・・

そこでリスペクトしていた元上司からこんな提案がありました。


【slackならスマホにも入れてるから、slackからFWへ追加設定出来る様にしよう!!!!】


(と同時に既にscriptもほぼ作り上げていました( ̄д ̄)!!)

まずslackから対応出来るようにする為のscriptを作成する前に運用ルールを考えました。

■ルール

slackから対応出来る様、"bot_palo"というslack botを用意し、
そこから追加分のIPアドレスレンジの確認や追加設定を行う。
ただし、slackから追加設定出来るのは、あくまでも【既存リージョンへのIPアドレスレンジ追加のみ】
新リージョン、IPアドレスレンジの変更・削除は今まで通り手動で行う。

では、次にこのルールを踏まえて作られたscriptの追加設定までの流れを説明します。

■説明

  1. Amazon公式サイトに掲載されているAWS EC2の使用IPアドレスレンジとFWに設定されているIPアドレスレンジ情報をpanxapiを使い、情報を引っ張ってきて比較
  2. 比較し、出た差分情報(追加が必要なIPアドレスレンジ)を中川にメール通知(既存リージョンへのIPアドレスレンジ追加なのか新リージョンなのか、変更・削除なのかまで出す)
  3. slack上で"bot_palo ck"と打つと今回の対象分(既存リージョンへの追加IPアドレスレンジ)を確認できる
  4. “bot_palo set"と打つと、FWへ設定が入る(panxapiを使って追加処理を動かす

実行例

bot_palo ck

f:id:AdwaysEngineerBlog:20170901125049p:plain

bot_palo set

f:id:AdwaysEngineerBlog:20170901130002p:plain`

これにより出先からでも対応出来る様になり、またいちいちFWにログインして、IPアドレスレンジを登録して、アドレスグループに入れて・・・とやらなくても
ささっとslack上から設定する事が出来るので手間も省け、この作業に費やす工数を減らすことが出来ました!!!!!!!

今回は細かいscriptの内容まで書くことはできませんでしたが、
今後もpanxapiを利用して出来る事があれば、チャレンジしていきたいと思っております。

Mackerel Plugin Hackathon #1 Tokyo に 参加した話

こんにちは、久保田です。

先週の土曜日(8/19)に「Mackerel Plugin Hackathon #1 Tokyo」に参加して参りました。

mackerelio.connpass.com

人生初ハッカソンだったのですが、楽しく過ごせたので、どんな感じだったのか、つらつらと書いていきたいと思います。

説明/アイディアソン

まず、13時に今回の会場であるVoyageさんのオフィスに集合し、はてなのsongmuさんから今回のテーマであるMackerelのpluginについてのお話がありました。

プラグインには

  • メトリックプラグイン
  • チェックプラグイン
  • メタデータプラグイン

があり、それぞれデモを交えて説明していただきました。
とてもわかりやすかったです。
今までメトリックプラグインしか作ったことがなかったので、色々できることが増えそうでわくわくでした。

そしてその後、近くの人とグループになり、アイディアを出し合いました。
みなさんいろいろなアイディアがあるようで、かぶらないものを探すのに必死でした。笑

実装

14時からは各自実装でした。
17時までと3時間しかないため、まだ何を作るか迷っていた僕は結構焦っていました。

はてなのスタッフの方々が質問にも答えてくださるので、大変心強かったです。

みなさん各々実装していたので、とても集中して作ることができました。

最初はgoで作ろうと思ってたのですが、時間もなく、僕はメタデータプラグインを作っていたので、最終的にはRubyで実装しました。

成果発表

あっという間に3時間が過ぎ、成果の発表になりました。
みなさん時間内でしっかり成果を出していて、驚きました。

僕が一番驚いたのは、jsonを与えるとスキーマいらずで良い感じにmackerel-agentが求める必要な形に成形してくれるプラグインでした。
ぜひ今度コードを読んでみたいなと思いました。

そんな僕は「ホストに入っているプログラミング言語のバージョン」をメタデータとして登録するプラグインを作成しました。

これがあれば、脆弱性があるバージョンの言語を入れていたりサポートが終わった言語を使っているホストを特定できるな、と考え作りました。

github.com

まとめ

その後懇親会があったようですが、僕は私用があり先に帰らせていただきました。
みなさんそれぞれの多種多様なアイディアがあり、エンジニアとしてとても刺激になりました。
また、初めてのハッカソンでしたが、短い時間で1つ作りあげることができ、とてもいい時間でした。

機会があれば参加したいなと思います。

素晴らしい機会を提供していただいたはてなの皆様、ありがとうございました。