Saturday, September 22, 2018

How to convert EC2 T2 instance to T3

1. Create snapshot of your ec2 instance volume (storage)
2. Install AWS CLI if not installed
3. Configure AWS CLI - set region, Access Key
4. run this command, replacing name, description and snapshot ID:


aws ec2 register-image --architecture "x86_64" --description "descr" --ena-support --name "name" --root-device-name "/dev/sda1" --block-device-mappings "[{\"DeviceName\": \"/dev/sda1\",\"Ebs\": {\"SnapshotId\": \"snap-123\"}}]" --virtualization-type "hvm"

5. Launch new instance from new AMI

Saturday, May 2, 2015

Mobile App with Ionic, ES6, AngularJS 1.4

While the world is awaiting for Ionic 2 based on Angular 2, I'm going to show you how to use little bit less bleeding edge technologies, but existing and working already today and still much more exciting than old ES5. Really, when you try arrow functions, you won't use ES5 again.

I will use both generator-gulp-angular and ionic-cli to generate project. First one for ES6 and tests running, second one for js-to-mobile builds.

Step 1:  Install generator-gulp-angular


npm install -g yo gulp bower

npm install -g generator-gulp-angular

Step 2: Install Ionic:


npm install -g cordova

npm install -g ionic


Step 3: Generate ionic files

We will start with Ionic, because Ionic will create a folder and will remember name of this folder somewhere inside:

ionic start example

Where example is the name of our project.
We actually don't need whole content of generated folder, but we have to do previous step to save name of folder inside ionic.
Now we will rename it:

mv example example_ionic

Step 4: Generate project folder

Let's create a folder again and this time it will be fulfilled by generator-gulp-angular:

mkdir example
cd example
yo gulp-angular example

On generation steps please select:
1) AngularJS 1.3 (or later version if in your time you have later version)
2) ng-modules: animate, touch, sanitize
3) jQuery: none
4) rest: ng-resource
5) router: ui-router
6) UI-framework: none (we will use Ionic for it)
7) CSS preprocessor - whatever you prefer
8) JS preprocessor: ES6 Babel
9) html template engine - whatever you prefer

Now we have generated project and it's the structure we will use as main.

Step 5: Merge

Let's copy ionic-generated files to our project:

cp ../example_ionic/config.xml ./
cp ../example_ionic/ionic.project ./
cp -R ../example_ionic/plugins ./plugins
cp -R ../example_ionic/hooks ./hooks

From ../example_ionic/package.json copy branch "cordovaPlugins" into your ./package.json.

Step 6: Change AngularJS version to 1.4

If in your time generator-gulp-angular has AngularJS version 1.4 or higher - skip this step.

Otherwise, let's change version of AngularJS and modules to 1.4.
To do this, you need a text editor (or your favorite IDE). Good chance to try new shiny Visual Studio Code :)

In bower.json, replace all entries of AngularJS 1.3 modules dependencies to 1.4.x:
Hint: VS Code replace shortcut in OS X is alt+cmd+F.

Replace all entries, save your edits and:

bower install

Step 7: Add latest ionic as bower dependency

bower install ionic#~1.x --save

On versions conflicts, select most latest versions and prefix your answers with "!".

Step 8: Add platforms

mkdir www

ionic platform add ios

ionic platform add android

Step 9: Build

In gulpfile.js, change in the options: 
dist: 'dist' 
to 
dist: 'www'

Now try to build your ES6 code:

gulp

You will run this command before each app deployment.

Check if ionic-cli works:

ionic serve

You should see something like this:

It doesn't look like mobile app, so let's use power of Ionic framework to change it!
Please interrupt ionic-cli by Ctrl+C for now.

Step 10: Ionize

In src/index.html, add link to ionic CSS into block "build:css": 

<!-- endbower -->
      here
<!-- endbuild -->

so it becomes:

    <!-- build:css({.tmp/serve,src}) styles/vendor.css -->
    <!-- bower:css -->
    <!-- run `gulp inject` to automatically populate bower styles dependencies -->
    <!-- endbower -->
    <link href="../bower_components/ionic/release/css/ionic.css" rel="stylesheet">
    <!-- endbuild -->

Now add links to JS files into first build:js block, after endbower and before endbuild line, so it becomes:

    <!-- build:js(src) scripts/vendor.js -->
    <!-- bower:js -->
    <!-- run `gulp inject` to automatically populate bower script dependencies -->
    <!-- endbower -->
    <script src="../bower_components/ionic/release/js/ionic.js"></script>
    <script src="../bower_components/ionic/release/js/ionic-angular.js"></script>
    <!-- endbuild -->

