If you work as an investment advisor or are part of the banking industry, you already know how blockchain technology is transforming your workplace and changing the rules of the game.
{: .align-center}
Investment advisors can barely go a day without at least one Bitcoin inquiry, and financial professionals are constantly looking for new ways to incorporate cryptocurrencies and blockchain technology into their day-to-day operations.
For those in other industries, the recognition of blockchain technology and its inherent transformative power is often slower, but that does not mean it is not happening. Indeed, blockchain technology has the power to change virtually every industry, and those who fail to adapt to the shifting landscape could find themselves left behind.
The advertising industry is a case in point and an illustrative example of how blockchain technology is already changing the world. Whether you work in the advertising industry or are just an interested observer, it pays to know what to expect, and how blockchain technology could transform the world of marketing in just a few short years. Here are three ways blockchain technology is already changing the world of advertising.
Transformation #1 - Advertising Will Become More Transparent
Throughout the years, the advertising industry has been called many things, but transparent has rarely been one of them. Indeed, many consumers have complained that advertising was often opaque and even deceptive, with unproven claims, dishonest operators and a host of other problems.
In the future, blockchain technology could make advertising far more transparent than it is today. Many of these changes are already underway., with voluntary reporting on the origin of social media ads and other types of marketing outreach. In the future, blockchain technology will make advertising even more accessible and transparent, benefitting consumers and businesses alike.
Transformation #2 - Video Content Advertising Will Be Changed Forever
The widespread adoption of high-speed internet has changed the media landscape forever, and those alterations are still underway. Video content is quickly supplementing its text-only counterparts, as content production gets easier and less expensive and bandwidth capabilities expand.
The power of the blockchain will change the creation and distribution of content just as much, allowing even the smallest businesses to produce and distribute high-quality video. From simple animations to studio-quality video, the world of advertising will be transformed, thanks to the power of the blockchain.
Transformation #3 - Direct Access to the Consumer
From the earliest days of the advertising industry, there has always been a middleman standing between consumers with money to spend and advertisers with something sell. Initially, those middlemen were newspaper publishers and magazine owners, then the owners of television studios and finally the operators of search engines and online directories.
Thanks to the transformational power of the blockchain, those middlemen may soon become a thing of the past. Blockchain technology is already allowing more direct contact between consumers and advertisers, increasingly making the middlemen obsolete. This change promises to revolutionize the world of advertising, changing the publishing business in countless ways and disrupting the industry like never before.
Blockchain technology is changing the world in many different ways, from the way we bank and invest to the way we work and create business relationships. For those in the advertising industry, the transformational power of blockchain technology could be even greater, and the time to get ready for the changes is now.
Today I started working on updating Apport code from Swift 2 to Swift 4. So I got everything ready, made a fresh cup of coffee and opened the project workspace in Xcode 9. And then I got this message:
I have to convert the project to Swift 3 first in Xcode 8 and then convert once again to Swift 4 in Xcode 9.
So I need both Xcode 8 and Xcode 9 installed, and here is how that can be done:
In this post we show how you can use Chef to build an Ubuntu 14.04 LTS web server running Nginx, Python 2, virtualenv, uWSGI, and Flask - all done on Windows 10 host.
All commands are executed in PowerShell on a Windows workstation. The Chef version that is used is 12.5.1 - it is the version that comes with ChefDK 0.10.0. To avoid unexpected behavior, we recommend using those versions, when following this step-by-step guide.
The test application that we use for this deployment is available in the my_flask_app repository. The application was created using Visual Studio 2015 with Python Tools for Visual Studio (PTVS).
If you do not have Chocolatey, you can install it by following the instructions on chocolatey.org. You may also see this post for instructions on how to set the Chocolatey cache location.
This file will be merged within Test Kitchen's generated Vagrantfile. In it, we put the configuration for the vagrant-cachier plugin
touch.kitchen.vagrant_cachier.rb
Paste this in the .kitchen.vagrant_hostmanager.rb file:
# This requires vagrant-cachier plugin.# For more information see http://fgrehm.viewdocs.io/vagrant-cachier/#Vagrant.configure("2")do|config|ifVagrant.has_plugin?("vagrant-cachier")config.cache.auto_detect=trueconfig.cache.scope=:boxendifVagrant.has_plugin?("vagrant-omnibus")config.omnibus.cache_packages=trueconfig.omnibus.chef_version="12.5.1"endconfig.vbguest.auto_update=falseend
This file will be merged within Test Kitchen's generated Vagrantfile. In it, we put the configuration for the vagrant-hostmanager plugin, which updates C:/Windows/System32/drivers/etc/hosts, and allows you to access the virtual machine by name instead of IP address, e.g. default-ubuntu-1404.
touch.kitchen.vagrant_hostmanager.rb
Paste this in the .kitchen.vagrant_hostmanager.rb file:
# This requires vagrant-hostmanager plugin.# For more information see https://github.com/smdahlen/vagrant-hostmanager#Vagrant.configure("2")do|config|ifVagrant.has_plugin?("vagrant-hostmanager")# update /ect/hosts on all running guestsconfig.hostmanager.enabled=true# do not add offline guests to /etc/hostsconfig.hostmanager.include_offline=false# use the private ip address with ip_reslover, see belowconfig.hostmanager.ignore_private_ip=false# custom IP resolver# get each guest's IP address by running `hostname -I` on the guestconfig.hostmanager.ip_resolver=procdo|vm,resolving_vm|ifhostname=(vm.ssh_info&&vm.ssh_info[:host])`vagrant ssh -c "hostname -I"`.split()[1]endend# also update host's /ect/hostsconfig.hostmanager.manage_host=trueendend
Update .kitchen.yml to include only the ubuntu-14.04 platform for now. Also add the data bag path and Chef version. This is how it should look at the end:
## Cookbook Name:: my_flask_server# Recipe:: my_app_dir## Copyright (c) 2016 The Authors, All Rights Reserved.# app root directorydirectory'/var/www/my_flask_app'doaction:createrecursivetrueuser'www-data'group'www-data'end# app shared directorydirectory'/var/www/my_flask_app/shared'doaction:createuser'www-data'group'www-data'end# for virtualenvdirectory'/var/www/my_flask_app/shared/.env2'doaction:createuser'www-data'group'www-data'end# for uwsgi socket and uwsgi configdirectory'/var/www/my_flask_app/shared/.uwsgi'doaction:createuser'www-data'group'www-data'end# required by sshdirectory'/var/www/.ssh'doaction:createrecursivetrueuser'www-data'group'www-data'end# required by pipdirectory'/var/www/.cache'doaction:createrecursivetrueuser'www-data'group'www-data'end
## Cookbook Name:: my_flask_server# Recipe:: default## Copyright (c) 2016 The Authors, All Rights Reserved.include_recipe'apt::default'include_recipe'my_flask_server::my_app_dir'
require'spec_helper'describe'my_flask_server::my_app_python'do# Serverspec examples can be found at# http://serverspec.org/resource_types.html# verify system pythondescribepackage('python')doit{shouldbe_installed}end# verify system pipdescribecommand('which pip')doits(:stdout){shouldcontain'/usr/local/bin/pip'}end# verify system setuptoolsdescribecommand('which easy_install')doits(:stdout){shouldcontain'/usr/local/bin/easy_install'}end# verify system virtualenvdescribecommand('which virtualenv')doits(:stdout){shouldcontain'/usr/local/bin/virtualenv'}end# verify my_flask_app virtual environment# See `helpers/serverspec/type/virtualenv.rb`describevirtualenv('/var/www/my_flask_app/shared/.env2')doit{shouldbe_virtualenv}endend
############################################################################### You can find the original code at:# <https://github.com/jantman/serverspec-extended-types># Licensed under the MIT License############################################################################### ServerspecmoduleServerspec# TypemoduleType# VirtualenvclassVirtualenv<Base# Test whether this appears to be a working venv## Tests performed:# - venv_path/bin/pip executable by owner?# - venv_path/bin/python executable by owner?# - venv_path/bin/activate readable by owner?# - 'export VIRTUAL_ENV' in venv_path/bin/activate?## @example# describe virtualenv('/path/to/venv') do# it { should be_virtualenv }# end## @api public# @return [Boolean]defvirtualenv?pip_path=::File.join(@name,'bin','pip')python_path=::File.join(@name,'bin','python')act_path=::File.join(@name,'bin','activate')cmd="grep -q 'export VIRTUAL_ENV' #{act_path}"@runner.check_file_is_executable(pip_path,'owner')&&@runner.check_file_is_executable(python_path,'owner')&&@runner.check_file_is_readable(act_path,'owner')&&@runner.run_command(cmd).exit_status.to_i==0endend# Serverspec Type wrapper method for Serverspec::Type::Virtualenv## @example# describe virtualenv('/path/to/venv') do# # tests here# end## @param name [String] the absolute path to the virtualenv root## @api public# @return {Serverspec::Type::Virtualenv}defvirtualenv(name)Virtualenv.new(name)endendendincludeServerspec::Type
Add this line to test/integration/helpers/serverspec/spec_helper.rb:
## Cookbook Name:: my_flask_server# Recipe:: default## Copyright (c) 2016 The Authors, All Rights Reserved.include_recipe'apt::default'include_recipe'my_flask_server::my_app_dir'include_recipe'my_flask_server::my_app_python'
This key will be used to encrypt sensitive cookbook information like SSH private keys. Make sure you store a copy of the ~/.chef/chef_data_bag_secret file in a secure location.
IMPORTANT: Make sure the file uses Unix Line Ending (\n, LF) and UTF-8 encoding. Otherwise you may get weird errors when Chef client runs the script during deployment.
require'spec_helper'describe'my_flask_server::my_app_ssh'do# Serverspec examples can be found at# http://serverspec.org/resource_types.htmldescribefile('/tmp/my_flask_app/ssh/wrap-ssh-4-git.sh')doit{shouldbe_file}it{shouldbe_mode'755'}it{shouldbe_owned_by'www-data'}it{shouldbe_grouped_into'www-data'}enddescribefile('/tmp/my_flask_app/ssh/id_my_flask_app_deploy')doit{shouldbe_file}it{shouldbe_mode'600'}it{shouldbe_owned_by'www-data'}it{shouldbe_grouped_into'www-data'}endend
## Cookbook Name:: my_flask_server# Recipe:: default## Copyright (c) 2016 The Authors, All Rights Reserved.include_recipe'apt::default'include_recipe'my_flask_server::my_app_dir'include_recipe'my_flask_server::my_app_python'include_recipe'my_flask_server::my_app_ssh'
The test application is available in the my_flask_app repository on Bitbucket. Make sure you have forked it, and configured your SSH key, as explained earlier in this tutorial.
require'spec_helper'describe'my_flask_server::my_app_deploy'do# Serverspec examples can be found at# http://serverspec.org/resource_types.html# verify git deploymentdescribefile('/var/www/my_flask_app/current')doit{shouldbe_symlink}enddescribefile('/var/www/my_flask_app/current/app.py')doit{shouldexist}end# verify requirements.txt has been processed# i.e. local python packages like `Flask` have been installeddescribecommand('/var/www/my_flask_app/shared/.env2/bin/pip list')doits(:stdout){shouldcontain'Flask'}its(:exit_status){shouldeq0}endend
## Cookbook Name:: my_flask_server# Recipe:: my_app_deploy## Copyright (c) 2016 The Authors, All Rights Reserved.include_recipe'git::default'# checkout app from git repo / master branch# creates `releases`, and `current` directories# links `current` to latest revisiondeploy_revision'/var/www/my_flask_app'doaction:deployrepo'ssh://git@bitbucket.org/vkantchev/my_flask_app.git'branch'master'user'www-data'group'www-data'ssh_wrapper'/tmp/my_flask_app/ssh/wrap-ssh-4-git.sh'purge_before_symlink[]create_dirs_before_symlink[]symlinks({})migratefalsesymlink_before_migrate({})end# install python packages in `my_flask_app_env` via pip# `my_flask_app_env` is defined in the `my_app_python.rb`pip_requirements'/var/www/my_flask_app/current/requirements.txt'dovirtualenv'my_flask_app_env'user'www-data'group'www-data'action:installend
## Cookbook Name:: my_flask_server# Recipe:: default## Copyright (c) 2016 The Authors, All Rights Reserved.include_recipe'apt::default'include_recipe'my_flask_server::my_app_dir'include_recipe'my_flask_server::my_app_python'include_recipe'my_flask_server::my_app_ssh'include_recipe'my_flask_server::my_app_deploy'
Add this content to the files/default/uwsgi/my_flask_app.ini:
# See:# http://uwsgi-docs.readthedocs.org/en/latest/WSGIquickstart.html# http://uwsgi-docs.readthedocs.org/en/latest/Upstart.html# http://uwsgi-docs.readthedocs.org/en/latest/Options.html#plugin-python[uwsgi]# socket configurationsocket=/var/www/my_flask_app/shared/.uwsgi/my_flask_app.sockchmod-socket=664vacuum=true# process configurationmaster=trueprocesses=2threads=4die-on-term=true# app configuration# virtual environmentvirtualenv=/var/www/my_flask_app/shared/.env2# call the app instance from the app.py modulechdir=/var/www/my_flask_app/currentmodule=appcallable=app
IMPORTANT: Make sure the file uses Unix Line Ending (\n, LF) and UTF-8 encoding. Otherwise you may get weird errors when Chef client runs the script during deployment.
Add this content to the files/default/uwsgi/my_flask_app.conf:
description "uWSGI instance to serve my_flask_app"
start on runlevel [2345]
stop on runlevel [!2345]
setuid www-data
setgid www-data
script
cd /var/www/my_flask_app/shared
. .env2/bin/activate
uwsgi --ini .uwsgi/my_flask_app.ini
end script
IMPORTANT: Make sure the file uses Unix Line Ending (\n, LF) and UTF-8 encoding. Otherwise you may get weird errors when Chef client runs the script during deployment.
## Cookbook Name:: my_flask_server# Recipe:: default## Copyright (c) 2016 The Authors, All Rights Reserved.include_recipe'apt::default'include_recipe'my_flask_server::my_app_dir'include_recipe'my_flask_server::my_app_python'include_recipe'my_flask_server::my_app_ssh'include_recipe'my_flask_server::my_app_deploy'include_recipe'my_flask_server::my_app_uwsgi'
Rename test/integration/default/serverspec/default_spec.rb to test/integration/default/serverspec/my_app_nginx_spec.rb
Replace the contents of my_app_nginx_spec.rb with this code:
require'spec_helper'describe'my_flask_server::my_app_nginx'do# Serverspec examples can be found at# http://serverspec.org/resource_types.html# verify nginx packagedescribepackage('nginx')doit{shouldbe_installed}end# verify nginx sericedescribeservice('nginx')doit{shouldbe_enabled}it{shouldbe_running}endend
Add this content to the files/default/nginx/my_flask_app:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
# Make site accessible from http://localhost/
server_name localhost;
location / {
include uwsgi_params;
uwsgi_pass unix:/var/www/my_flask_app/shared/.uwsgi/my_flask_app.sock;
}
}
IMPORTANT: Make sure the file uses Unix Line Ending (\n, LF) and UTF-8 encoding. Otherwise you may get weird errors when Chef client runs the script during deployment.
## Cookbook Name:: my_flask_server# Recipe:: default## Copyright (c) 2016 The Authors, All Rights Reserved.include_recipe'apt::default'include_recipe'my_flask_server::my_app_dir'include_recipe'my_flask_server::my_app_python'include_recipe'my_flask_server::my_app_ssh'include_recipe'my_flask_server::my_app_deploy'include_recipe'my_flask_server::my_app_uwsgi'include_recipe'my_flask_server::my_app_nginx'
If you do not have Chocolatey, you can install it by following the instructions on chocolatey.org. You may also see this post for instructions on how to set the Chocolatey cache location.
The first step is to create the recipe file, install_nginx.rb. Run the following command to generate it:
chefgeneraterecipeinstall_nginx
Write out recipes/install_nginx.rb like this:
## Cookbook Name:: my_ubuntu_nginx# Recipe:: install_nginx## Copyright (c) 2016 The Authors, All Rights Reserved.# Only needed if you want to install latest stable package from nginx.orginclude_recipe'nginx::repo'package'nginx'doaction:installendservice'nginx'dosupportsstatus:true,restart:true,reload:trueaction:enableend
Add this line to cookbooks/my_web_server/recipes/default.rb:
include_recipe'my_ubuntu_nginx::install_nginx'
Here is the complete file:
## Cookbook Name:: my_ubuntu_nginx# Recipe:: default## Copyright (c) 2016 The Authors, All Rights Reserved.include_recipe'apt::default'include_recipe'my_ubuntu_nginx::install_nginx'
Replace the contents of test/integration/default/serverspec/default_spec.rb with this code:
require'spec_helper'describe'my_ubuntu_nginx::default'do# Serverspec examples can be found at# http://serverspec.org/resource_types.htmldescribepackage('nginx')doit{shouldbe_installed}enddescribeservice('nginx')doit{shouldbe_enabled}it{shouldbe_running}endend