2016年1月28日 星期四

Nginx 支援多網域 Access-Control-Allow-Origin 設定方式

原先 Access-Control-Allow-Origin 只能支援一個指定網域或 "*" 的設定,想要支持多網域設定時,就來用一下 nginx 的變數吧!

set $access_control_allow_origin "www.changyy.org";
if ($http_host ~ ^(.*\.changyy\.org)$ ) {
set $access_control_allow_origin $1;
}
if ($http_referer ~ ^(https*\:\/\/.*\.changyy\.org)\/ ) {
set $access_control_allow_origin $1;
}
add_header Access-Control-Allow-Origin $access_control_allow_origin;
add_header Access-Control-Allow-Methods "GET, OPTIONS, POST, HEAD, DELETE, PUT";
add_header Access-Control-Allow-Headers "Authorization, X-Requested-With, Content-Type, Origin, Accept";
add_header Access-Control-Allow-Credentials "true";
add_header Access-Control-Max-Age: 86400;


如此一來,只要是 *.changyy.org 的都可以支援啦!同理就可以用在多網域得設置。

若需要支援不同網域以及非預設的 web port ,則要把規則改成:

set $access_control_allow_origin "www.changyy.org";
if ($http_host ~ ^(.*\.changyy\.org(:[0-9]+)*)$ ) {
set $access_control_allow_origin $1;
}
if ($http_referer ~ ^(https*\:\/\/.*\.changyy\.org(:[0-9]+)*)\/ ) {
set $access_control_allow_origin $1;
}

Ansible 筆記 - 解決 selectattr('field_name','equalto','field_value') - TemplateRuntimeError: no test named 'equalto' @ Ubuntu 14.04

最近又再調整 Ansible 的使用架構,想要更多的彈性,勢必就會碰到抽資料出來的問題,接著就會踩到想要用 Jinja2 裡的 test equalto 用法。

目前環境:

$ ansible --version
ansible 2.0.0.2
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
$ pip show jinja2
---
Name: Jinja2
Version: 2.7.2
Location: /usr/lib/python2.7/dist-packages
Requires: markupsafe


而 equalto 的用法是 Jinja2 2.8 之後才支援的 Orz

只好硬解一下:

$ sudo pip install jinja2 --upgrade
$ pip show jinja2
---
Name: Jinja2
Version: 2.8
Location: /usr/local/lib/python2.7/dist-packages
Requires: MarkupSafe


接著,就沒事了 :P 來一個完整範例紀錄:


- hosts: localhost
  vars:
    rpm_list:
      - name: "my-service-package-1"
        install_dir: "/opt/my-service-package-1/"
      - name: "my-service-package-2"
        install_dir: "/opt/my-service-package-2/"

  task:
    - set_fact: x="{{rpm_list | selectattr('name','equalto','my-service-package-2') | map(attribute='install_dir') |list}}"
    - debug: var={{x}}


執行:

TASK [set_fact] ****************************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "/opt/my-service-package-2/": "VARIABLE IS NOT DEFINED!"
}


---
更新:

$ cat echo.sh
#!/bin/sh
echo '{"all":["127.0.0.1"]}'

$ cat test.xml
---

- hosts: all 
  vars:
    rpm_list:
      - name: "my-service-package-1"
        install_dir: "/opt/my-service-package-1/"
      - name: "my-service-package-2"
        install_dir: "/opt/my-service-package-2/"
  tasks:
    - set_fact: x="{{rpm_list | selectattr('name','equalto','my-service-package-2') | map(attribute='install_dir') |list}}"
    - debug: var=x

$ ansible-playbook -i echo.sh test.xml 
PLAY [all] ***********************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************
ok: [127.0.0.1]

TASK [set_fact] ******************************************************************************************************************************************
ok: [127.0.0.1]

TASK [debug] *********************************************************************************************************************************************
ok: [127.0.0.1] => {
    "x": [

        "/opt/my-service-package-2/"
    ]
}

PLAY RECAP ***********************************************************************************************************************************************
127.0.0.1                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


其他參考資料:

2016年1月26日 星期二

使用微軟翻譯 API (Translator API - Microsoft Translator)