You need only these 2 files, everything else will be added by Gulp tasks.

Now replace 

<div ui-view></div>

with

<ion-nav-view></ion-nav-view>

And remove Google Analytics template code.

In src/app/index.js add Ionic as dependency, so list should look like this at this moment:
angular.module('example', ['ionic', 'ngAnimate', 'ngTouch', 'ngSanitize', 'ngResource', 'ui.router'])

To make UI of our app little bit more mobile friendly, let's take content of file ../example_ionic/www/templates/tab-dash.html, generated by ionic and put it into our src/app/main/main.html (replacing all lines).

Let's see what we have in result:

gulp serve

Project has been ionized!

While gulp serve work, every change we make in html/css/js source files will be reflected in the browser, so we don't need to run this task after each change manually - very handy for development.

Step 11: Use the power of ES6

To help you love ES6, I will show you some tricks, how to use it without any pain with AngularJS 1.4.

ControllerAs

ControllerAs it's a very important thing, it's not just handy feature, it makes your code much more clean and especially beautiful with ES6.
So, as a first step, in src/app/index.js replace 
  controller: 'MainCtrl'
with
  controller: 'MainCtrl as Main'
Now in html template you can use Main as reference to your controller and inside controller you can bind properties to "this" instead of $scope. More details about usage of controllerAs you can find in an article of very smart guys from thoughtram.

Services and Controllers

Services and Controllers can be easily presented as ES6 classes. To not duplicate list of dependencies in $inject, you can add string 
'ngInject';
inside function with list of dependencies. In case of class it's constructor.
Example:

class ExampleController {
  constructor($timeout) {

    'ngInject';
    this.$timeout = $timeout;
  }
}


export default ExampleController;

Directives, Filters and Resources

But some things are much more simple when we use them as old good functions.
Examples:

Resource:

function SomeLog($resource, Config, Token) { 

  'ngInject';
  return $resource(Config.apiUrl + '/events/:token', {token: Token.get()}, {
    count: {
      method: 'GET',
    
      url: Config.apiUrl + '/events/count/:token',     
      isArray: false,     
      transformResponse: function (data) {
        data = JSON.parse(data);
        return {'count': data};
      }
    }
  });
}

export default SomeLog;


Directive:

function exmpNavigation($state) { 
  'ngInject';
  return {
    restrict: '',
    templateUrl: 'components/exmpNavigation/template.html',
    controllerAs: 'cNav',
    controller: function () {
      this.go = function (route) {
        $state.go(route); 
      };
    }
  };
}
export default exmpNavigation;


Step 12: Mobile App

When your app is interesting enough to be tested on mobile device, create a build.
Don't forget to compile from sources:
gulp

And then we can create the build for iOS:
ionic build ios

and even test it, if you use OS X:
ionic emulate ios

More info about builds, including Android, can be found in Ionic tutorial.

One more interesting feature Ionic has: Ionic View. It's amazing thing and I recommend you to try it - pretty simple to use and saves tones of time for debug and testing on real devices. To start, just run:
ionic upload

All the power is in your hands (and brain)

Now you can use all the power of generator-gulp-angular, including handy shortcuts for testing (gulp test, gulp protractor), you can write awesome code in ES6 to build best in the universe mobile apps with Ionic, powered by the best AngularJS version yet. 
Good luck! :)

Thursday, February 19, 2015

How to setup VPN on Google Cloud Platform

After 19 days of using VPN on Google Cloud Platform, I want to spread more information about their excellent service.

Previous VPN services I tried where very unstable for me - even 1 disconnect per hour is not acceptable for me, because when it happens it happens in the wrong moment and it's very annoying.

Then I tried OpenVPN on own Linode VPS, but was wonder to still see disconnections, although less often - once per 2 hours approximately. I suppose Linode have some issues in their London DC network (and tests on speedtest.net confirms that). Next my try was same-sized VPN on DigitalOcean (Amsterdam 2 DC), and connection was more stable. But still few disconnections per day. Have to say, performance of same size server is much better on Linode. They just need more stable network.

