How to solve tiller is unable to connect localhost:8080 in Helm

If you are facing issue when running helm ls, helm install (no resources found)…

Solution 1

when install helm (2.8.2)

kubectl create serviceaccount --namespace kube-system tiller

/* solve configmaps is forbidden: User "system:serviceaccount:kube-system:tiller" cannot list configmaps in the namespace "kube-system" */

kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller

helm init --service-account tiller

Solution 2

set the automountServiceAccountToken to true (It seems to be fixed in v2.9?)

kubectl -n kube-system patch deployment tiller-deploy -p '{"spec": {"template": {"spec": {"automountServiceAccountToken": true}}}}'



How to use Terraform with Nectar For Beginner

What is Nectar?

Nectar is a cloud platform built on top of OpenStack. Nectar is used to support Australian researchers.

What is Terraform?

Terraform is a tool of Infrastructure-As-Code (IAC). By using it, we write codes in HCL language to provision VMs in automation manner. Other tools of IAC are Ansible, Chef, Puppet, etc. It provides us great maintainability and reduces the security flaws if a same procedure has to be done again and again to build and configure VMs.

Terraform’s file extension is *.tf.  In this tutorial, we will create three files:

    • Variables such as account credentials, login url, etc, are all declared here.
    • Terraform is built on modules. We need to let it know which module we will use.
    • Configuration of VMs lies here.

Get Started

Install Terraform
brew install terraform
Account Credentials

Once log in Nectar, reset your password in order to access OpenStack in SSH. The credentials you log in Dashboard with is not the one for SSH.

Download the OpenStack RC file which is used to set environment variables on client-side.

Create your keypair

Now that credentials are obtained, we can start putting them into the file.