有個工作拖了很久,最後請同事協助處理了一下,順手筆記 :) 由於 App 撒出去世界各地,所以總會有好心人士留留言給予鼓勵,無奈很多語言都看不懂 XD 人工用 Google 翻譯當然夠用,但量大的時候,就希望能夠自動翻譯一下。

同事研究後,發現微軟翻譯 API 有免費使用額度(一個月200萬個字),所以就挑這來做了!

首先,註冊一下帳號:https://datamarket.azure.com/account ,填一下基本資料即可,一開始就會得到一組主要帳戶金鑰跟客戶識別碼,這組可以用來測試一些 API。

當要正式使用時,請至開發人員頁面,註冊一個應用程式(重導網址隨便輸入即可,在此不會用到),用新註冊到的金鑰跟客戶識別碼來工作即可。不然會收到類似的訊息:

TranslateApiExceptionMethod: Translate()Message: Cannot find an active Azure Market Place Translator Subscription associated with the request credentials.message

整個微軟翻譯 API 的使用流程:

Step 1: 透過 client_id 和 client_secret 換得 token

<?php

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://datamarket.accesscontrol.windows.net/v2/OAuth2-13/');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
'grant_type' => 'client_credentials',
'scope' => 'http://api.microsofttranslator.com'
'client_id' => 'YourAppID',
'client_secret' => 'YourAppSecretKey'
)));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$ret = curl_exec($ch);
curl_close($ch);
$token = json_decode($ret)->access_token;


Step 2: 帶著 token 跟待查的資料去問微軟翻譯 API

<?php

// https://msdn.microsoft.com/en-us/library/ff512421.aspx
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://api.microsofttranslator.com/v2/Http.svc/Translate?'.http_build_query(array(
'text' => '第二十四個夏天後',
'from' => null,
'to' => 'en',
)));
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization: Bearer '.$token,
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$ret = curl_exec($ch);
curl_close($ch);
echo strip_tags($ret)."\n";


收工。

2016年1月23日 星期六

老片情懷:飲食男女

晚上不知幹嘛,就看了個老片:飲食男女。有興趣可以在 LiTV.tv 找免費的電影,有數位復修版。

這部片感觸真深,例如令人想睡的化學課、排球課、電腦遊戲(很像軒轅劍貳系列)以及慢跑的台北街場,細細述說著每個年代的情懷憂愁,說也說不盡,更別說片尾又來個驚喜,還真的沒料到結局啊。

台灣彷彿也剛經歷個改朝換代,只是過了一夜的激情後,那然後呢?其實什麼都沒有改變,股市隨著大環境起起落落,油價供電需求亦是如此。同輩之間又再次風水輪流轉,各人有個人的情懷,這大概是資訊圈的常態吧!看著學弟從中國回來後,在台灣又找不到合適落腳處,或許,就像 1994 年的飲食男女,原來這樣的狀態在 n 年前依舊一模一樣,戀愛的戀愛,工作的工作,惆悵的依然香煙渺渺,我想,堅持的還是自己的信念吧 :)

持續積極正面生活吧!如同柯p所言,人的終點是死亡,但死亡絕對不是人生的目的啊,生活也好、做事也罷,別老想著負面跟自己過不去,衝刺吧,熱情還在就好,傻裡傻氣也沒什麼不好。

2016年1月22日 星期五

DevOps 筆記 - Jenkins 處理 Git Submodule Authentication/Credential 問題

已經很習慣用 Bitbucket 做 git service,然後有個 project 裡有個 sub-project 一樣有存取控管,而 Jenkins 預設只有第一層存取時,可以正確透過 Credentials 來解決,但是 submodule 就會失敗。

依照原理解法有兩招:

  1. 直接在 Jenkins 執行者的 $HOME/.ssh/ 去撰寫底層 ssh 連線認證方式
  2. 使用 Jenkins plugin - SSH Agent Plugin

為了管理維護方便,當然就用 SSH Agent Plugin 啦,安裝完後,每一個 Project 就會多一個 SSH Agent 的設定選項,只需設定好即可。

另外,有一派會建議把原先 Jenkins Project 裡的 Git Credentials 去掉,一律都用 SSH Agent Plugin 的設定,但這招會導致後續要做 Git Publisher 要做 git tag 時產生問題。