In 19 days of usage VPN on Google Cloud Platform I've encountered... 0 disconnections. It wonders me and I'm glad to share my how-to (copy of my answer on serverfault.com).

  • I recommend you create additional network (see "Networks" tab"). In network preferences, add allowing rules for: tcp:22 (if not exist), tcp:9700, tcp:1761917619 here is variable - change it to any port you like (range is 9075-65534). You only need 3 rules and 2 default routes, nothing else.
  • Go to "Create Compute Engine instance", click "Show advanced options", allow ports forwarding, select location of the server.
  • Now (when you've selected location), add static IP to the server.
  • Select Ubuntu 14.04 image (exactly this version).
  • Create instance
  • Connect via SSH (most easy way - use in-browser tool from GCE panel)
  • sudo su
  • apt-key update && apt-get update && apt-get -y upgrade && apt-get -y install python-software-properties && apt-get -y install software-properties-common && add-apt-repository -y ppa:pritunl && apt-get update && apt-get -y install pritunl
  • In browser open https://instance_ip:9700
  • On question about DB, click "Save"
  • In login window, use pritunl as username and password
  • Now change username and password of admin user
  • Add organization, then 2 users (for desktop and mobile)
  • Click "Add server" in "Servers" tab
  • Use port number from first step (17619 as example) and tcp protocol.
  • Attach organization to server
  • Start server
  • In "Users" tab download keys for both users (tar archives with ovpn files inside).
I use Viscosity for OS X and OpenVPN connect for iOS as clients. In Viscosity, turn on "Send all traffic over VPN connection" option in "Networking" tab.

Wednesday, December 31, 2014

Testing AngularJS app with Protractor in multiple browsers (OS X)

Different browsers have different quirks, so let's try to run e2e tests in multiple major browsers.
We can't run IE in OS X, Opera is customized Chrome, so we need: Chrome, Safari,  Firefox.


Protractor has option to run specs in multiple browsers, called multiCapabilities.
By default all browsers run tests simultaneously, but in my experience it leads to errors ("failed expectations"), because sometimes tests trying to fulfill same records and it leads to conflicts.
To run tests in browsers consecutive, we can use "maxSessions: 1" in Protractor config.
So result is:

multiCapabilities: [
{
'browserName': 'chrome'
}
, {
'browserName': 'safari'
}
, {
'browserName': 'firefox'
}
],
maxSessions: 1,


If you use browserSync to run app locally, add "ghostMode: false" in browserSync config to avoid conflicts in launched versions of app when testing.

But software is often more complicated than we expect.
First: we can't run actual version of Firefox on OS X, even with new Selenium drivers.
Bug has status "Fixed" but nobody cares about regression. Update: to run tests in Firefox, use Protractor 1.8+, it will install Selenium 2.45, where bug is fixed.

So now we have Chrome and Safari in list.
Safari don't want to run too, hehe :) But it's fixable at least, thanks to this detailed answer.
Get actual version of Selenium driver jar here: http://central.maven.org/maven2/org/seleniumhq/selenium/selenium-safari-driver/
rename extension to .zip, 
unzip file 
and then in folder 'org/openqa/selenium' find file 'SafariDriver.safariextz' (it's not random letters :)) and double-click it.

After that, we can run tests in Safari, hurray!
And it's not the end of this story :)
Selenium can't navigate in browsing history of Safari (known issue), so if you use 


browser.navigate().back();

replace it to:

// before changing URL
var prevUrl = browser.getCurrentUrl();
// here some changing URL action, maybe click()
// ...
// and then
browser.navigate().to(prevUrl);

It's pretty obvious fix.
And now we can run Protractor tests in Chrome and Safari consecutive. It took few hours of my time to find all these fixes and workarounds, so I hope this article will help somebody to save time :)



Wednesday, November 12, 2014

AngularJS 1.3 and ES6 - how to use it already today

ES6, AtScript

Next version of Angular will use AtScript - superset of ES6 (upcoming version of JavaScript). So, if you write in ES5 (current version of JavaScript), you already write in AtScript, just without all of these optional additions - annotations, types and introspections. Yes, they will stay optional, but it's nice to have them.

We can't use AtScript in existing projects yet (and Angular 2 will be ready even later than AtScript), but we already can use ES6 with AngularJS 1.3, best Angular yet (current stable branch), with all cool things ES6 going to give us. Take it now! :)

How to

Update Feb 18, 2015:

Time goes and in few weeks after publishing this article, angular-gulp generator have implemented support of ES6. I highly recommend to use it instead of generator-angular, and all ES6 support will be provided "out of the box": https://github.com/Swiip/generator-gulp-angular


I'll show you how to do it on example of the project, bootstrapped by Yeoman's generator-angular. Maybe not top-notch folders structure, but easy to start with.
Source code of project:

Step 1 - install modules

When we have base of project, let's add components:
Grunt will transpile ES6 to ES5 (I know I know, Gulp is our new trend, but.. next time)

npm install grunt-traceur --save-dev

PhantomJS doesn't support ES5 even, so we will run unit tests in Chrome:

npm install karma-chrome-launcher --save-dev

We need traceur runtime in app:

bower install traceur --save

That's all.

Step 2 - Structure

In structure of this project most convenient place I found for ES6 files is /app/es6 - I just copied content of 'scripts' folder here. Now I can use watch, livereload, build project and run tests. Awesome.

Step 3 - Gruntfile

Example of Gruntfile.js
And what has been changed in file, generated by generator-angular:
We add new task, 'traceur' and add it to build, test, serve tasks. 

Step 4 - Unit tests config

replace PhantomJS by Chrome (it will run without taking focus, in background) and add traceur.min.js link.

Step 5 - index.html

Just add link to traceur.min.js

Enjoy ES6!

Now you can use ES6 in your AngularJS project. For example, I use ES6 classes for Services, because I like it and it works :)
Traceur will compile AtScript in the same way it compile ES6 for us in this project, so it's nice to meet Traceur already now and start use advantages of new technologies.

Additional Links

Monday, November 10, 2014

SOA for client-side apps as the way of interoperation

It's idea to discuss and, maybe, implementation.

When building web-apps, we write code for the server side and for the client side. On the server side we can use any language we want - just give API (REST as standard nowadays) and be happy - any app, written in any language (with access to network), can communicate with your programm.


On the client side.. You know, only JavaScript.
TypeScript and even Dart, at the moment I write this, should be transpiled into JS to run in all major browsers. On the web page we can use different JS libraries, jQuery plugins and each one will do it's task and they will not do something in cooperation - in the best case functionality of one library (often jQuery) will be used as a tool in other JS libraries. It doesn't mean they can't coexist - they can and do, but often by the price of tight coupling and only in the scope of one language, so even if you transpile Dart to JS, you can't use all the power of Dart just because of compatibility. And it's the reason why there is not so many new languages for the client side.

Idea

I think we could use SOA inside web page, when web app is the set of services, communicating by APIs. So we need transport, like HTTP, and as this transport we can use DOM (what most JS libs use now) or Local Storage (SessionStorage). DOM (and especially Shadow DOM) looks more attractive, because here we can use object.observe and some other interesting things, but DOM requires browser's attention and I'm not sure if this approach is safe in terms of occasional re-renderings, leaked nodes and collisions/pollution with user-defined elements.
In Session Storage we can have more freedom and it's just less dangerous. If we can do dirty-checking with speed of 300 000 checks/ms in JS, then maybe we can something similar with SessionStorage (or DOM at least), and then we can build event dispatchers on top of that and use it as transport for APIs interoperation. It will not be possible to send pointers of functions (as we used to in JS), but it's how a lot of amazing apps work on the servers and on desktops.

If it's implemented already somewhere - please let me know.

Sunday, November 9, 2014

Importance of idempotence - what if POST request will be cached

Couple of weeks ago tester of mobile app I'm building sent us bug report, and described bug was awful - data loss because of wrong synchronization process. Synchronization is always tricky thing to do, but I was sure all works fine because all code, especially of synchronization, is heavily covered by tests (unit and e2e). And all of them were "green".

I've tried to reproduce, as described in report - not reproducible... It's even worse than reproducible.
But what was more interesting - teammates in the USA were able to reproduce it with 100% chance. Really, we demonstrated each other how app behaves and they could reproduce it, I saw it, when I couldn't, even in most difficult cases (for synchronization algorithm)..

As I discovered by symptoms, server has been sending same responses for separate POST requests, when server should generate unique identificator. We checked code of the API - all fine. And for me API doesn't send same responses, so... Yes, responses (or requests) were cached! And cached not by server (nobody will configure server to cache POST requests, I suppose), but somewhere inside the US network between users and server - that's why it wasn't reproducible from my side - I'm testing it from Russia (where I live).

Same "unique" id for different records it's a very dangerous thing and leads to very bad bugs and data losses, so we decided to add random hash to all requests and it solved our issue.

It wasn't difficult to fix, but it was very difficult to find, because I couldn't imagine that POST request can be cached (responses have been sent without touching server, just responses for previous requests with the same signature).

What to think about it? Should we (all programmers) add cache-preventing garbage to each POST/DELETE request? Of course, network providers shouldn't cache POST requests, but we can't force them and can't wait while they'll fix it.

I'm still not sure, so please share your opinions.