午前6時——
携帯電話(ブブブブ、ブブブブ
続きを読む
Azure Resource Usage APIで課金情報を取得する
BY | コメントをどうぞAzureの課金APIがリリースされていたので触ってみました。
Microsoft Azure リソースの消費を把握する
https://azure.microsoft.com/ja-jp/documentation/articles/billing-usage-rate-card-overview/
Azure Billing REST API Reference (Preview)
https://msdn.microsoft.com/library/azure/1ea5b323-54bb-423d-916f-190de96c6a3c
手順
- Azure AD applicationの作成 と アクセストークンの作成
- DHCでリクエストを実行
AngularJS 自作ディレクティブ集
BY | コメントをどうぞシンプルなものがほとんどですが、今後も使えそうなものもあるので備忘録として載せておきます。
imgタグをsvgに置き換える
svgクラスが付加されたimgタグをsrcに指定されたsvgに置き換えます。CSSの疑似クラスを使ってsvg内の要素に効果を付けたい時などに使えます。(注:jQueryのロードが必要です)
.directive('img2svg', function($http){
return {
restrict: 'EA',
link: function(scope, elm, attrs){
$this = $(elm);
$this.find('img.svg').each(function(){
var $img = $(this);
var imgURL = $img.attr('src');
$http.get(imgURL, {cache:true}).success(function(data) {
var $svg = $(data)[4];
$img.replaceWith($svg);
}, 'xml');
});
}
}
})
サンプル:
<div img2svg>
<img class="svg" src="hoge.svg">
<img class="svg" src="piyo.svg">
</div>
特定のイベントを受け取った時に要素にフォーカスを移す
属性値に指定したイベントを要素が受け取った時にフォーカスを移します。
.directive('focusOnEvent', ['$timeout', function($timeout) {
return {
restrict:'A',
link: function(scope, element, attrs) {
scope.$on(attrs.ngFocusOnEvent, function(){
$timeout(function() {
element[0].focus();
});
});
}
};
}])
サンプル:
HTML
<body ng-app="sample" ng-controller="SampleCtrl as sample">
<button ng-click="sample.trigger('btnClicked')">フォーカスを移す</button>
<input type="text" ng-focus-on-event="btnClicked">
</body>
Controller
.controller('SampleCtrl', ['$scope', function($scope){
this.trigger = function(event){
$scope.$broadcast(event);
}
}]);
指定した値(モデル)と同じ値を持たないかチェック
バリデーション用のディレクティブです。ディレクティブを付与した要素のモデルの値とディレクティブで指定したモデルの値が一致しないかチェックします。
.directive('notSame', function(){
return {
require: 'ngModel',
link: function(scope, $element, attrs, ctrl){
var validator = function(viewValue) {
var targetVal = scope.$eval(attrs.notSame);
if(!viewValue) return viewValue;
if(viewValue == targetVal){
ctrl.$setValidity('notSame', false);
return viewValue;
}else{
ctrl.$setValidity('notSame', true);
return viewValue;
}
}
ctrl.$parsers.unshift(validator);
ctrl.$formatters.unshift(validator);
}
}
})
サンプル:
<div ng-form="form" ng-init="text1='hoge'; text2='hoge'">
<input type="text" ng-model="text2" not-same="text1" name="textInput2">
<span ng-show="form.textInput2.$error.notSame">エラー</span>
<input type="text" ng-model="text3" not-same="'piyo'" name="textInput3">
<span ng-show="form.textInput3.$error.notSame">エラー</span>
</div>
指定した値(モデル)以上かチェック
バリデーション用のディレクティブです。ディレクティブを付与した要素のモデルの値が指定した値以上かチェックします。不等号を変えれば以下や未満などもできると思います。
.directive('greaterEqual', function(){
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, $element, attrs, ctrl){
var validate = function(viewValue) {
var targetVal = scope.$eval(attrs.greaterEqual);
if(viewValue === undefined || viewValue.length == 0) {
ctrl.$setValidity('greaterEqual', true);
return viewValue;
}
if(viewValue < targetVal || !isFinite(viewValue)){
ctrl.$setValidity('greaterEqual', false);
return viewValue;
}else{
ctrl.$setValidity('greaterEqual', true);
return viewValue;
}
};
ctrl.$parsers.unshift(validate);
ctrl.$formatters.unshift(validate);
}
}
})
ブラウザのリサイズ時に何か処理を行う
サイズ変更時にブラウザが発生させるイベントを拾って属性値に指定したイベントハンドラを実行します。また、スコープにイベントを通知します。
.directive('resize', ['$rootScope', '$window', '$timeout', function($rootScope, $window, $timeout){
return {
restrict: 'EA',
scope: {
resize: '&'
},
link: function(scope){
var timer = false;
angular.element($window).on('load resize', function(e){
if(timer) $timeout.cancel(timer);
timer = $timeout(function(){
scope.resize();
}, 200);
});
}
}
}]);
サンプル:
HTML
<body ng-app="sample" ng-controller="SampleCtrl as sample"> <div resize="sample.resizeHandler()"></div> </body>
Controller
.controller('SampleCtrl', ['$scope', function($scope){
this.trigger = function(event){
$scope.$broadcast(event);
}
this.resizeHandler = function(){
alert('リサイズされました');
}
}]);
バリデーションエラーをUI Bootstrapのtooltipに表示させる
以前の記事をご覧ください。
AWSのVPCの予約IPについての勘違い
BY | コメントをどうぞAWSで中にサブネットを複数持つVPCのIPについて勘違いしていたので書きます。
サブネットを作成するとCIDRの最初の4つ(正確には3つ?)最後の1つはAWS側で予約されているので
使えないのはAWSを利用している方ならご存知かと思います。
例えば192.168.0.0/24のCIDRのサブネットの場合、
●192.168.0.0はネットワーク全体を表すのでAWSだからとでなく使えません。
●192.168.0.1はAWS側で予約で使えません。
●192.168.0.2はAWS側で予約で使えません。
●192.168.0.3はAWS側で予約で使えません。
●192.168.0.254はAWS側で予約で使えません。
で、実際に使ってみるとどうやら、
●192.168.0.1はゲートウェイIPになっている模様。
●192.168.0.2はDNSになっている模様。
●192.168.0.3は何やってるかわからない。
●192.168.0.254は何やってるかわからない。
一般的にアドレスの一番最初は大抵DNSとかゲートウェイとかDHCPにしている場合が多いので
納得いきます。最後の1つもゲートウェイにしている場合が多いので納得いきます。
で、サブネットを二つ持つVPCでも各サブネットごとにAWSは予約IPが同じようにあります。
公式サイトにも以下のように書いてあります。
Important AWS は、各サブネット CIDR ブロックの最初の 4 つの IP アドレスと最後の IP アドレスの両方を 予約します。これらのアドレスをユーザーが使用することはできません。 たとえば、CIDR ブロック 10.0.0.0/24 を持つサブネットの場合、 IP アドレス 10.0.0.0、10.0.0.1、10.0.0.2、10.0.0.255、 および 10.0.0.3 が予約されます。 http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_Subnets.html
なので、サブネットを2つ持つVPC、例えば、
ゾーンA:192.168.0.0/25
ゾーンB:192.168.0.128/25
の場合は、
ゾーンAは、192.168.0.0,192.168.0.1,192.168.0.2,192.168.0.3,192.168.0.127
ゾーンBは、192.168.0.128,192.168.0.129,192.168.0.130,192.168.0.131,192.168.0.254
はAWS側で予約されていて使えません。実際に使ってみた経験から、
ゾーンAのゲートウェイは192.168.0.1
ゾーンBのゲートウェイは192.168.0.129
になると推測出来き、実際に確認するとその通りになっています。
次にDNSはこれまでの経験から、
ゾーンAのDNSは192.168.0.2
ゾーンBのDNSは192.168.0.130
と推測出来ます。そして実際に確認すると・・・
ゾーンAのDNSは192.168.0.2
ゾーンBのDNSは192.168.0.2
・・・?ゾーンBにいるのにゾーンAのIPのDNSに聞きにいってる。。
ここで以下の疑問がわきます。
●ゾーンBにいるサーバが名前解決するのにゾーンAのDNSに聞きに行くのは距離が離れている分遅くなるのではないか?
●ゾーンAとゾーンBで冗長化している場合はゾーンAが落ちたらゾーンBのサーバも名前解決出来なくなるではないか?
●ゾーンBの192.168.0.130は何やってるの?DNSじゃないの?
色々ドキュメントを漁る。グーグル先生に聞く。自分であれこれコマンド実行で調べる。
・・・をやってみましたがわかりませんでした。
わからないのでAWSサポートに聞きました。で、回答はこんな感じでした。
DNSはVPCのCIDRの2番目のアドレスです。
そうなんですか。各サブネットごとに存在するのかと思っていました。予約されているし。
でもVPCのCIDRの2番目のアドレスのみなら遠回りの問題とDNSが存在するゾーンが拠点障害
起きたらまずいのかと・・・。
それに対して以下の回答が。
DNSサーバーは冗長化されていて 特定のVPC サブネット上に 配置されたものではありません。 Availability Zone で機能します。 DNS の IP アドレスは仮想的なものとご理解下さい。
だそうです。見かけ上は192.168.0.2に対してゾーンBから名前解決しているように見えても
同じゾーン内にあるDNSに問い合わせいってるとの事です。
自分と同じ勘違いをしている人もいるかもしれませんので共有します。
ゾーンAの192.168.0.2とDNSの仮想IPの192.168.0.2でかぶってるけどどう処理してるんだろう?とかゾーンBからの192.168.0.2のパケットはゾーンB内のIPに変換されているのだろうか?
とか、予約されているIPは何に使われているのだろうか?
などは今もわかりませんが。。(最初のIPはほぼほぼゲートウェイとは思います。)
Amazon SES 利用時、最大送信レート制限に引っかからない方法を考える
BY | コメントをどうぞAmazon SES 利用時、何も考えずメールを大量送信していると以下のようなエラーが出ることがあります。
Maximum sending rate exceeded
最大送信レートを超過したぞ、というエラーメッセージです。
最大送信レートとは
SESのドキュメントには以下のようにあります。
AWS RDSのログ監視をZabbixで。
BY | コメントをどうぞAWSのRDSはCLIツールでログの取得が出来きるのでZabbixサーバにRDSのログを取得して通常のログ監視設定と似たような感じで監視をします。ZabbixでRDSのログ監視をするには以下の条件が必要になります。
● RDSのログを取得できる権限(IAM)を持っていること。
● CLIツールを導入していること。
正確にはCLIツール無くてもプログラム書ける人ならとってこれるようですが、自分のような非プログラマでもAPIにアクセスしてデータを取得できるCLIツールをリリースしてくれているので使わない手は無いです。
CLIツールは複数の言語版がありますが、JAVA版とPython版を使います。
何故2種類使うのか?となりますが、前にJAVA版で色々とCLIツールで監視データ取得したりバックアップ運用していたのですがJAVA版は重いのです。t2.microでZabbixを動かしていたのですが、CLIを使ったスクリプトを複数個動かすとCPULoadがかなり高くなってました。t2.microでZabbixを動かす事自体問題あるのですが、ブラウザでのアクセスは反応遅いけどもその状態で1年くらいZabbixが落ちたりもせずAWSの障害通知メールも飛ばしてくれてたので放置してましたが、去年の4月にチーム編成が変わって同じチームになった人から「Python版使ってますが重いと感じたことないですけど?」と言われて試してみたら「本当だ軽い・・・」今まで使ってたスクリプトをPython版に書きなおして現在に至るまでZabbixサーバが重くなったことはありませんでした。
AmazonLinuxには最初からPython版CLIツールがセットアップされてるくらいだしPython版のみで行こう!
・・・と思ったらログをtail出来る機能がJAVA版にはあったけどpython版はやり方がわからない。もしくは無いかもしれない。。
(aws-cli/1.3.18 Python/2.6.6のバージョンではよくわからなかった。)
その為、いつかPython版でRDSのログtailの方法がわかったらいつでも全部Python版に変更出来る用に最初の部分はPythonコマンドで実行してtailの部分はJAVA版で実行しています。
● Python版CLIインストール
AmazonLinuxなら最初から入っていますが、CentOSではインストールします。yumで入るので楽です。
# yum install python -y # yum install python-devel -y # yum install python-setuptools -y # easy_install pip # pip install awscli
次に認証に使うファイルが必要なので作成します。AWSのアクセスキーとシークレットアクセスキーを中に記述します。リージョンはRDSが動いているところにします。ファイル名はアカウント/サービスごとに分けると後で楽です。
# vi 任意の名前 [default] aws_access_key_id=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX aws_secret_access_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX region=ap-northeast-1
認証ファイルの場所を設定します。
# export AWS_CONFIG_FILE=任意の名前で作成したファイル
コマンドのタブ補完が効かないので効くようにします。毎回補完出来るように.bash_profileに書いておくのも良さそうです。
# complete -C aws_completer aws
セットアップがうまく行ったかか確認します。ログファイルがずらっと表示されればうまく行っています。
# aws rds describe-db-log-files --db-instance-identifier RDS名 --output text UNIXエポック ファイル名 DESCRIBEDBLOGFILES 1425877196000 error/postgresql.log.2015-03-09-04 4470072 DESCRIBEDBLOGFILES 1425880791000 error/postgresql.log.2015-03-09-05 5148177 DESCRIBEDBLOGFILES 1425884399000 error/postgresql.log.2015-03-09-06 581115 DESCRIBEDBLOGFILES 1425887996000 error/postgresql.log.2015-03-09-07 105250 DESCRIBEDBLOGFILES 1425888531000 error/postgresql.log.2015-03-09-08 36301
「–output」で指定した形式で表示してくれます。「table」と指定するとteble形式、「text」と指定するとテキスト形式で表示してくれます。何も指定しないと「json」形式で表示されて見にくいです。(jqとかかまさないと見づらい)
● JAVA版CLIセットアップ
JAVA版CLIのセットアップ方法はこのブログでも他の人が紹介されているので省略します。(手抜き)
RDSのログをtailするだけだとAWS側で定期的(1時間ごと?)にローテされて見失うので一定間隔で
ログが新しくなったかチェックして最新のログを吐き出すスクリプトを作成します。
●RDSログをtailするスクリプト
#!/bin/sh # EC2-APITools settings export JAVA_HOME=/usr # keys export AWS_CREDENTIAL_FILE=クレデンシャルファイルのPATH export AWS_CONFIG_FILE=configファイルのPATH # RDS CLI setting export AWS_RDS_HOME=/usr/local/rds export EC2_REGION="ap-northeast-1" export PATH=$PATH:$JAVA_HOME/bin:$AWS_RDS_HOME/bin COMMAND=スクリプトの絶対PATH DBINSTANCEID=RDSの名前 LOGDIR=ログを保管するPATH LOG=`aws rds describe-db-log-files --db-instance-identifier $DBINSTANCEID --output text| awk '{ print $2"\t"$3"\t"$4 }' | awk '{print substr($0,1,length($1)-3)"\t"$2"\t"$3}' | awk '{ print strftime("%Y/%m/%d %H:%M:%S",$1)" "$2" "$3 }' | tail -1 | awk '{print $3}'` LOGFILENAME=`echo $LOG | sed 's/[a-z]*\///g'` rds-watch-db-logfile $DBINSTANCEID --log-file-name $LOG > ${LOGDIR}/$LOGFILENAME 2>&1 & C=0 while [ $C = 0 ] do LOG2=`aws rds describe-db-log-files --db-instance-identifier $DBINSTANCEID --output text| awk '{ print $2"\t"$3"\t"$4 }' | awk '{print substr($0,1,length($1)-3)"\t"$2"\t"$3}' | awk '{ print strftime("%Y/%m/%d %H:%M:%S",$1)" "$2" "$3 }' | tail -1 | awk '{print $3}'` if [ $LOG != $LOG2 ];then pgrep -f $LOG | xargs kill -9 $CMDPATH fi sleep 300 done
AWS側のローテはおそらく一時間に一回くらいのようですが、スクリプト内では5分に一回チェックして
新しくなったら新たにログファイルを作り直してtailするようにしています。
このスクリプトをバックグラウンドで動かしっぱなしにして
あとはこのログをZabbixでログ監視すればRDSのログ監視が可能になります。
問題点として、古いファイルを消すようにしていないのでローテ後のログファイルが溜まっていく事と、
JAVAのCLIはやっぱり重い事です。
あと、身も蓋もないですが、RDSのログをリアルタイムで監視したいという要件自体がほぼほぼ無いです。
AngularJSでUI BootstrapのTooltipをValidationに連動させて表示させる
BY | コメントをどうぞAngularJSには強力なフォームのバリデーション機能があり、任意のタイミングでエラーメッセージを表示することができます。
このエラーメッセージをバリデーションの状態に連動してUI BootstrapのTooltipに表示したいとき、どうすればよいでしょうか。
まずは思い付く方法で
まずは最初に思い付いた方法で実装してみます。
ツールチップはtooltip-enable
ディレクティブで有効/無効を切り替えられるので、バリデーションに失敗したときだけ有効にして表示するようにしてみました。
index.html
...
<form name="form" style="width:500px;" ng-class="{'has-error': form.value1.$dirty && form.value1.$invalid}">
<table class="table">
<tr>
<th>お名前(20文字まで)</th>
<td>
<input type="text" class="form-control input-sm" name="value1" ng-required="true" ng-model="value1" tooltip="20文字以下で入力して下さい" tooltip-enable="form.value1.$dirty && form.value1.$invalid" ng-maxlength="20">
</td>
</tr>
</table>
</form>
...
app.js
angular.module('app', ['ui.bootstrap']);
結果
バリデーションエラー時にinputにマウスカーソルを乗せることでツールチップが表示されるようになりました。
しかし、これではinputにマウスカーソルを乗せるまでエラーの内容が分かりませんし、マウスカーソルを離すとツールチップが消えてしまうのでイマイチです。
これは、ツールチップの表示を切り替えるデフォルトのトリガーイベントがmouseenter/mouseleave
となっているためです。
...
// Default hide triggers for each show trigger
var triggerMap = {
'mouseenter': 'mouseleave',
'click': 'click',
'focus': 'blur',
'none': ''
};
...
.directive('tooltip', [ '$tooltip', function($tooltip) {
return $tooltip('tooltip', 'tooltip', 'mouseenter');
}])
...
tooltipのカスタムトリガーとカスタムディレクティブで実現する
Plunker
今回はバリデーションの状態変化に応じて自動的にツールチップを表示したいので、自由に使えるカスタムトリガーが必要になります。
まずは、適当なconfig
セクションで$tooltipProvider.setTriggers()
を使ってカスタムトリガーを定義しましょう。$tooltipProvider.setTriggers()
の引数には、表示イベント名をプロパティ名、非表示イベントをそのプロパティの値として持つオブジェクトを指定します。
app.js
var app = angular.module('app', ['ui.bootstrap', 'app.directives']);
// 追加
app.config(['$tooltipProvider', function ($tooltipProvider) {
$tooltipProvider.setTriggers({
'show': 'hide'
});
}]);
これで要素がshow
イベントを受け取った時にツールチップが表示されるようになりました。
次に、このトリガーを発火するための仕組みを作ります。
AngularJSのバリデーション機能は、バリデーション対象として指定したモデルの値の変化に応じてリアルタイムに実行され、実行結果がスコープにセットされるようになっています。上記index.htmlの例だと、form.value1.$invalid
やform.value1.$valid
のboolean値を読むことでバリデーションの状態を取得することができます。
今回はtooltip
ディレクティブを拡張するカスタムディレクティブを用意して、その中でform.value1.$invalid
を監視することで、バリデーションの状態が切り替わった時にshow
イベントまたはhide
イベントを発生させてツールチップの表示を切り替えるようにしました。
directives.js
angular.module('app.directives', [])
// ツールチップ本体に付加されるディレクティブ
// デフォルトのものをそのまま流用
.directive( 'myTooltipPopup', function () {
return {
restrict: 'EA',
replace: true,
scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
templateUrl: 'template/tooltip/tooltip-popup.html'
};
})
// tooltipディレクティブを拡張するカスタムディレクティブ
.directive('myTooltip', ['$tooltip', '$timeout', function ($tooltip, $timeout) {
// tooltipのインスタンスを作成する
var tooltip = $tooltip( 'myTooltip', 'myTooltip', 'show' );
var originalCompile = angular.copy(tooltip.compile);
tooltip.scope = {myTooltipShow : "&"}
// compileを拡張
tooltip.compile = function(element, attrs, scope){
// オリジナルのLink function
var originalLink = originalCompile(element, attrs);
// linkを拡張
var link = function(scope, element, attrs) {
// my-tooltip-show属性の値を監視する
scope.$watch(scope.myTooltipShow, function (val) {
if (val) { // 評価値がtrueならばshowイベントを発生させる
$timeout(function() {
element.triggerHandler('show');
});
}else{ // 評価値がfalseならばhideイベントを発生させる
$timeout(function() {
element.triggerHandler('hide');
});
}
});
// オリジナルのlinkを実行する
originalLink(scope, element, attrs);
}
return link;
}
return tooltip;
}])
index.html
...
<input type="text" class="form-control input-sm" name="value2" ng-required="true" ng-model="value2" my-tooltip-show="form.value2.$dirty && form.value2.$invalid" my-tooltip="20文字以下で入力して下さい" ng-maxlength="20">
...
これで、バリデーションの状態がエラーになった時点でツールチップが表示され、正常になった時点で非表示になるようになりました。
my-tooltip-show
にform.value2.$dirty
を加えているのは初期状態でツールチップが表示されるのを抑制するためです。
今回作成したものはPlunkerにデモを用意していますので、ご利用ください。
http://plnkr.co/edit/ynywEEpNvlx0iSA2bUpI?p=preview
AWS ECSで insecureレジストリ(非SSL)を参照したい
BY | コメントをどうぞお盆も過ぎまして、ここ最近はなんだか涼しく感じるTokyoです。
そろそろ夏休みシーズンも終わりですね。
私はというもの8月は業務に明け暮れ、9月に夏休みがずれました。
がはは!俺が勝ち組だ!
どうも、DiceK Mikamiです。
今回は、AWS ECS(EC2 Container Service)にて、非SSLレジストリからイメージを取得するTipsをご紹介したいと思います。
続きを読む
Angular.jsで、アップロードするファイルをcontrollerでも使えるようdirectiveを自作する
BY | コメントをどうぞちまたにはAngular.jsのファイルアップロードのモジュールがたくさんあるのですが、シンプルで単機能なものが欲しく、自作しました。
ファイルの内容が、
<input type="file"> → directiveのchangeイベント → controller
の順で渡るところのコードです。
controllerでその後サーバーにアップロードするところは省きます。
前提のコード
下記のように、ファイルをアップロードするコードがあるとします。
index.htmlの中で、upload.htmlをincludeしています。
upload.htmlの中ではmy-sectionというdirectiveをtranscludeで使い、またtype=”file”のinputタグがあります。
続きを読む
HTMLとJavaScriptでEC2インスタンスを起動する
BY | コメントをどうぞAWSのSDKは様々な言語向けに用意されていますが、サーバーサイドの実装なしでAWSのAPIを叩く場合の選択肢として、AWS SDK for JavaScriptがあります。
http://aws.amazon.com/jp/tools/
ただ、他のSDKと違って対応しているサービスが限られています。
利用可能なサービスはS3、SQS、SNS、DynamoDBなどで、EC2は対象ではありませんでした。
EC2をサポート
6月24日のリリースで、In the BrowserにEC2がこっそり追加されていました。
http://aws.amazon.com/releasenotes/SDK/JavaScript/5873934951898767
6月18日のリリースにはEC2はありませんね。
http://aws.amazon.com/releasenotes/SDK/JavaScript/3577030144306744