variable "openstack_user_name" {
 description = "The username for the Tenant."
 default = "your account name : email"

variable "openstack_tenant_id" {
 description = "The id of the Tenant."
 default = "your project id"

variable "openstack_tenant_name" {
 description = "The name of the Tenant."
 default = "your project name"

variable "openstack_password" {
 description = "The password for the Tenant."
 default = "your password"

variable "openstack_auth_url" {
 description = "The endpoint url to connect to OpenStack."
 default = ""

variable "openstack_keypair" {
 description = "The keypair to be used."
 default = "your-keypair"

variable "tenant_network" {
 description = "The network to be used."
 default = "Classic Provider"

We are using auth v3, therefore, Tenant name/ID is replaced by Project name/ID.
provider "openstack" {
 user_name = "${var.openstack_user_name}"
 tenant_id = "${var.openstack_tenant_id}"
 tenant_name = "${var.openstack_tenant_name}"
 password = "${var.openstack_password}"
 auth_url = "${var.openstack_auth_url}"

We provision 2 instances. In OpenStack, the type of machine is called flavor and its ID can be found in the dashboard, so can the image (Operation System).

variable "count" {
 default = 2

resource "openstack_compute_instance_v2" "web" {
 count = "${var.count}"
 name = "${format("web-%02d", count.index+1)}"
 image_id = "d87a2d42-6a90-4d7d-918c-988e9ab13b56"
 availability_zone = "melbourne"
 flavor_id = "639b8b2a-a5a6-4aa2-8592-ca765ee7af63"
 key_pair = "${var.openstack_keypair}"
 security_groups = ["default"]
 network {
 name = "${var.tenant_network}"
 user_data = "${file("")}"

yum install -y httpd
chkconfig --level 345 httpd on

cat <<EOF > /var/www/html/index.html
<p>hostname is: $(hostname)</p>
chown -R apache:apache /var/www/html
service httpd start

Now we can tell Terraform to deploy it.
Before actually deploying it, we can preview it.

terraform plan

then apply(deploy) it

terraform apply
Test the instances

The deploy script has a key called user_data. Each instance will invoke this user data where we set up a static web page.

Initialising instances may take some time. Let’s wait…

Once it is done, we navigate to our instance with port 80.

You should able to see “host name is XXXX”


Wonder what can Terraform do more for OpenStack?

Check Terraform official guide for OpenStack – link

OpenStack is not fully supported by Terraform yet. Some functions may not be working.

Background Location Update in iOS 11

In iOS 11, CoreLocation has some changes including the showsBackgroundLocationIndicator property, a new Info.plist key : NSLocationAlwaysAndWhenInUseUsageDescription.

To suppor iOS 11, there are two keys for location service.

  1. NSLocationWhenInUseUsageDescription
  2. NSLocationAlwaysAndWhenInUseUsageDescription
  3. NSLocationAlwaysUsageDescription (support iOS 10 device or below)

Apple encourages developers to use location service more in foreground than in background, and gives users a clearer understanding of when and how the location service is used.

The arrow indicator of location service

  • stays hollow when device is either monitoring geofences or using significant location service.
  • stays solid when device receives location updates

The mechanism of CL Location Manager has been changed. There are some reports showing that apps can no longer receive background updates. During my testing on iOS 11.2.2, I found out the following scenarios work.

  1. Significant location service work in both foreground, background, and even user kills the App, it will wake up.
  2. Standard location service doesn’t start when the App is in the background. However, if the App also registers significant location service, standard location service is able to start in the background, even the App has been killed manually by users and significant location service launches the App before starting standard location service. (This requires UIBackgroundMode is set with Location Update).
  3. Entering geofences will give the App 10 seconds of execution time. During that time, the App can launch standard location service.
// setting up location manager

locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation // accuracy enhanced by sensor data

locationManager.pausesLocationUpdatesAutomatically = false // or true depends on you

locationManager.distanceFilter = 5 // how you want to receive the updates, every 5 meters? In real situation, it may report less than 5 meters!

if #available(iOS 11.0, *) {
    locationManager.showsBackgroundLocationIndicator = true // show users when standard location service is activated, good for debugging.

locationManager.allowsBackgroundLocationUpdates = true //  necessary to make standard location service work in background

locationManager.requestAlwaysAuthorization() // request permission

locationManager.startMonitoringSignificantLocationChanges() // crucial to start standard location service in background

// start standard location service when user enters a geofence
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {


I’ve tested the code on iPhone X iOS 11.2.2.
If you want to share test results on other devices, please do so! Thanks!

How to write multiple language code snippets in MkDocs

MkDocs is using markdown to generate documents on static web pages.

Recently, I was working on writing documents for a iOS project. In iOS, I would need to document 2 programming languages: Objective-C & Swift. If I write them in two separate code snippets, that would be very unreadable. So to improve the readability, I decided to put them together by using HTML Tabs.

We will need to use custom configuration to let MkDocs generate those HTML syntax with the javascript and CSS.

In mkdocs.yaml, specify the js and CSS files used for the tabs.

    - styles/tab.css
    - custom/tab.js

Javascript: when clicks the tab, it will hide others tab contents.

function openCode(codeName, elmnt, color) {
// Hide all elements with class="tabcontent" by default */
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i &lt; tabcontent.length; i++) {
tabcontent[i].style.display = "none";

// Remove the background color of all tablinks/buttons
tablinks = document.getElementsByClassName("tablink");
for (i = 0; i &lt; tablinks.length; i++) {
tablinks[i].style.backgroundColor = "";
tablinks[i].style.color = "black";

// Show the specific tabs content
var elements = document.getElementsByClassName(codeName);
for (i = 0; i&lt; elements.length; i++) {
elements[i].style.display = "block";

// Add the specific color to the button used to open the tab content
elements = document.getElementsByClassName(elmnt.className);
for (i = 0; i&lt; elements.length; i++) {
elements[i].style.backgroundColor = color;
elements[i].style.color = "white";

// Get the element with id="defaultOpen" and click on it
if(document.getElementsByClassName("objbutton") !== null){
var elements = document.getElementsByClassName("objbutton");
for (i = 0; i&lt; elements.length; i++) {

CSS: for Tab styling

/* Style the tab buttons */
.tablink {
    color: black;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 12px;
    font-size: 12px;
    width: 100px;

/* Change background color of buttons on hover */
.tablink:hover {
    background-color: #777;

/* Set default styles for tab content */
.tabcontent {
    color: black;
    display: none;

/* Style each tab content individually */ 
#Obj {background-color:white;}
#Swift {background-color:white;}

Then finally in markdown file, we can easily create a multi-language code snippet.

<button class="tablink objbutton" onclick="openCode('obj', this, '#03a9f4')" markdown="1">Objective-C</button> 
<button class="tablink swiftbutton" onclick="openCode('swift', this, '#03a9f4')" markdown="1">Swift</button> 


<div class="obj tabcontent"> 
Your objective-c code goes here.


<div class="swift tabcontent"> 
Your swift code goes here.


In HTML tags, the markdown="1" tells MkDocs do not parse its content so it will be generated as normal HTML syntax.

Here it is how it looks like.

How to create iOS fat dynamic framework

“Fat” means that this framework has many slices. Each slice (machine code) is built for certain architecture. The fat framework we are going to build contains i386 x86_64 armv7 armv7s arm64.

  • armv7 is for iPhone 4s
  • armv7s is for iPhone 5
  • arm64 is for iPhone 6

Firstly we need to create a target for dynamic framework: Cocoa Touch Framework

Secondly we create a new target: External Build System

Go to Build Phases -> Run script

Paste the below code snippet in there


# make sure the output directory exists
# Step 1. Build Device and Simulator versions
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
# Step 2. Copy the framework structure (from iphoneos build) to the universal folder
# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
# Step 5. Convenience step to copy the framework to desktop directory
ditto "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${HOME}/Desktop/${PROJECT_NAME}.framework"

Build it then your fat dynamic framework will be located on your desktop! Before submitting the App to AppStore, you must strip off the simulator slice (i386 x86_64) from the framework

lipo -remove i386 Name.framework/Name -output Path/name

lipo -remove x86_64 Name.framework/Name -output Path/name

Or you can refer to this solution:


Logitech G213 Prodigy Keyboard

My first mechanical keyboard was CM Storm QuickFire TK. I likes its CHERRY MX RED Switches. Unfortunately, it did not come along with me to Australia. I had to use MacBook’s keyboard for 9 months. Finally, G213 caught my eyes with its shiny LED lights, and very fair price.

G213 supports OS X, its multimedia buttons are functional, including playing iTunes music, lower/raise the volume.

Though, it is not a mechanical keyboard, its keys actually provides a similar feeling as using cherry red switches. Nonetheless, the sound of clicking is not so clear and sharp as cherry red switches.

Its RGB lights are bright, and the keyboard can support multiple colors in 4 zones at once.

For this fair price, 70AUD, it worths purchasing.

GoPro 5 Black is here!

關注於動作攝影機已有兩三年了吧,一直在Sony 與 GoPro之間遊蕩。為了即將開始的Road Trip,有恰當的理由可以入手了!可以錄起我最愛的運動:衝浪,滑板,滑雪,潛水!

car charger, 3 way stick, GoPro 5, 2 batteries(Wasabi) with charger, head strap, quick clip.

Choice of memory card for 4K recording

SanDisk Extreme 128GB
Samsung Pro Plus 64GB

I bought the SanDisk Extreme 128GB first, then I found out that it is incompatible with GoPro 5 Black. After searching online, it seems that every SanDisk card with UHS-speed 3 has issue.
Then I got another one which is Samsung Pro plus 64GB, which works well.


Whilst using SanDisk Extreme, I had to insert and remove the SD card 4 or 5 times to get it work when the GoPro is on. This is very annoying and it is impossible to do that when you are doing sports.


Updated: After the firmware v1.57 of GoPro5, SanDisk Extreme 128GB works really well!!!

Osaka Universal Studio 大阪 環球影城

歡迎來到 Universal Studio




門票的部分,我們在網路上已經先訂好了Express 7,可以快速通關七項遊樂設施。進場時,出示QR Code便可以,不需有紙本票根。如果有購買快速通關的話,就不需要花太多時間排隊囉,真的挺貴的。但是逆轉世界這項遊樂設施還是排了挺久的,一個多小時吧。如果沒有快速通關大概要兩三小時吧….









霍格華滋提供了軌道列車搭載4K3D影院,感覺就像法國迪士尼的L’Aventure Totalement Toquée de Rémy 料理鼠王的實境歷險。不過霍格華滋的刺激度更上一層樓,坐完可能會暈眩唷,因人而異。這項設施有快速通關的話,可以節省不少時間,我幾乎沒有花到什麼等待的時間。

這個遊樂設施跟逆轉世界比…等待的時間也挺久的 >_<




Intel Galileo 2 FTDI cable serial connection tutorial on Mac OS X

First of all, you will need

  • Intel Galileo 2 (Linux installed)
  • FTDI  TTL-232R cable

Step 1.

Install FTDI VCP driver from here

Step 2.

Reboot your computer

Step 3.

Connect FTDI Cable to your computer

Step 4.


ls /dev/tty.*

You should now see


Step 5.

screen /dev/tty.usbserial-XXXXXXXX 115200 -L


Step 6.

If you see blank, press Enter twice.

Then you will see the login request.

Step 7.

Login as root

Step 8.

You are now connected to Intel Galileo 2.



With Mac OS 10.9 (Mavericks) and later, Apple has built their own version of the FTDI VCP driver into the operating system (AN134). However, there seems to be some conflict between drivers from and the ones inherent to Apple. Luckily, there is a solution to this problem, and it comes from FTDI directly.

If you have that issues, solution is referred to this site: