├── Chapter01 ├── requirements.txt ├── README.md └── hello.py ├── Chapter02 ├── requirements.txt ├── README.md ├── mydb.db ├── flask_test.py └── app.py ├── Chapter05 ├── node_modules │ ├── .bin │ │ ├── r.js │ │ └── r_js │ └── requirejs │ │ ├── README.md │ │ └── package.json ├── requirements.txt ├── README.md ├── __pycache__ │ └── requests.cpython-34.pyc ├── static │ ├── components │ │ ├── templatetweet.js │ │ ├── TweetList.js │ │ └── Tweet.js │ ├── main.js │ └── style.css ├── webpack.config.js ├── templates │ ├── layout.html │ ├── login.html │ ├── profile.html │ ├── signup.html │ └── index.html ├── package.json ├── requests.py └── app.py ├── Chapter03 ├── requirements.txt ├── README.md ├── mydb.db ├── templates │ ├── addname.html │ ├── main.html │ ├── addtweets.html │ └── adduser.html ├── static │ ├── tweet.js │ ├── app.js │ └── style.css └── flask_test.py ├── Chapter04 ├── requirements.txt ├── README.md ├── templates │ ├── addname.html │ ├── main.html │ ├── addtweets.html │ └── adduser.html ├── static │ ├── tweet.js │ ├── app.js │ └── style.css └── flask_test.py ├── Chapter07 ├── eventsourcing │ ├── errors.py │ ├── events.py │ ├── commands.py │ ├── aggregate.py │ ├── main.py │ └── command_handler.py ├── README.md ├── static │ ├── dispatcher.jsx │ ├── constants.jsx │ ├── actions │ │ ├── Tactions.jsx │ │ └── SActions.jsx │ ├── components │ │ ├── TweetList.jsx │ │ ├── templatetweet.jsx │ │ └── Tweet.jsx │ ├── API.jsx │ ├── main.jsx │ ├── stores │ │ └── TStore.jsx │ └── style.css ├── __pycache__ │ ├── models.cpython-34.pyc │ └── requests.cpython-34.pyc ├── requirements.txt ├── webpack.config.js ├── templates │ ├── layout.html │ ├── login.html │ ├── profile.html │ ├── signup.html │ └── index.html ├── build.js ├── package.json ├── requests.py └── app.py ├── Chapter06 ├── README.md ├── static │ ├── dispatcher.jsx │ ├── constants.jsx │ ├── actions │ │ ├── Tactions.jsx │ │ └── SActions.jsx │ ├── components │ │ ├── TweetList.jsx │ │ ├── templatetweet.jsx │ │ └── Tweet.jsx │ ├── API.jsx │ ├── main.jsx │ ├── stores │ │ └── TStore.jsx │ └── style.css ├── requirements.txt ├── webpack.config.js ├── templates │ ├── layout.html │ ├── login.html │ ├── profile.html │ ├── signup.html │ └── index.html ├── package.json ├── requests.py └── app.py ├── Chapter08 ├── README.md ├── static │ ├── dispatcher.jsx │ ├── constants.jsx │ ├── actions │ │ ├── Tactions.jsx │ │ └── SActions.jsx │ ├── components │ │ ├── TweetList.jsx │ │ ├── templatetweet.jsx │ │ └── Tweet.jsx │ ├── API.jsx │ ├── main.jsx │ ├── stores │ │ └── TStore.jsx │ └── style.css ├── requirements.txt ├── webpack.config.js ├── templates │ ├── layout.html │ ├── profile.html │ ├── signup.html │ ├── login.html │ └── index.html ├── build.js ├── package.json └── request.py ├── Chapter10 ├── README.md ├── app │ ├── cloud-native-app │ │ ├── requirements.txt │ │ ├── static │ │ │ ├── dispatcher.jsx │ │ │ ├── constants.jsx │ │ │ ├── actions │ │ │ │ ├── Tactions.jsx │ │ │ │ └── SActions.jsx │ │ │ ├── components │ │ │ │ ├── TweetList.jsx │ │ │ │ ├── templatetweet.jsx │ │ │ │ └── Tweet.jsx │ │ │ ├── API.jsx │ │ │ ├── main.jsx │ │ │ ├── stores │ │ │ │ └── TStore.jsx │ │ │ └── style.css │ │ ├── __pycache__ │ │ │ ├── models.cpython-34.pyc │ │ │ └── requests.cpython-34.pyc │ │ ├── webpack.config.js │ │ ├── templates │ │ │ ├── layout.html │ │ │ ├── login.html │ │ │ ├── profile.html │ │ │ ├── signup.html │ │ │ └── index.html │ │ ├── build.js │ │ ├── package.json │ │ └── requests.py │ └── Dockerfile └── mongodb │ └── Dockerfile ├── Chapter11 ├── README.md ├── terraform-app │ ├── terraform.tfstate │ ├── variables.tf │ └── main.tf └── cloudformation │ └── vpc.template ├── .gitattributes ├── .gitignore ├── LICENSE └── README.md /Chapter01/requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | -------------------------------------------------------------------------------- /Chapter02/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==2.3.2 2 | nose 3 | -------------------------------------------------------------------------------- /Chapter05/node_modules/.bin/r.js: -------------------------------------------------------------------------------- 1 | ../requirejs/bin/r.js -------------------------------------------------------------------------------- /Chapter05/node_modules/.bin/r_js: -------------------------------------------------------------------------------- 1 | ../requirejs/bin/r.js -------------------------------------------------------------------------------- /Chapter03/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==2.3.2 2 | flask-cors==3.0.2 3 | -------------------------------------------------------------------------------- /Chapter04/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==2.3.2 2 | pymongo==3.4.0 3 | flask-cors==3.0.2 4 | -------------------------------------------------------------------------------- /Chapter05/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==2.3.2 2 | pymongo==3.4.0 3 | flask-cors==6.0.0 4 | -------------------------------------------------------------------------------- /Chapter07/eventsourcing/errors.py: -------------------------------------------------------------------------------- 1 | class InvalidOperationError(RuntimeError): 2 | pass 3 | -------------------------------------------------------------------------------- /Chapter01/README.md: -------------------------------------------------------------------------------- 1 | # Cloud-Native-Python - Chapter 01 2 | Cloud Native Python by Packtpub 3 | -------------------------------------------------------------------------------- /Chapter02/README.md: -------------------------------------------------------------------------------- 1 | # Cloud-Native-Python - Chapter 02 2 | Cloud Native Python by Packtpub 3 | -------------------------------------------------------------------------------- /Chapter03/README.md: -------------------------------------------------------------------------------- 1 | # Cloud-Native-Python - Chapter 03 2 | Cloud Native Python by Packtpub 3 | -------------------------------------------------------------------------------- /Chapter04/README.md: -------------------------------------------------------------------------------- 1 | # Cloud-Native-Python - Chapter 04 2 | Cloud Native Python by Packtpub 3 | -------------------------------------------------------------------------------- /Chapter05/README.md: -------------------------------------------------------------------------------- 1 | # Cloud-Native-Python - Chapter 05 2 | Cloud Native Python by Packtpub 3 | -------------------------------------------------------------------------------- /Chapter06/README.md: -------------------------------------------------------------------------------- 1 | # Cloud-Native-Python - Chapter 06 2 | Cloud Native Python by Packtpub 3 | -------------------------------------------------------------------------------- /Chapter07/README.md: -------------------------------------------------------------------------------- 1 | # Cloud-Native-Python - Chapter 07 2 | Cloud Native Python by Packtpub 3 | -------------------------------------------------------------------------------- /Chapter08/README.md: -------------------------------------------------------------------------------- 1 | # Cloud-Native-Python - Chapter 08 2 | Cloud Native Python by Packtpub 3 | -------------------------------------------------------------------------------- /Chapter10/README.md: -------------------------------------------------------------------------------- 1 | # Cloud-Native-Python - Chapter 10 2 | Cloud Native Python by Packtpub 3 | -------------------------------------------------------------------------------- /Chapter11/README.md: -------------------------------------------------------------------------------- 1 | # Cloud-Native-Python - Chapter 11 2 | Cloud Native Python by Packtpub 3 | -------------------------------------------------------------------------------- /Chapter02/mydb.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Cloud-Native-Python/HEAD/Chapter02/mydb.db -------------------------------------------------------------------------------- /Chapter03/mydb.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Cloud-Native-Python/HEAD/Chapter03/mydb.db -------------------------------------------------------------------------------- /Chapter06/static/dispatcher.jsx: -------------------------------------------------------------------------------- 1 | import Flux from 'flux'; 2 | 3 | export default new Flux.Dispatcher(); 4 | -------------------------------------------------------------------------------- /Chapter07/static/dispatcher.jsx: -------------------------------------------------------------------------------- 1 | import Flux from 'flux'; 2 | 3 | export default new Flux.Dispatcher(); 4 | -------------------------------------------------------------------------------- /Chapter08/static/dispatcher.jsx: -------------------------------------------------------------------------------- 1 | import Flux from 'flux'; 2 | 3 | export default new Flux.Dispatcher(); 4 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==2.3.2 2 | pymongo==3.4.0 3 | flask-cors==3.0.2 4 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/static/dispatcher.jsx: -------------------------------------------------------------------------------- 1 | import Flux from 'flux'; 2 | 3 | export default new Flux.Dispatcher(); 4 | -------------------------------------------------------------------------------- /Chapter06/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==2.3.2 2 | pymongo==3.4.0 3 | flask-cors==6.0.0 4 | bcrypt 5 | flask-pymongo 6 | flask-mongoalchemy 7 | -------------------------------------------------------------------------------- /Chapter06/static/constants.jsx: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | RECEIVED_TWEETS: 'RECEIVED_TWEETS', 4 | RECEIVED_TWEET: 'RECEIVED_TWEET', 5 | } 6 | -------------------------------------------------------------------------------- /Chapter07/static/constants.jsx: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | RECIEVED_TWEETS: 'RECIEVED_TWEETS', 4 | RECIEVED_TWEET: 'RECIEVED_TWEET', 5 | } 6 | -------------------------------------------------------------------------------- /Chapter08/static/constants.jsx: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | RECIEVED_TWEETS: 'RECIEVED_TWEETS', 4 | RECIEVED_TWEET: 'RECIEVED_TWEET', 5 | } 6 | -------------------------------------------------------------------------------- /Chapter07/__pycache__/models.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Cloud-Native-Python/HEAD/Chapter07/__pycache__/models.cpython-34.pyc -------------------------------------------------------------------------------- /Chapter07/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==2.3.2 2 | pymongo==4.6.3 3 | flask-cors==3.0.2 4 | bcrypt 5 | pymongo 6 | flask-pymongo 7 | auth0-python 8 | requests 9 | -------------------------------------------------------------------------------- /Chapter08/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==2.3.2 2 | pymongo==3.4.0 3 | flask-cors==3.0.2 4 | bcrypt 5 | pymongo 6 | flask-pymongo 7 | auth0-python 8 | requests 9 | -------------------------------------------------------------------------------- /Chapter05/__pycache__/requests.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Cloud-Native-Python/HEAD/Chapter05/__pycache__/requests.cpython-34.pyc -------------------------------------------------------------------------------- /Chapter07/__pycache__/requests.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Cloud-Native-Python/HEAD/Chapter07/__pycache__/requests.cpython-34.pyc -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/static/constants.jsx: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | RECIEVED_TWEETS: 'RECIEVED_TWEETS', 4 | RECIEVED_TWEET: 'RECIEVED_TWEET', 5 | } 6 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/__pycache__/models.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Cloud-Native-Python/HEAD/Chapter10/app/cloud-native-app/__pycache__/models.cpython-34.pyc -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/__pycache__/requests.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Cloud-Native-Python/HEAD/Chapter10/app/cloud-native-app/__pycache__/requests.cpython-34.pyc -------------------------------------------------------------------------------- /Chapter01/hello.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | app = Flask(__name__) 3 | 4 | @app.route("/") 5 | def hello(): 6 | return "Hello World!" 7 | 8 | if __name__ == '__main__': 9 | app.run(host='0.0.0.0', port=5000, debug=True) 10 | -------------------------------------------------------------------------------- /Chapter05/node_modules/requirejs/README.md: -------------------------------------------------------------------------------- 1 | # requirejs 2 | 3 | RequireJS for use in Node. includes: 4 | 5 | * r.js: the RequireJS optimizer, and AMD runtime for use in Node. 6 | * require.js: The browser-based AMD loader. 7 | 8 | More information at http://requirejs.org 9 | 10 | -------------------------------------------------------------------------------- /Chapter06/static/actions/Tactions.jsx: -------------------------------------------------------------------------------- 1 | import API from "../API" 2 | 3 | export default{ 4 | getAllTweets(){ 5 | // console.log(1, "Tactions for tweets"); 6 | API.getAllTweets(); 7 | }, 8 | sendTweet(body, user){ 9 | API.addTweet(body, user); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Chapter07/static/actions/Tactions.jsx: -------------------------------------------------------------------------------- 1 | import API from "../API" 2 | 3 | export default{ 4 | getAllTweets(){ 5 | // console.log(1, "Tactions for tweets"); 6 | API.getAllTweets(); 7 | }, 8 | sendTweet(body, user){ 9 | API.addTweet(body, user); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Chapter08/static/actions/Tactions.jsx: -------------------------------------------------------------------------------- 1 | import API from "../API" 2 | 3 | export default{ 4 | getAllTweets(){ 5 | // console.log(1, "Tactions for tweets"); 6 | API.getAllTweets(); 7 | }, 8 | sendTweet(body, user){ 9 | API.addTweet(body, user); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/static/actions/Tactions.jsx: -------------------------------------------------------------------------------- 1 | import API from "../API" 2 | 3 | export default{ 4 | getAllTweets(){ 5 | // console.log(1, "Tactions for tweets"); 6 | API.getAllTweets(); 7 | }, 8 | sendTweet(body, user){ 9 | API.addTweet(body, user); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Chapter11/terraform-app/terraform.tfstate: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "terraform_version": "0.9.6", 4 | "serial": 17, 5 | "lineage": "3b9d2a92-9fe3-45c4-8c7a-db5f75a43efa", 6 | "modules": [ 7 | { 8 | "path": [ 9 | "root" 10 | ], 11 | "outputs": {}, 12 | "resources": {}, 13 | "depends_on": [] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /Chapter05/static/components/templatetweet.js: -------------------------------------------------------------------------------- 1 | export default class Tweettemplate extends React.Component { 2 | render(){ 3 | return( 4 |
  • 5 | play_arrow 6 | {this.props.tweetedby} 7 |

    {this.props.body}

    8 |

    {this.props.timestamp}

    9 |
  • 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter05/static/components/TweetList.js: -------------------------------------------------------------------------------- 1 | import Tweettemplate from './templatetweet' 2 | 3 | export default class TweetList extends React.Component { 4 | render(){ 5 | let tweetlist = this.props.tweet.map(tweet => ); 6 | return( 7 |
    8 | 11 |
    12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter06/static/components/TweetList.jsx: -------------------------------------------------------------------------------- 1 | import Tweettemplate from './templatetweet' 2 | 3 | export default class TweetList extends React.Component { 4 | render(){ 5 | let tweetlist = this.props.tweet.map(tweet => ); 6 | return( 7 |
    8 |
      9 | {tweetlist} 10 |
    11 |
    12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter06/static/components/templatetweet.jsx: -------------------------------------------------------------------------------- 1 | export default class Tweettemplate extends React.Component { 2 | render(){ 3 | return( 4 |
  • 5 | play_arrow 6 | {this.props.tweetedby} 7 |

    {this.props.body}

    8 |

    {this.props.updatedate}

    9 |
  • 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter07/static/components/TweetList.jsx: -------------------------------------------------------------------------------- 1 | import Tweettemplate from './templatetweet' 2 | 3 | export default class TweetList extends React.Component { 4 | render(){ 5 | let tweetlist = this.props.tweet.map(tweet => ); 6 | return( 7 |
    8 |
      9 | {tweetlist} 10 |
    11 |
    12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter07/static/components/templatetweet.jsx: -------------------------------------------------------------------------------- 1 | export default class Tweettemplate extends React.Component { 2 | render(){ 3 | return( 4 |
  • 5 | play_arrow 6 | {this.props.tweetedby} 7 |

    {this.props.body}

    8 |

    {this.props.updatedate}

    9 |
  • 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter08/static/components/TweetList.jsx: -------------------------------------------------------------------------------- 1 | import Tweettemplate from './templatetweet' 2 | 3 | export default class TweetList extends React.Component { 4 | render(){ 5 | let tweetlist = this.props.tweet.map(tweet => ); 6 | return( 7 |
    8 |
      9 | {tweetlist} 10 |
    11 |
    12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter08/static/components/templatetweet.jsx: -------------------------------------------------------------------------------- 1 | export default class Tweettemplate extends React.Component { 2 | render(){ 3 | return( 4 |
  • 5 | play_arrow 6 | {this.props.tweetedby} 7 |

    {this.props.body}

    8 |

    {this.props.updatedate}

    9 |
  • 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter07/eventsourcing/events.py: -------------------------------------------------------------------------------- 1 | class UserRegisterEvent(object): 2 | def apply_changes(self, userdetails): 3 | id = userdetails.id 4 | name = userdetails.name 5 | password = userdetails.password 6 | emailid = userdetails.emailid 7 | 8 | class UserPasswordEvent(object): 9 | def __init__(self, password): 10 | self.password = password 11 | 12 | def apply_changes(password): 13 | user.password = password 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /Chapter05/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: "./static/main.js", 3 | output: { 4 | path: __dirname + "/static/build/", 5 | filename: "bundle.js" 6 | }, 7 | resolve: { 8 | extensions: ['', '.js', '.jsx'] 9 | }, 10 | module: { 11 | loaders: [ 12 | { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", query:{presets:['react','es2015']} } 13 | ] 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /Chapter06/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: "./static/main.jsx", 3 | output: { 4 | path: __dirname + "/static/build/", 5 | filename: "bundle.js" 6 | }, 7 | resolve: { 8 | extensions: ['', '.js', '.jsx'] 9 | }, 10 | module: { 11 | loaders: [ 12 | { test: /\.jsx$/, exclude: /node_modules/, loader: "babel-loader", query:{presets:['react','es2015']} } 13 | ] 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /Chapter07/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: "./static/main.jsx", 3 | output: { 4 | path: __dirname + "/static/build/", 5 | filename: "bundle.js" 6 | }, 7 | resolve: { 8 | extensions: ['', '.js', '.jsx'] 9 | }, 10 | module: { 11 | loaders: [ 12 | { test: /\.jsx$/, exclude: /node_modules/, loader: "babel-loader", query:{presets:['react','es2015']} } 13 | ] 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /Chapter08/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: "./static/main.jsx", 3 | output: { 4 | path: __dirname + "/static/build/", 5 | filename: "bundle.js" 6 | }, 7 | resolve: { 8 | extensions: ['', '.js', '.jsx'] 9 | }, 10 | module: { 11 | loaders: [ 12 | { test: /\.jsx$/, exclude: /node_modules/, loader: "babel-loader", query:{presets:['react','es2015']} } 13 | ] 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/static/components/TweetList.jsx: -------------------------------------------------------------------------------- 1 | import Tweettemplate from './templatetweet' 2 | 3 | export default class TweetList extends React.Component { 4 | render(){ 5 | let tweetlist = this.props.tweet.map(tweet => ); 6 | return( 7 |
    8 |
      9 | {tweetlist} 10 |
    11 |
    12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/static/components/templatetweet.jsx: -------------------------------------------------------------------------------- 1 | export default class Tweettemplate extends React.Component { 2 | render(){ 3 | return( 4 |
  • 5 | play_arrow 6 | {this.props.tweetedby} 7 |

    {this.props.body}

    8 |

    {this.props.updatedate}

    9 |
  • 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: "./static/main.jsx", 3 | output: { 4 | path: __dirname + "/static/build/", 5 | filename: "bundle.js" 6 | }, 7 | resolve: { 8 | extensions: ['', '.js', '.jsx'] 9 | }, 10 | module: { 11 | loaders: [ 12 | { test: /\.jsx$/, exclude: /node_modules/, loader: "babel-loader", query:{presets:['react','es2015']} } 13 | ] 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /Chapter06/static/actions/SActions.jsx: -------------------------------------------------------------------------------- 1 | import AppDispatcher from '../dispatcher'; 2 | import ActionTypes from '../constants' 3 | 4 | export default{ 5 | receivedTweets(rawTweets){ 6 | // console.log(3, rawTweets); 7 | AppDispatcher.dispatch({ 8 | actionType: ActionTypes.RECEIVED_TWEETS, 9 | rawTweets 10 | }) 11 | }, 12 | receivedTweet(rawTweet){ 13 | AppDispatcher.dispatch({ 14 | actionType: ActionTypes.RECEIVED_TWEET, 15 | rawTweet 16 | }) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter07/static/actions/SActions.jsx: -------------------------------------------------------------------------------- 1 | import AppDispatcher from '../dispatcher'; 2 | import ActionTypes from '../constants' 3 | 4 | export default{ 5 | recievedTweets(rawTweets){ 6 | // console.log(3, rawTweets); 7 | AppDispatcher.dispatch({ 8 | actionType: ActionTypes.RECIEVED_TWEETS, 9 | rawTweets 10 | }) 11 | }, 12 | recievedTweet(rawTweet){ 13 | AppDispatcher.dispatch({ 14 | actionType: ActionTypes.RECIEVED_TWEET, 15 | rawTweet 16 | }) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter08/static/actions/SActions.jsx: -------------------------------------------------------------------------------- 1 | import AppDispatcher from '../dispatcher'; 2 | import ActionTypes from '../constants' 3 | 4 | export default{ 5 | recievedTweets(rawTweets){ 6 | // console.log(3, rawTweets); 7 | AppDispatcher.dispatch({ 8 | actionType: ActionTypes.RECIEVED_TWEETS, 9 | rawTweets 10 | }) 11 | }, 12 | recievedTweet(rawTweet){ 13 | AppDispatcher.dispatch({ 14 | actionType: ActionTypes.RECIEVED_TWEET, 15 | rawTweet 16 | }) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter05/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cloud-native-app 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% block body %}{% endblock %} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Chapter06/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cloud-native-app 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% block body %}{% endblock %} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Chapter07/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cloud-native-app 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% block body %}{% endblock %} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Chapter08/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cloud-native-app 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% block body %}{% endblock %} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/static/actions/SActions.jsx: -------------------------------------------------------------------------------- 1 | import AppDispatcher from '../dispatcher'; 2 | import ActionTypes from '../constants' 3 | 4 | export default{ 5 | recievedTweets(rawTweets){ 6 | // console.log(3, rawTweets); 7 | AppDispatcher.dispatch({ 8 | actionType: ActionTypes.RECIEVED_TWEETS, 9 | rawTweets 10 | }) 11 | }, 12 | recievedTweet(rawTweet){ 13 | AppDispatcher.dispatch({ 14 | actionType: ActionTypes.RECIEVED_TWEET, 15 | rawTweet 16 | }) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cloud-native-app 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% block body %}{% endblock %} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Chapter07/eventsourcing/commands.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import os 3 | 4 | class userregister(object): 5 | def __init__(self, user_id, user_name, password, emailid): 6 | self.user_id = user_id 7 | self.user_name = user_name 8 | self.password = password 9 | self.emailid = emaild 10 | 11 | class updatepassword(object): 12 | def __init__(self, user_id, new_password, original_version): 13 | self.item_id = item_id 14 | self.new_password = new__password 15 | self.original_version = original_version 16 | -------------------------------------------------------------------------------- /Chapter07/eventsourcing/aggregate.py: -------------------------------------------------------------------------------- 1 | class Aggregate(object): 2 | def __init__(self): 3 | self.uncommitted_changes = [] 4 | 5 | @classmethod 6 | def from_events(cls, events): 7 | aggregate = cls() 8 | for event in events: event.apply_changes(aggregate) 9 | aggregate.uncommitted_changes = [] 10 | return aggregate 11 | 12 | def changes_committed(self): 13 | self.uncommitted_changes = [] 14 | 15 | def _apply_changes(self, event): 16 | self.uncommitted_changes.append(event) 17 | event.apply_changes(self) 18 | -------------------------------------------------------------------------------- /Chapter07/build.js: -------------------------------------------------------------------------------- 1 | ({ 2 | preserveLicenseComments: false, 3 | optimize: "uglify2", 4 | uglify2: { 5 | output: { 6 | beautify: false, 7 | comments: false 8 | }, 9 | compress: { 10 | drop_console: true 11 | } 12 | }, 13 | paths: { 14 | jquery: ".", 15 | jsx: "vendors/jsx-requirejs-plugin/js/jsx", 16 | JSXTransformer: "vendors/jsx-requirejs-plugin/js/JSXTransformer", 17 | text: "vendors/requirejs-text/text", 18 | react: "vendors/react/react-with-addons.min" 19 | }, 20 | jsx: { 21 | fileExtension: ".jsx" 22 | }, 23 | stubModules: ["jsx", "JSXTransformer", "text"] 24 | }) 25 | -------------------------------------------------------------------------------- /Chapter08/build.js: -------------------------------------------------------------------------------- 1 | ({ 2 | preserveLicenseComments: false, 3 | optimize: "uglify2", 4 | uglify2: { 5 | output: { 6 | beautify: false, 7 | comments: false 8 | }, 9 | compress: { 10 | drop_console: true 11 | } 12 | }, 13 | paths: { 14 | jquery: ".", 15 | jsx: "vendors/jsx-requirejs-plugin/js/jsx", 16 | JSXTransformer: "vendors/jsx-requirejs-plugin/js/JSXTransformer", 17 | text: "vendors/requirejs-text/text", 18 | react: "vendors/react/react-with-addons.min" 19 | }, 20 | jsx: { 21 | fileExtension: ".jsx" 22 | }, 23 | stubModules: ["jsx", "JSXTransformer", "text"] 24 | }) 25 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/build.js: -------------------------------------------------------------------------------- 1 | ({ 2 | preserveLicenseComments: false, 3 | optimize: "uglify2", 4 | uglify2: { 5 | output: { 6 | beautify: false, 7 | comments: false 8 | }, 9 | compress: { 10 | drop_console: true 11 | } 12 | }, 13 | paths: { 14 | jquery: ".", 15 | jsx: "vendors/jsx-requirejs-plugin/js/jsx", 16 | JSXTransformer: "vendors/jsx-requirejs-plugin/js/JSXTransformer", 17 | text: "vendors/requirejs-text/text", 18 | react: "vendors/react/react-with-addons.min" 19 | }, 20 | jsx: { 21 | fileExtension: ".jsx" 22 | }, 23 | stubModules: ["jsx", "JSXTransformer", "text"] 24 | }) 25 | -------------------------------------------------------------------------------- /Chapter07/eventsourcing/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from aggregate import Aggregate 4 | from errors import InvalidOperationError 5 | from events import * 6 | 7 | class userdetails(Aggregate): 8 | def __init__(self, id = None, name = '””, password = “”, emailid = “” ): 9 | Aggregate.__init__(self) 10 | self._apply_changes(Userdetails(id, name, password, emailid)) 11 | 12 | def userRegister(self, userdetails): 13 | userdetails = {1, “robin99”, “xxxxxx”, “robinatkevin@gmail.com” } 14 | self._apply_changes(UserRegisterevent(userdetails)) 15 | 16 | 17 | def updatePassword(self, count): 18 | password = “” 19 | self._apply_changes(UserPasswordEvent(password)) 20 | -------------------------------------------------------------------------------- /Chapter10/mongodb/Dockerfile: -------------------------------------------------------------------------------- 1 | # MongoDB Dockerfile 2 | # Pull base image. 3 | FROM ubuntu 4 | MAINTAINER Manish Sethi 5 | # Install MongoDB. 6 | RUN \ 7 | apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 && \ 8 | echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' > /etc/apt/sources.list.d/mongodb.list && \ 9 | apt-get update && \ 10 | apt-get install -y mongodb-org && \ 11 | rm -rf /var/lib/apt/lists/* 12 | 13 | # Define mountable directories. 14 | VOLUME ["/data/db"] 15 | 16 | # Define working directory. 17 | WORKDIR /data 18 | 19 | # Define default command. 20 | CMD ["mongod"] 21 | 22 | # Expose ports. 23 | EXPOSE 27017 24 | EXPOSE 28017 25 | 26 | -------------------------------------------------------------------------------- /Chapter05/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "twitter", 3 | "version": "1.0.0", 4 | "description": "Twitter App", 5 | "main": "index.js", 6 | "dependencies": { 7 | "babel-loader": "^6.4.1", 8 | "fbjs": "^0.8.11", 9 | "object-assign": "^4.1.1", 10 | "react": "^15.4.2", 11 | "react-dev": "0.0.1", 12 | "react-dom": "^0.14.7", 13 | "requirejs": "^2.3.3" 14 | }, 15 | "devDependencies": { 16 | "babel-core": "^6.4.5", 17 | "babel-loader": "^6.2.1", 18 | "babel-preset-es2015": "^6.3.13", 19 | "babel-preset-react": "^6.3.13", 20 | "webpack": "^1.12.12" 21 | }, 22 | "scripts": { 23 | "test": "echo \"Error: no test specified\" && exit 1" 24 | }, 25 | "author": "Manish Sethi", 26 | "license": "ISC" 27 | } 28 | -------------------------------------------------------------------------------- /Chapter06/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "twitter", 3 | "version": "1.0.0", 4 | "description": "Twitter App", 5 | "main": "index.js", 6 | "dependencies": { 7 | "babel-loader": "^6.4.1", 8 | "events": "^1.1.1", 9 | "fbjs": "^0.8.11", 10 | "flux": "^3.1.2", 11 | "object-assign": "^4.1.1", 12 | "react": "^15.4.2", 13 | "react-dev": "0.0.1", 14 | "react-dom": "^0.14.7", 15 | "requirejs": "^2.3.3" 16 | }, 17 | "devDependencies": { 18 | "babel-core": "^6.4.5", 19 | "babel-loader": "^6.2.1", 20 | "babel-preset-es2015": "^6.3.13", 21 | "babel-preset-react": "^6.3.13", 22 | "webpack": "^1.12.12" 23 | }, 24 | "scripts": { 25 | "test": "echo \"Error: no test specified\" && exit 1" 26 | }, 27 | "author": "Manish Sethi", 28 | "license": "ISC" 29 | } 30 | -------------------------------------------------------------------------------- /Chapter07/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "twitter", 3 | "version": "1.0.0", 4 | "description": "Twitter App", 5 | "main": "index.js", 6 | "dependencies": { 7 | "babel-loader": "^6.4.1", 8 | "events": "^1.1.1", 9 | "fbjs": "^0.8.11", 10 | "flux": "^3.1.2", 11 | "object-assign": "^4.1.1", 12 | "react": "^15.4.2", 13 | "react-dev": "0.0.1", 14 | "react-dom": "^0.14.7", 15 | "requirejs": "^2.3.3" 16 | }, 17 | "devDependencies": { 18 | "babel-core": "^6.4.5", 19 | "babel-loader": "^6.2.1", 20 | "babel-preset-es2015": "^6.3.13", 21 | "babel-preset-react": "^6.3.13", 22 | "webpack": "^1.12.12" 23 | }, 24 | "scripts": { 25 | "test": "echo \"Error: no test specified\" && exit 1" 26 | }, 27 | "author": "Manish Sethi", 28 | "license": "ISC" 29 | } 30 | -------------------------------------------------------------------------------- /Chapter08/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "twitter", 3 | "version": "1.0.0", 4 | "description": "Twitter App", 5 | "main": "index.js", 6 | "dependencies": { 7 | "babel-loader": "^6.4.1", 8 | "events": "^1.1.1", 9 | "fbjs": "^0.8.11", 10 | "flux": "^3.1.2", 11 | "object-assign": "^4.1.1", 12 | "react": "^15.4.2", 13 | "react-dev": "0.0.1", 14 | "react-dom": "^0.14.7", 15 | "requirejs": "^2.3.3" 16 | }, 17 | "devDependencies": { 18 | "babel-core": "^6.4.5", 19 | "babel-loader": "^6.2.1", 20 | "babel-preset-es2015": "^6.3.13", 21 | "babel-preset-react": "^6.3.13", 22 | "webpack": "^1.12.12" 23 | }, 24 | "scripts": { 25 | "test": "echo \"Error: no test specified\" && exit 1" 26 | }, 27 | "author": "Manish Sethi", 28 | "license": "ISC" 29 | } 30 | -------------------------------------------------------------------------------- /Chapter07/eventsourcing/command_handler.py: -------------------------------------------------------------------------------- 1 | from commands import * 2 | 3 | class UserCommandsHandler(object): 4 | def __init__(self, user_repository): 5 | self.user_repository = user_repository 6 | 7 | def handle(self, command): 8 | if command.__class__ == UserRegisterEvent: 9 | self.user_repository.save(commands.userRegister(command.id, command.name, command.password, command.emailid)) 10 | if command.__class__ == UpdatePasswordEvent: 11 | with self._user_(commands.updatePassword(self.id, command.password, command.original_version) as user: 12 | user.update(command.password) 13 | @contextmanager 14 | def _user(self, id, user_version): 15 | user = self.user_repository.find_by_id(id) 16 | yield user 17 | self.user.save(password, user_version) 18 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "twitter", 3 | "version": "1.0.0", 4 | "description": "Twitter App", 5 | "main": "index.js", 6 | "dependencies": { 7 | "babel-loader": "^6.4.1", 8 | "events": "^1.1.1", 9 | "fbjs": "^0.8.11", 10 | "flux": "^3.1.2", 11 | "object-assign": "^4.1.1", 12 | "react": "^15.4.2", 13 | "react-dev": "0.0.1", 14 | "react-dom": "^0.14.7", 15 | "requirejs": "^2.3.3" 16 | }, 17 | "devDependencies": { 18 | "babel-core": "^6.4.5", 19 | "babel-loader": "^6.2.1", 20 | "babel-preset-es2015": "^6.3.13", 21 | "babel-preset-react": "^6.3.13", 22 | "webpack": "^1.12.12" 23 | }, 24 | "scripts": { 25 | "test": "echo \"Error: no test specified\" && exit 1" 26 | }, 27 | "author": "Manish Sethi", 28 | "license": "ISC" 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /Chapter06/static/API.jsx: -------------------------------------------------------------------------------- 1 | import SActions from './actions/SActions'; 2 | 3 | export default{ 4 | getAllTweets(){ 5 | // console.log(2, "API get tweets"); 6 | let str = "/api/v2/tweets/" + localStorage.getItem("sessionid") 7 | $.getJSON(str , function(tweetModels) { 8 | var t = tweetModels 9 | SActions.receivedTweets(t) 10 | }); 11 | }, 12 | addTweet(body, user){ 13 | $.ajax({ 14 | url: '/api/v2/tweets', 15 | contentType: 'application/json', 16 | type: 'POST', 17 | data: JSON.stringify({ 18 | 'username': user, 19 | 'body': body, 20 | }), 21 | success: function() { 22 | rawTweet => SActions.receivedTweet({ tweetedby: user,body: tweet, timestamp: Date.now}) 23 | }, 24 | error: function() { 25 | return console.log("Failed"); 26 | } 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter07/static/API.jsx: -------------------------------------------------------------------------------- 1 | import SActions from './actions/SActions'; 2 | 3 | export default{ 4 | getAllTweets(){ 5 | // console.log(2, "API get tweets"); 6 | let str = "/api/v2/tweets/" + localStorage.getItem("sessionid") 7 | $.getJSON(str , function(tweetModels) { 8 | var t = tweetModels 9 | SActions.recievedTweets(t) 10 | }); 11 | }, 12 | addTweet(body, user){ 13 | $.ajax({ 14 | url: '/api/v2/tweets', 15 | contentType: 'application/json', 16 | type: 'POST', 17 | data: JSON.stringify({ 18 | 'username': user, 19 | 'body': body, 20 | }), 21 | success: function() { 22 | rawTweet => SActions.recievedTweet({ tweetedby: user,body: tweet, timestamp: Date.now}) 23 | }, 24 | error: function() { 25 | return console.log("Failed"); 26 | } 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/static/API.jsx: -------------------------------------------------------------------------------- 1 | import SActions from './actions/SActions'; 2 | 3 | export default{ 4 | getAllTweets(){ 5 | // console.log(2, "API get tweets"); 6 | let str = "/api/v2/tweets/" + localStorage.getItem("sessionid") 7 | $.getJSON(str , function(tweetModels) { 8 | var t = tweetModels 9 | SActions.recievedTweets(t) 10 | }); 11 | }, 12 | addTweet(body, user){ 13 | $.ajax({ 14 | url: '/api/v2/tweets', 15 | contentType: 'application/json', 16 | type: 'POST', 17 | data: JSON.stringify({ 18 | 'username': user, 19 | 'body': body, 20 | }), 21 | success: function() { 22 | rawTweet => SActions.recievedTweet({ tweetedby: user,body: tweet, timestamp: Date.now}) 23 | }, 24 | error: function() { 25 | return console.log("Failed"); 26 | } 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter08/static/API.jsx: -------------------------------------------------------------------------------- 1 | import SActions from './actions/SActions'; 2 | 3 | export default{ 4 | getAllTweets(){ 5 | // console.log(2, "API get tweets"); 6 | let str = "/api/v2/tweets/" + localStorage.getItem("sessionid") 7 | $.getJSON(str , function(tweetModels) { 8 | var t = tweetModels 9 | SActions.recievedTweets(t) 10 | }); 11 | }, 12 | addTweet(body, user){ 13 | $.ajax({ 14 | url: '/api/v2/tweets', 15 | contentType: 'application/json', 16 | type: 'POST', 17 | data: JSON.stringify({ 18 | 'username': localStorage.getItem("sessionid"), 19 | 'body': body, 20 | }), 21 | success: function() { 22 | rawTweet => SActions.recievedTweet({ tweetedby: user,body: tweet, timestamp: Date.now}) 23 | }, 24 | error: function() { 25 | return console.log("Failed"); 26 | } 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter03/templates/addname.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Twitter App Demo 4 | 5 | 6 | 7 |
    8 |
    9 |

    Enter your name

    10 |
    11 |
    12 |
    13 | 14 |
    15 | 16 |
    17 |
    18 |
    19 |

    20 |
    21 |
    22 | 
    23 |                
    24 |
    25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Chapter04/templates/addname.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Twitter App Demo 5 | 6 | 7 | 8 |
    9 |
    10 |

    Enter your name

    11 |
    12 |
    13 |
    14 | 15 |
    16 | 17 |
    18 |
    19 |
    20 |

    21 |
    22 |
    23 | 
    24 |                
    25 |
    26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Chapter03/templates/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Twitter App Demo 4 | 5 | 6 | 7 |
    8 |
    9 |

    10 |
    11 |
    12 | {% if session['name'] %} 13 | Your name seems to be {{session['name']}}.
    14 | {% else %} 15 | Please set username by clicking it here.
    16 | {% endif %} 17 | Visit this for adding new application user or this to add new tweets page to interact with RESTFUL API. 18 |

    19 | Clear session 20 |
    21 |
    22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Chapter11/terraform-app/variables.tf: -------------------------------------------------------------------------------- 1 | variable "public_key_path" { 2 | default = "ms-cna.pub" 3 | } 4 | 5 | variable "key_name" { 6 | description = "Desired name of AWS key pair" 7 | default = "ms-cna" 8 | } 9 | 10 | variable "key_file_path" { 11 | description = "Private Key Location" 12 | default = "~/.ssh/ms-cna" 13 | } 14 | 15 | variable "vpc_cidr"{ 16 | default = "10.127.0.0/16" 17 | } 18 | 19 | variable "subnet_cidr"{ 20 | default = "10.127.0.0/24" 21 | } 22 | 23 | 24 | variable "aws_region" { 25 | description = "AWS region to launch servers." 26 | default = "us-east-1" 27 | } 28 | 29 | 30 | # Ubuntu Precise 12.04 LTS (x64) 31 | variable "aws_amis" { 32 | default = { 33 | eu-west-1 = "ami-b1cf19c6" 34 | us-east-1 = "ami-0a92db1d" 35 | #us-east-1 = "ami-e881c6ff" 36 | us-west-1 = "ami-3f75767a" 37 | us-west-2 = "ami-21f78e11" 38 | } 39 | } 40 | 41 | 42 | variable "aws_access_key" { 43 | description = "AWS access key" 44 | default = "" 45 | } 46 | 47 | variable "aws_secret_key" { 48 | description = "AWS secret access key" 49 | default = "" 50 | } 51 | -------------------------------------------------------------------------------- /Chapter04/templates/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Twitter App Demo 5 | 6 | 7 | 8 |
    9 |
    10 |

    11 |
    12 |
    13 | {% if session['name'] %} 14 | Your name seems to be {{session['name']}}.
    15 | {% else %} 16 | Please set username by clicking it here.
    17 | {% endif %} 18 | Visit this for adding new application user or this to add new tweets page to interact with RESTFUL API. 19 |

    20 | Clear session 21 |
    22 |
    23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Chapter10/app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04 2 | MAINTAINER Manish Sethi 3 | 4 | # no tty 5 | ENV DEBIAN_FRONTEND noninteractive 6 | 7 | # get up to date 8 | RUN apt-get -qq update --fix-missing 9 | 10 | # Bootstrap the image so that it includes all of our dependencies 11 | RUN apt-get -qq install python3 python-dev python-virtualenv python3-pip --assume-yes 12 | RUN sudo apt-get install build-essential autoconf libtool libssl-dev libffi-dev --assume-yes 13 | # Setup locale 14 | RUN export LC_ALL=en_US.UTF-8 15 | RUN export LANG=en_US.UTF-8 16 | RUN export LANGUAGE=en_US.UTF-8 17 | 18 | # copy the contents of the cloud-native-app(i.e. complete application) folder into the container at build time 19 | COPY cloud-native-app/ /app/ 20 | 21 | # Create Virtual environment 22 | RUN mkdir -p /venv/ 23 | RUN virtualenv /venv/ --python=python3 24 | 25 | # Python dependencies inside the virtualenv 26 | RUN /venv/bin/pip3 install -r /app/requirements.txt 27 | 28 | # expose a port for the flask development server 29 | EXPOSE 5000 30 | 31 | # Running our flask application 32 | CMD cd /app/ && /venv/bin/python app.py 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Chapter05/static/components/Tweet.js: -------------------------------------------------------------------------------- 1 | export default class Tweet extends React.Component { 2 | sendTweet(event){ 3 | event.preventDefault(); 4 | this.props.sendTweet(this.refs.tweetTextArea.value); 5 | this.refs.tweetTextArea.value = ''; 6 | } 7 | render(){ 8 | return( 9 |
    10 | 19 | 20 |
    21 |
    22 | 19 |
    20 |
    21 |
    22 | 23 | 24 |
    25 |
      26 |
    • 27 |

      28 |

      29 |

      30 | 31 |
    • 32 |
    33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Chapter08/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "layout.html" %} 3 | {% block body %} 4 | {% if session['logged_in'] %} 5 |

    You're logged in already!

    6 | {% else %} 7 | 8 |
    9 |
    10 | 34 |
    35 | 36 | 47 | 48 | 49 | {% endif %} 50 | {% endblock %} 51 | -------------------------------------------------------------------------------- /Chapter04/templates/addtweets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Twitter Application 5 | 6 | 7 |
    8 | 13 |
    14 | 15 | 16 | Username: 17 | 18 |
    19 | body: 20 |
    21 |
    22 |
    23 | 24 |
    25 | 26 |
      27 |
    • 28 |

      29 |

      30 |

      31 | 32 |
    • 33 |
    34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Chapter03/templates/adduser.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Twitter Application 4 | 5 | 6 |
    7 | 12 |
    13 | 14 | 15 | Name: 16 | 17 |
    18 | Username: 19 |
    20 |
    21 | email: 22 |
    23 |
    24 | password: 25 |
    26 | 27 |
    28 | 29 |
      30 |
    • 31 |

      32 |

      33 |

      34 |

      35 |
    • 36 |
    37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Chapter05/static/main.js: -------------------------------------------------------------------------------- 1 | import Tweet from "./components/Tweet"; 2 | import TweetList from "./components/TweetList"; 3 | import cookie from 'react-cookie'; 4 | 5 | 6 | 7 | class Main extends React.Component{ 8 | constructor(props){ 9 | super(props); 10 | this.state = { userId: cookie.load('session') }; 11 | this.state={tweets:[]} 12 | } 13 | // function to post tweets 14 | addTweet(tweet){ 15 | var self = this; 16 | $.ajax({ 17 | url: '/api/v2/tweets', 18 | contentType: 'application/json', 19 | type: 'POST', 20 | data: JSON.stringify({ 21 | 'username': "Saussiona55", 22 | 'body': tweet, 23 | }), 24 | success: function() { 25 | alert("success") 26 | let newTweetList = self.state.tweets; 27 | newTweetList.unshift({ tweetedby: "Saussiona55",body: tweet, timestamp: Date.now}); 28 | self.setState({tweets: newTweetList}) 29 | return; 30 | }, 31 | error: function() { 32 | return console.log("Failed"); 33 | } 34 | }); 35 | } 36 | // function to pull tweets 37 | componentDidMount() { 38 | var self=this; 39 | $.getJSON('/api/v2/tweets', function(tweetModels) { 40 | var t = tweetModels 41 | // var t = $.map(tweetModels, function(item) { 42 | // return item; 43 | // }); 44 | alert(t) 45 | self.setState({tweets: t}) 46 | }); 47 | 48 | // $.ajax("/api/v2/tweets") 49 | // // .success(data => this.setState({tweets: data})) 50 | // .success(alert(data)) 51 | // .error(error => console.log(error)); 52 | } 53 | 54 | render(){ 55 | return ( 56 |
    57 | 58 | 59 |
    60 | ); 61 | } 62 | } 63 | 64 | 65 | let documentReady =() =>{ 66 | ReactDOM.render( 67 |
    , 68 | document.getElementById('react') 69 | ); 70 | }; 71 | 72 | $(documentReady); 73 | -------------------------------------------------------------------------------- /Chapter04/templates/adduser.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Twitter Application 5 | 6 | 7 |
    8 | 13 |
    14 | 15 | 16 | Name: 17 | 18 |
    19 | Username: 20 |
    21 |
    22 | email: 23 |
    24 |
    25 | password: 26 |
    27 | 28 |
    29 | 30 |
      31 |
    • 32 |

      33 |

      34 |

      35 |

      36 |
    • 37 |
    38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Chapter06/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cloud Native App 7 | 8 | 9 | 10 | 11 |
    12 |

    13 |
    Welcome {{ session }}
    14 |
    15 |
    16 | 17 |
    18 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Chapter07/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cloud Native App 7 | 8 | 9 | 10 | 11 |
    12 |

    13 |
    Welcome {{ session }}
    14 |
    15 |
    16 | 17 |
    18 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Chapter08/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cloud Native App 7 | 8 | 9 | 10 | 11 |
    12 |

    13 |
    Welcome {{ user['nickname'] }}
    14 |
    15 |
    16 | 17 |
    18 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cloud Native App 7 | 8 | 9 | 10 | 11 |
    12 |

    13 |
    Welcome {{ session }}
    14 |
    15 |
    16 | 17 |
    18 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Chapter02/flask_test.py: -------------------------------------------------------------------------------- 1 | # Test cases for restful API 2 | from app import app 3 | import unittest 4 | 5 | class FlaskappTests(unittest.TestCase): 6 | def setUp(self): 7 | # creates a test client 8 | self.app = app.test_client() 9 | # propagate the exceptions to the test client 10 | self.app.testing = True 11 | def test_users_status_code(self): 12 | # sends HTTP GET request to the application 13 | # on the specified path 14 | result = self.app.get('/api/v1/users') 15 | print (result) 16 | # assert the status code of the response 17 | self.assertEqual(result.status_code, 200) 18 | 19 | def test_tweets_status_code(self): 20 | # sends HTTP GET request to the application 21 | # on the specified path 22 | result = self.app.get('/api/v2/tweets') 23 | 24 | # assert the status code of the response 25 | self.assertEqual(result.status_code, 200) 26 | 27 | def test_addusers_status_code(self): 28 | # sends HTTP POST request to the application 29 | # on the specified path 30 | result = self.app.post('/api/v1/users', data='{ "username":"Ovestint", "email": "ronaldrvera@jourrapide.com", "password": "juzahpei6e", "name":"Ronald R. Vera"}', content_type='application/json') 31 | print (result) 32 | # assert the status code of the response 33 | self.assertEquals(result.status_code, 201) 34 | 35 | def test_updusers_status_code(self): 36 | # sends HTTP PUT request to the application 37 | # on the specified path 38 | result = self.app.put('/api/v1/users/5', data='{"username":"Tagning", "email": "leolaLguertin@teleworm.us"}', content_type='application/json') 39 | # assert the status code of the response 40 | self.assertEquals(result.status_code, 200) 41 | def test_addtweets_status_code(self): 42 | # sends HTTP GET request to the application 43 | # on the specified path 44 | result = self.app.post('/api/v2/tweets', data='{"username":"Tagning", "body": "It Works!#Awesome"}', content_type='application/json') 45 | 46 | # assert the status code of the response 47 | self.assertEqual(result.status_code, 201) 48 | 49 | def test_delusers_status_code(self): 50 | # sends HTTP Delete request to the application 51 | # on the specified path 52 | result = self.app.delete('/api/v1/users', data='{"username":"Ovestint"}', content_type='application/json') 53 | print (result) 54 | # assert the status code of the response 55 | self.assertEquals(result.status_code, 200) 56 | -------------------------------------------------------------------------------- /Chapter03/flask_test.py: -------------------------------------------------------------------------------- 1 | # Test cases for restful API 2 | from app import app 3 | import unittest 4 | 5 | class FlaskappTests(unittest.TestCase): 6 | def setUp(self): 7 | # creates a test client 8 | self.app = app.test_client() 9 | # propagate the exceptions to the test client 10 | self.app.testing = True 11 | def test_users_status_code(self): 12 | # sends HTTP GET request to the application 13 | # on the specified path 14 | result = self.app.get('/api/v1/users') 15 | print (result) 16 | # assert the status code of the response 17 | self.assertEqual(result.status_code, 200) 18 | 19 | def test_tweets_status_code(self): 20 | # sends HTTP GET request to the application 21 | # on the specified path 22 | result = self.app.get('/api/v2/tweets') 23 | 24 | # assert the status code of the response 25 | self.assertEqual(result.status_code, 200) 26 | 27 | def test_addusers_status_code(self): 28 | # sends HTTP POST request to the application 29 | # on the specified path 30 | result = self.app.post('/api/v1/users', data='{ "username":"Ovestint", "email": "ronaldrvera@jourrapide.com", "password": "juzahpei6e", "name":"Ronald R. Vera"}', content_type='application/json') 31 | print (result) 32 | # assert the status code of the response 33 | self.assertEquals(result.status_code, 201) 34 | 35 | def test_updusers_status_code(self): 36 | # sends HTTP PUT request to the application 37 | # on the specified path 38 | result = self.app.put('/api/v1/users/5', data='{"username":"Tagning", "email": "leolaLguertin@teleworm.us"}', content_type='application/json') 39 | # assert the status code of the response 40 | self.assertEquals(result.status_code, 200) 41 | def test_addtweets_status_code(self): 42 | # sends HTTP GET request to the application 43 | # on the specified path 44 | result = self.app.post('/api/v2/tweets', data='{"username":"Tagning", "body": "It Works!#Awesome"}', content_type='application/json') 45 | 46 | # assert the status code of the response 47 | self.assertEqual(result.status_code, 201) 48 | 49 | def test_delusers_status_code(self): 50 | # sends HTTP Delete request to the application 51 | # on the specified path 52 | result = self.app.delete('/api/v1/users', data='{"username":"Ovestint"}', content_type='application/json') 53 | print (result) 54 | # assert the status code of the response 55 | self.assertEquals(result.status_code, 200) 56 | -------------------------------------------------------------------------------- /Chapter04/flask_test.py: -------------------------------------------------------------------------------- 1 | # Test cases for restful API 2 | from app import app 3 | import unittest 4 | 5 | class FlaskappTests(unittest.TestCase): 6 | def setUp(self): 7 | # creates a test client 8 | self.app = app.test_client() 9 | # propagate the exceptions to the test client 10 | self.app.testing = True 11 | def test_users_status_code(self): 12 | # sends HTTP GET request to the application 13 | # on the specified path 14 | result = self.app.get('/api/v1/users') 15 | print (result) 16 | # assert the status code of the response 17 | self.assertEqual(result.status_code, 200) 18 | 19 | def test_tweets_status_code(self): 20 | # sends HTTP GET request to the application 21 | # on the specified path 22 | result = self.app.get('/api/v2/tweets') 23 | 24 | # assert the status code of the response 25 | self.assertEqual(result.status_code, 200) 26 | 27 | def test_addusers_status_code(self): 28 | # sends HTTP POST request to the application 29 | # on the specified path 30 | result = self.app.post('/api/v1/users', data='{ "username":"Ovestint", "email": "ronaldrvera@jourrapide.com", "password": "juzahpei6e", "name":"Ronald R. Vera"}', content_type='application/json') 31 | print (result) 32 | # assert the status code of the response 33 | self.assertEquals(result.status_code, 201) 34 | 35 | def test_updusers_status_code(self): 36 | # sends HTTP PUT request to the application 37 | # on the specified path 38 | result = self.app.put('/api/v1/users/5', data='{"username":"Tagning", "email": "leolaLguertin@teleworm.us"}', content_type='application/json') 39 | # assert the status code of the response 40 | self.assertEquals(result.status_code, 200) 41 | def test_addtweets_status_code(self): 42 | # sends HTTP GET request to the application 43 | # on the specified path 44 | result = self.app.post('/api/v2/tweets', data='{"username":"Tagning", "body": "It Works!#Awesome"}', content_type='application/json') 45 | 46 | # assert the status code of the response 47 | self.assertEqual(result.status_code, 201) 48 | 49 | def test_delusers_status_code(self): 50 | # sends HTTP Delete request to the application 51 | # on the specified path 52 | result = self.app.delete('/api/v1/users', data='{"username":"Ovestint"}', content_type='application/json') 53 | print (result) 54 | # assert the status code of the response 55 | self.assertEquals(result.status_code, 200) 56 | -------------------------------------------------------------------------------- /Chapter05/node_modules/requirejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_args": [ 3 | [ 4 | { 5 | "raw": "requirejs@^2.3.3", 6 | "scope": null, 7 | "escapedName": "requirejs", 8 | "name": "requirejs", 9 | "rawSpec": "^2.3.3", 10 | "spec": ">=2.3.3 <3.0.0", 11 | "type": "range" 12 | }, 13 | "/vagrant/github/Cloud-Native-Python/chapter 05" 14 | ] 15 | ], 16 | "_from": "requirejs@>=2.3.3 <3.0.0", 17 | "_id": "requirejs@2.3.3", 18 | "_inCache": true, 19 | "_location": "/requirejs", 20 | "_nodeVersion": "6.7.0", 21 | "_npmOperationalInternal": { 22 | "host": "packages-12-west.internal.npmjs.com", 23 | "tmp": "tmp/requirejs-2.3.3.tgz_1487524083275_0.3237284303177148" 24 | }, 25 | "_npmUser": { 26 | "name": "jrburke", 27 | "email": "jrburke@gmail.com" 28 | }, 29 | "_npmVersion": "3.10.3", 30 | "_phantomChildren": {}, 31 | "_requested": { 32 | "raw": "requirejs@^2.3.3", 33 | "scope": null, 34 | "escapedName": "requirejs", 35 | "name": "requirejs", 36 | "rawSpec": "^2.3.3", 37 | "spec": ">=2.3.3 <3.0.0", 38 | "type": "range" 39 | }, 40 | "_requiredBy": [ 41 | "/" 42 | ], 43 | "_resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.3.tgz", 44 | "_shasum": "aa59fd3a0287eaf407959a138228044b5dd6a6a3", 45 | "_shrinkwrap": null, 46 | "_spec": "requirejs@^2.3.3", 47 | "_where": "/vagrant/github/Cloud-Native-Python/chapter 05", 48 | "author": { 49 | "name": "James Burke", 50 | "email": "jrburke@gmail.com", 51 | "url": "http://github.com/jrburke" 52 | }, 53 | "bin": { 54 | "r.js": "./bin/r.js", 55 | "r_js": "./bin/r.js" 56 | }, 57 | "bugs": { 58 | "url": "https://github.com/jrburke/r.js/issues" 59 | }, 60 | "dependencies": {}, 61 | "description": "Node adapter for RequireJS, for loading AMD modules. Includes RequireJS optimizer", 62 | "devDependencies": {}, 63 | "directories": {}, 64 | "dist": { 65 | "shasum": "aa59fd3a0287eaf407959a138228044b5dd6a6a3", 66 | "tarball": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.3.tgz" 67 | }, 68 | "engines": { 69 | "node": ">=0.4.0" 70 | }, 71 | "homepage": "http://github.com/jrburke/r.js", 72 | "license": "MIT", 73 | "main": "./bin/r.js", 74 | "maintainers": [ 75 | { 76 | "name": "jrburke", 77 | "email": "jrburke@gmail.com" 78 | } 79 | ], 80 | "name": "requirejs", 81 | "optionalDependencies": {}, 82 | "readme": "ERROR: No README data found!", 83 | "repository": { 84 | "type": "git", 85 | "url": "git+https://github.com/jrburke/r.js.git" 86 | }, 87 | "scripts": {}, 88 | "version": "2.3.3" 89 | } 90 | -------------------------------------------------------------------------------- /Chapter03/static/style.css: -------------------------------------------------------------------------------- 1 | ::selection{ background-color: #E13300; color: white; } 2 | ::moz-selection{ background-color: #E13300; color: white; } 3 | ::webkit-selection{ background-color: #E13300; color: white; } 4 | 5 | body { 6 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 7 | color: #888; 8 | font-style: normal; 9 | font-size: 14px; 10 | line-height: 22px; 11 | } 12 | 13 | a { 14 | color: #003399; 15 | background-color: transparent; 16 | font-weight: normal; 17 | } 18 | 19 | .title { 20 | padding: 0 20px; 21 | background: #32373a; 22 | position: relative; 23 | height: 50px; 24 | } 25 | 26 | h1 { 27 | color: #fff; 28 | margin: 0; 29 | font-size: 18px; 30 | font-weight: 400; 31 | line-height: 50px; 32 | text-transform: capitalize; 33 | } 34 | 35 | code { 36 | font-family: Consolas, Monaco, Courier New, Courier, monospace; 37 | font-size: 12px; 38 | background-color: #f9f9f9; 39 | border: 1px solid #D0D0D0; 40 | color: #002166; 41 | display: block; 42 | padding: 12px 10px 12px 10px; 43 | } 44 | 45 | #content { 46 | padding: 20px; 47 | zoom: 1; 48 | } 49 | 50 | #body{ 51 | margin: 0 15px 0 15px; 52 | } 53 | 54 | p.footer{ 55 | text-align: right; 56 | font-size: 11px; 57 | border-top: 1px solid #D0D0D0; 58 | line-height: 32px; 59 | padding: 0 10px 0 10px; 60 | margin: 20px 0 0 0; 61 | } 62 | 63 | #container{ 64 | margin: 10px; 65 | border: 1px solid #D0D0D0; 66 | -webkit-box-shadow: 0 0 8px #D0D0D0; 67 | } 68 | 69 | /* Form Styles */ 70 | form label{ 71 | display: block; 72 | margin-bottom: 5px; 73 | } 74 | form input[type=text]{ 75 | border: 1px solid #aaa; 76 | border-radius: 2px; 77 | box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 78 | box-sizing: border-box; 79 | padding: 5px; 80 | margin-bottom: 20px; 81 | outline: 0; 82 | -webkit-border-radius: 2px; 83 | -moz-border-radius: 2px; 84 | -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 85 | -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 86 | } 87 | form input[type=submit]{ 88 | background: #198ad1; 89 | color: #fff; 90 | display: inline-block; 91 | padding: 0 20px; 92 | font-size: 16px; 93 | line-height: 2.6em; 94 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 95 | font-weight: 400; 96 | -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 97 | -moz-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 98 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 99 | -webkit-border-radius: 2px; 100 | -moz-border-radius: 2px; 101 | border-radius: 2px; 102 | text-transform: capitalize; 103 | border: 0; 104 | cursor: pointer; 105 | text-align: center; 106 | } 107 | -------------------------------------------------------------------------------- /Chapter04/static/style.css: -------------------------------------------------------------------------------- 1 | ::selection{ background-color: #E13300; color: white; } 2 | ::moz-selection{ background-color: #E13300; color: white; } 3 | ::webkit-selection{ background-color: #E13300; color: white; } 4 | 5 | body { 6 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 7 | color: #888; 8 | font-style: normal; 9 | font-size: 14px; 10 | line-height: 22px; 11 | } 12 | 13 | a { 14 | color: #003399; 15 | background-color: transparent; 16 | font-weight: normal; 17 | } 18 | 19 | .title { 20 | padding: 0 20px; 21 | background: #32373a; 22 | position: relative; 23 | height: 50px; 24 | } 25 | 26 | h1 { 27 | color: #fff; 28 | margin: 0; 29 | font-size: 18px; 30 | font-weight: 400; 31 | line-height: 50px; 32 | text-transform: capitalize; 33 | } 34 | 35 | code { 36 | font-family: Consolas, Monaco, Courier New, Courier, monospace; 37 | font-size: 12px; 38 | background-color: #f9f9f9; 39 | border: 1px solid #D0D0D0; 40 | color: #002166; 41 | display: block; 42 | padding: 12px 10px 12px 10px; 43 | } 44 | 45 | #content { 46 | padding: 20px; 47 | zoom: 1; 48 | } 49 | 50 | #body{ 51 | margin: 0 15px 0 15px; 52 | } 53 | 54 | p.footer{ 55 | text-align: right; 56 | font-size: 11px; 57 | border-top: 1px solid #D0D0D0; 58 | line-height: 32px; 59 | padding: 0 10px 0 10px; 60 | margin: 20px 0 0 0; 61 | } 62 | 63 | #container{ 64 | margin: 10px; 65 | border: 1px solid #D0D0D0; 66 | -webkit-box-shadow: 0 0 8px #D0D0D0; 67 | } 68 | 69 | /* Form Styles */ 70 | form label{ 71 | display: block; 72 | margin-bottom: 5px; 73 | } 74 | form input[type=text]{ 75 | border: 1px solid #aaa; 76 | border-radius: 2px; 77 | box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 78 | box-sizing: border-box; 79 | padding: 5px; 80 | margin-bottom: 20px; 81 | outline: 0; 82 | -webkit-border-radius: 2px; 83 | -moz-border-radius: 2px; 84 | -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 85 | -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 86 | } 87 | form input[type=submit]{ 88 | background: #198ad1; 89 | color: #fff; 90 | display: inline-block; 91 | padding: 0 20px; 92 | font-size: 16px; 93 | line-height: 2.6em; 94 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 95 | font-weight: 400; 96 | -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 97 | -moz-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 98 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 99 | -webkit-border-radius: 2px; 100 | -moz-border-radius: 2px; 101 | border-radius: 2px; 102 | text-transform: capitalize; 103 | border: 0; 104 | cursor: pointer; 105 | text-align: center; 106 | } 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Cloud Native Python 5 | This is the code repository for [Cloud Native Python](https://www.packtpub.com/application-development/cloud-native-python?utm_source=github&utm_medium=repository&utm_campaign=9781787129313), published by [Packt](https://www.packtpub.com/?utm_source=github). It contains all the supporting project files necessary to work through the book from start to finish. 6 | ## About the Book 7 | Businesses today are evolving so rapidly that having their own infrastructure to support their expansion is not feasible. As a result, they have been resorting to the elasticity of the cloud to provide a platform to build and deploy their highly scalable applications. 8 | 9 | 10 | ## Instructions and Navigation 11 | All of the code is organized into folders. Each folder starts with a number followed by the application name. For example, Chapter02. 12 | 13 | All the code files are present in their respective chapter folders. 14 | Chapters 9, 12, and 13 do not contain any code files. 15 | 16 | The code will look like the following: 17 | ``` 18 | self.addUser = function() { 19 | self.save(); 20 | self.name(""); 21 | self.username(""); 22 | self.email(""); 23 | self.password(""); 24 | }; 25 | ``` 26 | 27 | You will need to have Python installed on your system. A text editor, preferably 28 | Vim/Sublime/Notepad++, would be great. For one of the chapters, you may be required to 29 | download POSTMAN, which is a powerful API testing suite available as a Chrome 30 | extension. You can download this at https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en. 31 | Other than these, it would be great if you have an account on the following web applications: 32 | 33 | * Jenkins 34 | * Docker 35 | * Amazon Web Services 36 | * Terraform 37 | 38 | In case you do not have an account, this book will guide you, or at least direct you with 39 | regards to creating an account on the previously mentioned web applications. 40 | 41 | ## Related Products 42 | * [Cloud Native Applications in Java](https://www.packtpub.com/application-development/cloud-native-applications-java?utm_source=github&utm_medium=repository&utm_campaign=9781787124349) 43 | 44 | * [Deploying Cloud-Native AWS components [Video]](https://www.packtpub.com/virtualization-and-cloud/deploying-cloud-native-aws-components-video?utm_source=github&utm_medium=repository&utm_campaign=9781788299756) 45 | 46 | * [Cloud Development and Deployment with CloudBees](https://www.packtpub.com/virtualization-and-cloud/cloud-development-and-deployment-cloudbees?utm_source=github&utm_medium=repository&utm_campaign=9781783281633) 47 | ### Download a free PDF 48 | 49 | If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
    Simply click on the link to claim your free PDF.
    50 |

    https://packt.link/free-ebook/9781787129313

    -------------------------------------------------------------------------------- /Chapter11/cloudformation/vpc.template: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion" : "2010-09-09", 3 | 4 | "Description" : "Builds a VPC w/ INET Gateway and a public subnets. This template creates Amazon EC2 instance(s)", 5 | 6 | "Resources" : { 7 | 8 | "VPC" : { 9 | "Type" : "AWS::EC2::VPC", 10 | "Properties" : { 11 | "CidrBlock" : "172.31.0.0/16", 12 | "Tags" : [ 13 | {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} }, 14 | {"Key" : "Network", "Value" : "Public" } 15 | ] 16 | } 17 | }, 18 | 19 | "PublicSubnet" : { 20 | "Type" : "AWS::EC2::Subnet", 21 | "Properties" : { 22 | "VpcId" : { "Ref" : "VPC" }, 23 | "CidrBlock" : "172.31.16.0/20", 24 | "AvailabilityZone" : { "Fn::Select": [ "0", {"Fn::GetAZs": {"Ref": "AWS::Region"}} ]}, 25 | "Tags" : [ 26 | {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} }, 27 | {"Key" : "Network", "Value" : "Public" } 28 | ] 29 | } 30 | }, 31 | "PrivateSubnet" : { 32 | "Type" : "AWS::EC2::Subnet", 33 | "Properties" : { 34 | "VpcId" : { "Ref" : "VPC" }, 35 | "CidrBlock" : "172.31.0.0/20", 36 | "AvailabilityZone" : { "Fn::Select": [ "0", {"Fn::GetAZs": {"Ref": "AWS::Region"}} ]}, 37 | "Tags" : [ 38 | {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} }, 39 | {"Key" : "Network", "Value" : "Public" } 40 | ] 41 | } 42 | }, 43 | 44 | 45 | "InternetGateway" : { 46 | "Type" : "AWS::EC2::InternetGateway", 47 | "Properties" : { 48 | "Tags" : [ 49 | {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} }, 50 | {"Key" : "Network", "Value" : "Public" } 51 | ] 52 | } 53 | }, 54 | 55 | "AttachGateway" : { 56 | "Type" : "AWS::EC2::VPCGatewayAttachment", 57 | "Properties" : { 58 | "VpcId" : { "Ref" : "VPC" }, 59 | "InternetGatewayId" : { "Ref" : "InternetGateway" } 60 | } 61 | }, 62 | 63 | "PublicRouteTable" : { 64 | "Type" : "AWS::EC2::RouteTable", 65 | "Properties" : { 66 | "VpcId" : {"Ref" : "VPC"}, 67 | "Tags" : [ 68 | {"Key" : "Application", "Value" : { "Ref" : "AWS::StackName"} }, 69 | {"Key" : "Network", "Value" : "Public" } 70 | ] 71 | } 72 | }, 73 | 74 | "PublicRoute" : { 75 | "Type" : "AWS::EC2::Route", 76 | "Properties" : { 77 | "RouteTableId" : { "Ref" : "PublicRouteTable" }, 78 | "DestinationCidrBlock" : "0.0.0.0/0", 79 | "GatewayId" : { "Ref" : "InternetGateway" } 80 | } 81 | }, 82 | 83 | "PublicSubnetRouteTableAssociation" : { 84 | "Type" : "AWS::EC2::SubnetRouteTableAssociation", 85 | "Properties" : { 86 | "SubnetId" : { "Ref" : "PublicSubnet" }, 87 | "RouteTableId" : { "Ref" : "PublicRouteTable" } 88 | } 89 | } 90 | }, 91 | 92 | "Outputs" : { 93 | "VpcId" : { 94 | "Value" : {"Ref" : "VPC"}, 95 | "Description" : "VPC ID of newly created VPC" 96 | }, 97 | 98 | "PublicSubnet" : { 99 | "Value" : {"Ref" : "PublicSubnet"}, 100 | "Description" : "Public Subnet in AZ " 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Chapter05/requests.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request, jsonify, redirect, session 2 | from flask import abort 3 | from flask_cors import CORS, cross_origin 4 | from flask import make_response, url_for 5 | import json 6 | import random 7 | from pymongo import MongoClient 8 | from time import gmtime, strftime 9 | 10 | # connection to MongoDB Database 11 | connection = MongoClient("mongodb://localhost:27017/") 12 | 13 | class Requests: 14 | # List users 15 | def list_users(): 16 | api_list=[] 17 | db = connection.app.users 18 | for row in db.find(): 19 | api_list.append(str(row)) 20 | # print (api_list) 21 | return jsonify({'user_list': api_list}) 22 | 23 | # List specific users 24 | def list_user(user_id): 25 | print (user_id) 26 | api_list=[] 27 | db = connection.app.users 28 | for i in db.find({'id':user_id}): 29 | api_list.append(str(i)) 30 | 31 | if api_list == []: 32 | abort(404) 33 | return jsonify({'user_details':api_list}) 34 | 35 | # List specific tweet 36 | def list_tweet(user_id): 37 | print (user_id) 38 | db = connection.app.tweets 39 | api_list=[] 40 | tweet = db.find({'tweetedby':user_id}) 41 | for i in tweet: 42 | api_list.append(str(i)) 43 | if api_list == []: 44 | abort(404) 45 | return jsonify({'tweet': api_list}) 46 | 47 | # Adding user 48 | def add_user(new_user): 49 | api_list=[] 50 | print (new_user) 51 | db = connection.app.users 52 | user = db.find({'$or':[{"username":new_user['username']} ,{"email":new_user['email']}]}) 53 | for i in user: 54 | print (str(i)) 55 | api_list.append(str(i)) 56 | 57 | # print (api_list) 58 | if api_list == []: 59 | # print(new_user) 60 | db.insert(new_user) 61 | return "Success" 62 | else : 63 | abort(409) 64 | 65 | # Deleting User 66 | def del_user(del_user): 67 | db = connection.app.users 68 | api_list=[] 69 | for i in db.find({'username':del_user}): 70 | api_list.append(str(i)) 71 | 72 | if api_list == []: 73 | abort(404) 74 | else: 75 | db.remove({"username":del_user}) 76 | return "Success" 77 | 78 | # List tweets 79 | def list_tweets(): 80 | 81 | api_list=[] 82 | dict = {} 83 | db = connection.app.tweets 84 | for row in db.find(): 85 | print (row) 86 | dict = {} 87 | dict['id'] = row['id'] 88 | dict['timestamp'] = row['timestamp'] 89 | dict['tweetedby'] = row['tweetedby'] 90 | dict['body'] = row['body'] 91 | api_list.append(dict) 92 | 93 | print (api_list) 94 | return json.dumps(api_list) 95 | 96 | # Adding tweets 97 | def add_tweet(new_tweet): 98 | api_list=[] 99 | print (new_tweet) 100 | db_user = connection.app.users 101 | db_tweet = connection.app.tweets 102 | 103 | user = db_user.find({"username":new_tweet['tweetedby']}) 104 | for i in user: 105 | api_list.append(str(i)) 106 | if api_list == []: 107 | abort(404) 108 | else: 109 | db_tweet.insert(new_tweet) 110 | return "Success" 111 | 112 | def upd_user(user): 113 | api_list=[] 114 | print (user) 115 | db_user = connection.app.users 116 | users = db_user.find_one({"id":user['id']}) 117 | for i in users: 118 | api_list.append(str(i)) 119 | if api_list == []: 120 | abort(409) 121 | else: 122 | db_user.update({'id':user['id']},{'$set': user}, upsert=False ) 123 | return "Success" 124 | -------------------------------------------------------------------------------- /Chapter06/requests.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request, jsonify, redirect, session 2 | from flask import abort 3 | from flask_cors import CORS, cross_origin 4 | from flask import make_response, url_for 5 | import json 6 | import random 7 | from pymongo import MongoClient 8 | from time import gmtime, strftime 9 | 10 | # connection to MongoDB Database 11 | connection = MongoClient("mongodb://localhost:27017/") 12 | 13 | class Requests: 14 | # List users 15 | def list_users(): 16 | api_list=[] 17 | db = connection.app.users 18 | for row in db.find(): 19 | api_list.append(str(row)) 20 | # print (api_list) 21 | return jsonify({'user_list': api_list}) 22 | 23 | # List specific users 24 | def list_user(user_id): 25 | print (user_id) 26 | api_list=[] 27 | db = connection.app.users 28 | for i in db.find({'id':user_id}): 29 | api_list.append(str(i)) 30 | 31 | if api_list == []: 32 | abort(404) 33 | return jsonify({'user_details':api_list}) 34 | 35 | # List specific tweet 36 | def list_tweet(user_id): 37 | print (user_id) 38 | db = connection.app.tweets 39 | api_list=[] 40 | tweet = db.find({'tweetedby':user_id}) 41 | for row in tweet: 42 | dict = {} 43 | dict['id'] = row['id'] 44 | dict['timestamp'] = row['timestamp'] 45 | dict['tweetedby'] = row['tweetedby'] 46 | dict['body'] = row['body'] 47 | api_list.append(dict) 48 | if api_list == []: 49 | abort(404) 50 | print (api_list) 51 | return json.dumps(api_list) 52 | 53 | # Adding user 54 | def add_user(new_user): 55 | api_list=[] 56 | print (new_user) 57 | db = connection.app.users 58 | user = db.find({'$or':[{"username":new_user['username']} ,{"email":new_user['email']}]}) 59 | for i in user: 60 | print (str(i)) 61 | api_list.append(str(i)) 62 | 63 | # print (api_list) 64 | if api_list == []: 65 | # print(new_user) 66 | db.insert(new_user) 67 | return "Success" 68 | else : 69 | abort(409) 70 | 71 | # Deleting User 72 | def del_user(del_user): 73 | db = connection.app.users 74 | api_list=[] 75 | for i in db.find({'username':del_user}): 76 | api_list.append(str(i)) 77 | 78 | if api_list == []: 79 | abort(404) 80 | else: 81 | db.remove({"username":del_user}) 82 | return "Success" 83 | 84 | # List tweets 85 | def list_tweets(): 86 | 87 | api_list=[] 88 | dict = {} 89 | db = connection.app.tweets 90 | for row in db.find(): 91 | print (row) 92 | dict = {} 93 | dict['id'] = row['id'] 94 | dict['timestamp'] = row['timestamp'] 95 | dict['tweetedby'] = row['tweetedby'] 96 | dict['body'] = row['body'] 97 | api_list.append(dict) 98 | 99 | print (api_list) 100 | return json.dumps(api_list) 101 | 102 | # Adding tweets 103 | def add_tweet(new_tweet): 104 | api_list=[] 105 | print (new_tweet) 106 | db_user = connection.app.users 107 | db_tweet = connection.app.tweets 108 | 109 | user = db_user.find({"username":new_tweet['tweetedby']}) 110 | for i in user: 111 | api_list.append(str(i)) 112 | if api_list == []: 113 | abort(404) 114 | else: 115 | db_tweet.insert(new_tweet) 116 | return "Success" 117 | 118 | def upd_user(user): 119 | api_list=[] 120 | print (user) 121 | db_user = connection.app.users 122 | users = db_user.find_one({"id":user['id']}) 123 | for i in users: 124 | api_list.append(str(i)) 125 | if api_list == []: 126 | abort(409) 127 | else: 128 | db_user.update({'id':user['id']},{'$set': user}, upsert=False ) 129 | return "Success" 130 | -------------------------------------------------------------------------------- /Chapter07/requests.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request, jsonify, redirect, session 2 | from flask import abort 3 | from flask_cors import CORS, cross_origin 4 | from flask import make_response, url_for 5 | import json 6 | import random 7 | from pymongo import MongoClient 8 | from time import gmtime, strftime 9 | 10 | # connection to MongoDB Database 11 | connection = MongoClient("mongodb://localhost:27017/") 12 | 13 | class Requests: 14 | # List users 15 | def list_users(): 16 | api_list=[] 17 | db = connection.app.users 18 | for row in db.find(): 19 | api_list.append(str(row)) 20 | # print (api_list) 21 | return jsonify({'user_list': api_list}) 22 | 23 | # List specific users 24 | def list_user(user_id): 25 | print (user_id) 26 | api_list=[] 27 | db = connection.app.users 28 | for i in db.find({'id':user_id}): 29 | api_list.append(str(i)) 30 | 31 | if api_list == []: 32 | abort(404) 33 | return jsonify({'user_details':api_list}) 34 | 35 | # List specific tweet 36 | def list_tweet(user_id): 37 | print (user_id) 38 | db = connection.app.tweets 39 | api_list=[] 40 | tweet = db.find({'tweetedby':user_id}) 41 | for row in tweet: 42 | dict = {} 43 | dict['id'] = row['id'] 44 | dict['timestamp'] = row['timestamp'] 45 | dict['tweetedby'] = row['tweetedby'] 46 | dict['body'] = row['body'] 47 | api_list.append(dict) 48 | if api_list == []: 49 | abort(404) 50 | print (api_list) 51 | return json.dumps(api_list) 52 | 53 | # Adding user 54 | def add_user(new_user): 55 | api_list=[] 56 | print (new_user) 57 | db = connection.app.users 58 | user = db.find({'$or':[{"username":new_user['username']} ,{"email":new_user['email']}]}) 59 | for i in user: 60 | print (str(i)) 61 | api_list.append(str(i)) 62 | 63 | # print (api_list) 64 | if api_list == []: 65 | # print(new_user) 66 | db.insert(new_user) 67 | return "Success" 68 | else : 69 | abort(409) 70 | 71 | # Deleting User 72 | def del_user(del_user): 73 | db = connection.app.users 74 | api_list=[] 75 | for i in db.find({'username':del_user}): 76 | api_list.append(str(i)) 77 | 78 | if api_list == []: 79 | abort(404) 80 | else: 81 | db.remove({"username":del_user}) 82 | return "Success" 83 | 84 | # List tweets 85 | def list_tweets(): 86 | 87 | api_list=[] 88 | dict = {} 89 | db = connection.app.tweets 90 | for row in db.find(): 91 | print (row) 92 | dict = {} 93 | dict['id'] = row['id'] 94 | dict['timestamp'] = row['timestamp'] 95 | dict['tweetedby'] = row['tweetedby'] 96 | dict['body'] = row['body'] 97 | api_list.append(dict) 98 | 99 | print (api_list) 100 | return json.dumps(api_list) 101 | 102 | # Adding tweets 103 | def add_tweet(new_tweet): 104 | api_list=[] 105 | print (new_tweet) 106 | db_user = connection.app.users 107 | db_tweet = connection.app.tweets 108 | 109 | user = db_user.find({"username":new_tweet['tweetedby']}) 110 | for i in user: 111 | api_list.append(str(i)) 112 | if api_list == []: 113 | abort(404) 114 | else: 115 | db_tweet.insert(new_tweet) 116 | return "Success" 117 | 118 | def upd_user(user): 119 | api_list=[] 120 | print (user) 121 | db_user = connection.app.users 122 | users = db_user.find_one({"id":user['id']}) 123 | for i in users: 124 | api_list.append(str(i)) 125 | if api_list == []: 126 | abort(409) 127 | else: 128 | db_user.update({'id':user['id']},{'$set': user}, upsert=False ) 129 | return "Success" 130 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/requests.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request, jsonify, redirect, session 2 | from flask import abort 3 | from flask_cors import CORS, cross_origin 4 | from flask import make_response, url_for 5 | import json 6 | import random 7 | from pymongo import MongoClient 8 | from time import gmtime, strftime 9 | 10 | # connection to MongoDB Database 11 | connection = MongoClient("mongodb://localhost:27017/") 12 | 13 | class Requests: 14 | # List users 15 | def list_users(): 16 | api_list=[] 17 | db = connection.app.users 18 | for row in db.find(): 19 | api_list.append(str(row)) 20 | # print (api_list) 21 | return jsonify({'user_list': api_list}) 22 | 23 | # List specific users 24 | def list_user(user_id): 25 | print (user_id) 26 | api_list=[] 27 | db = connection.app.users 28 | for i in db.find({'id':user_id}): 29 | api_list.append(str(i)) 30 | 31 | if api_list == []: 32 | abort(404) 33 | return jsonify({'user_details':api_list}) 34 | 35 | # List specific tweet 36 | def list_tweet(user_id): 37 | print (user_id) 38 | db = connection.app.tweets 39 | api_list=[] 40 | tweet = db.find({'tweetedby':user_id}) 41 | for row in tweet: 42 | dict = {} 43 | dict['id'] = row['id'] 44 | dict['timestamp'] = row['timestamp'] 45 | dict['tweetedby'] = row['tweetedby'] 46 | dict['body'] = row['body'] 47 | api_list.append(dict) 48 | if api_list == []: 49 | abort(404) 50 | print (api_list) 51 | return json.dumps(api_list) 52 | 53 | # Adding user 54 | def add_user(new_user): 55 | api_list=[] 56 | print (new_user) 57 | db = connection.app.users 58 | user = db.find({'$or':[{"username":new_user['username']} ,{"email":new_user['email']}]}) 59 | for i in user: 60 | print (str(i)) 61 | api_list.append(str(i)) 62 | 63 | # print (api_list) 64 | if api_list == []: 65 | # print(new_user) 66 | db.insert(new_user) 67 | return "Success" 68 | else : 69 | abort(409) 70 | 71 | # Deleting User 72 | def del_user(del_user): 73 | db = connection.app.users 74 | api_list=[] 75 | for i in db.find({'username':del_user}): 76 | api_list.append(str(i)) 77 | 78 | if api_list == []: 79 | abort(404) 80 | else: 81 | db.remove({"username":del_user}) 82 | return "Success" 83 | 84 | # List tweets 85 | def list_tweets(): 86 | 87 | api_list=[] 88 | dict = {} 89 | db = connection.app.tweets 90 | for row in db.find(): 91 | print (row) 92 | dict = {} 93 | dict['id'] = row['id'] 94 | dict['timestamp'] = row['timestamp'] 95 | dict['tweetedby'] = row['tweetedby'] 96 | dict['body'] = row['body'] 97 | api_list.append(dict) 98 | 99 | print (api_list) 100 | return json.dumps(api_list) 101 | 102 | # Adding tweets 103 | def add_tweet(new_tweet): 104 | api_list=[] 105 | print (new_tweet) 106 | db_user = connection.app.users 107 | db_tweet = connection.app.tweets 108 | 109 | user = db_user.find({"username":new_tweet['tweetedby']}) 110 | for i in user: 111 | api_list.append(str(i)) 112 | if api_list == []: 113 | abort(404) 114 | else: 115 | db_tweet.insert(new_tweet) 116 | return "Success" 117 | 118 | def upd_user(user): 119 | api_list=[] 120 | print (user) 121 | db_user = connection.app.users 122 | users = db_user.find_one({"id":user['id']}) 123 | for i in users: 124 | api_list.append(str(i)) 125 | if api_list == []: 126 | abort(409) 127 | else: 128 | db_user.update({'id':user['id']},{'$set': user}, upsert=False ) 129 | return "Success" 130 | -------------------------------------------------------------------------------- /Chapter08/request.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request, jsonify, redirect, session 2 | from flask import abort 3 | from flask_cors import CORS, cross_origin 4 | from flask import make_response, url_for 5 | import json 6 | import random 7 | from pymongo import MongoClient 8 | from time import gmtime, strftime 9 | 10 | # connection to MongoDB Database 11 | connection = MongoClient("mongodb://localhost:27017/") 12 | 13 | class Requests: 14 | # List users 15 | def list_users(): 16 | api_list=[] 17 | db = connection.app.users 18 | for row in db.find(): 19 | api_list.append(str(row)) 20 | # print (api_list) 21 | return jsonify({'user_list': api_list}) 22 | 23 | # List specific users 24 | def list_user(user_id): 25 | print (user_id) 26 | api_list=[] 27 | db = connection.app.users 28 | for i in db.find({'id':user_id}): 29 | api_list.append(str(i)) 30 | 31 | if api_list == []: 32 | abort(404) 33 | return jsonify({'user_details':api_list}) 34 | 35 | # List specific tweet 36 | def list_tweet(user_id): 37 | print (user_id) 38 | db = connection.app.tweets 39 | api_list=[] 40 | tweet = db.find({'tweetedby':user_id}) 41 | for row in tweet: 42 | dict = {} 43 | dict['id'] = row['id'] 44 | dict['timestamp'] = row['timestamp'] 45 | dict['tweetedby'] = row['tweetedby'] 46 | dict['body'] = row['body'] 47 | api_list.append(dict) 48 | if api_list == []: 49 | abort(404) 50 | print (api_list) 51 | return json.dumps(api_list) 52 | 53 | # Adding user 54 | def add_user(new_user): 55 | # api_list=[] 56 | # print (new_user) 57 | # db = connection.app.users 58 | # user = db.find({'$or':[{"username":new_user['username']} ,{"email":new_user['email']}]}) 59 | # for i in user: 60 | # print (str(i)) 61 | # api_list.append(str(i)) 62 | # 63 | # # print (api_list) 64 | # if api_list == []: 65 | # # print(new_user) 66 | db.insert(new_user) 67 | return "Success" 68 | # else : 69 | # abort(409) 70 | 71 | # Deleting User 72 | def del_user(del_user): 73 | db = connection.app.users 74 | api_list=[] 75 | for i in db.find({'username':del_user}): 76 | api_list.append(str(i)) 77 | 78 | if api_list == []: 79 | abort(404) 80 | else: 81 | db.remove({"username":del_user}) 82 | return "Success" 83 | 84 | # List tweets 85 | def list_tweets(): 86 | 87 | api_list=[] 88 | dict = {} 89 | db = connection.app.tweets 90 | for row in db.find(): 91 | print (row) 92 | dict = {} 93 | dict['id'] = row['id'] 94 | dict['timestamp'] = row['timestamp'] 95 | dict['tweetedby'] = row['tweetedby'] 96 | dict['body'] = row['body'] 97 | api_list.append(dict) 98 | 99 | print (api_list) 100 | return json.dumps(api_list) 101 | 102 | # Adding tweets 103 | def add_tweet(new_tweet): 104 | api_list=[] 105 | print (new_tweet) 106 | db_user = connection.app.users 107 | db_tweet = connection.app.tweets 108 | 109 | user = db_user.find({"username":new_tweet['tweetedby']}) 110 | for i in user: 111 | api_list.append(str(i)) 112 | if api_list == []: 113 | abort(404) 114 | else: 115 | db_tweet.insert(new_tweet) 116 | return "Success" 117 | 118 | def upd_user(user): 119 | api_list=[] 120 | print (user) 121 | db_user = connection.app.users 122 | users = db_user.find_one({"id":user['id']}) 123 | for i in users: 124 | api_list.append(str(i)) 125 | if api_list == []: 126 | abort(409) 127 | else: 128 | db_user.update({'id':user['id']},{'$set': user}, upsert=False ) 129 | return "Success" 130 | -------------------------------------------------------------------------------- /Chapter05/static/style.css: -------------------------------------------------------------------------------- 1 | ::selection{ background-color: #E13300; color: white; } 2 | ::moz-selection{ background-color: #E13300; color: white; } 3 | ::webkit-selection{ background-color: #E13300; color: white; } 4 | 5 | body { 6 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 7 | color: #888; 8 | font-style: normal; 9 | font-size: 14px; 10 | line-height: px; 11 | } 12 | 13 | a { 14 | color: #003399; 15 | background-color: transparent; 16 | font-weight: normal; 17 | } 18 | 19 | .title { 20 | padding: 0 20px; 21 | background: #32373a; 22 | position: relative; 23 | height: 50px; 24 | } 25 | 26 | h1 { 27 | color: #fff; 28 | margin: 0; 29 | font-size: 18px; 30 | font-weight: 400; 31 | line-height: 50px; 32 | text-transform: capitalize; 33 | } 34 | 35 | code { 36 | font-family: Consolas, Monaco, Courier New, Courier, monospace; 37 | font-size: 12px; 38 | background-color: #f9f9f9; 39 | border: 1px solid #D0D0D0; 40 | color: #002166; 41 | display: block; 42 | padding: 12px 10px 12px 10px; 43 | } 44 | 45 | #content { 46 | padding: 20px; 47 | zoom: 1; 48 | } 49 | 50 | #body{ 51 | margin: 0 15px 0 15px; 52 | } 53 | 54 | p.footer{ 55 | text-align: right; 56 | font-size: 11px; 57 | border-top: 1px solid #D0D0D0; 58 | line-height: 32px; 59 | padding: 0 10px 0 10px; 60 | margin: 20px 0 0 0; 61 | } 62 | 63 | #container{ 64 | margin: 10px; 65 | border: 1px solid #D0D0D0; 66 | -webkit-box-shadow: 0 0 8px #D0D0D0; 67 | } 68 | 69 | /* Form Styles */ 70 | form label{ 71 | display: block; 72 | margin-bottom: 5px; 73 | } 74 | form input[type=text]{ 75 | border: 1px solid #aaa; 76 | border-radius: 2px; 77 | box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 78 | box-sizing: border-box; 79 | padding: 5px; 80 | margin-bottom: 20px; 81 | outline: 0; 82 | -webkit-border-radius: 2px; 83 | -moz-border-radius: 2px; 84 | -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 85 | -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 86 | } 87 | form input[type=submit]{ 88 | background: #198ad1; 89 | color: #fff; 90 | display: inline-block; 91 | padding: 0 20px; 92 | font-size: 16px; 93 | line-height: 2.6em; 94 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 95 | font-weight: 400; 96 | -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 97 | -moz-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 98 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 99 | -webkit-border-radius: 2px; 100 | -moz-border-radius: 2px; 101 | border-radius: 2px; 102 | text-transform: capitalize; 103 | border: 0; 104 | cursor: pointer; 105 | text-align: center; 106 | } 107 | 108 | * { 109 | box-sizing: border-box; 110 | } 111 | 112 | *:focus { 113 | outline: none; 114 | } 115 | body { 116 | font-family: Arial; 117 | background-color: #3498DB; 118 | padding: 50px; 119 | } 120 | .login { 121 | margin: 20px auto; 122 | width: 300px; 123 | } 124 | .login-screen { 125 | background-color: #FFF; 126 | padding: 20px; 127 | border-radius: 5px 128 | } 129 | 130 | .app-title { 131 | text-align: center; 132 | color: #777; 133 | } 134 | 135 | .login-form { 136 | text-align: center; 137 | } 138 | .control-group { 139 | margin-bottom: 10px; 140 | } 141 | 142 | input { 143 | text-align: center; 144 | background-color: #ECF0F1; 145 | border: 2px solid transparent; 146 | border-radius: 3px; 147 | font-size: 16px; 148 | font-weight: 200; 149 | padding: 10px 0; 150 | width: 250px; 151 | transition: border .5s; 152 | } 153 | 154 | input:focus { 155 | border: 2px solid #3498DB; 156 | box-shadow: none; 157 | } 158 | 159 | .btn { 160 | border: 2px solid transparent; 161 | background: #3498DB; 162 | color: #ffffff; 163 | font-size: 16px; 164 | line-height: 25px; 165 | padding: 10px 0; 166 | text-decoration: none; 167 | text-shadow: none; 168 | border-radius: 3px; 169 | box-shadow: none; 170 | transition: 0.25s; 171 | display: block; 172 | width: 250px; 173 | margin: 0 auto; 174 | } 175 | 176 | .btn:hover { 177 | background-color: #2980B9; 178 | } 179 | 180 | .login-link { 181 | font-size: 12px; 182 | color: #444; 183 | display: block; 184 | margin-top: 12px; 185 | } 186 | -------------------------------------------------------------------------------- /Chapter06/static/style.css: -------------------------------------------------------------------------------- 1 | ::selection{ background-color: #E13300; color: white; } 2 | ::moz-selection{ background-color: #E13300; color: white; } 3 | ::webkit-selection{ background-color: #E13300; color: white; } 4 | 5 | body { 6 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 7 | color: #888; 8 | font-style: normal; 9 | font-size: 14px; 10 | line-height: px; 11 | } 12 | 13 | a { 14 | color: #003399; 15 | background-color: transparent; 16 | font-weight: normal; 17 | } 18 | 19 | .title { 20 | padding: 0 20px; 21 | background: #32373a; 22 | position: relative; 23 | height: 50px; 24 | } 25 | 26 | h1 { 27 | color: #fff; 28 | margin: 0; 29 | font-size: 18px; 30 | font-weight: 400; 31 | line-height: 50px; 32 | text-transform: capitalize; 33 | } 34 | 35 | code { 36 | font-family: Consolas, Monaco, Courier New, Courier, monospace; 37 | font-size: 12px; 38 | background-color: #f9f9f9; 39 | border: 1px solid #D0D0D0; 40 | color: #002166; 41 | display: block; 42 | padding: 12px 10px 12px 10px; 43 | } 44 | 45 | #content { 46 | padding: 20px; 47 | zoom: 1; 48 | } 49 | 50 | #body{ 51 | margin: 0 15px 0 15px; 52 | } 53 | 54 | p.footer{ 55 | text-align: right; 56 | font-size: 11px; 57 | border-top: 1px solid #D0D0D0; 58 | line-height: 32px; 59 | padding: 0 10px 0 10px; 60 | margin: 20px 0 0 0; 61 | } 62 | 63 | #container{ 64 | margin: 10px; 65 | border: 1px solid #D0D0D0; 66 | -webkit-box-shadow: 0 0 8px #D0D0D0; 67 | } 68 | 69 | /* Form Styles */ 70 | form label{ 71 | display: block; 72 | margin-bottom: 5px; 73 | } 74 | form input[type=text]{ 75 | border: 1px solid #aaa; 76 | border-radius: 2px; 77 | box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 78 | box-sizing: border-box; 79 | padding: 5px; 80 | margin-bottom: 20px; 81 | outline: 0; 82 | -webkit-border-radius: 2px; 83 | -moz-border-radius: 2px; 84 | -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 85 | -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 86 | } 87 | form input[type=submit]{ 88 | background: #198ad1; 89 | color: #fff; 90 | display: inline-block; 91 | padding: 0 20px; 92 | font-size: 16px; 93 | line-height: 2.6em; 94 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 95 | font-weight: 400; 96 | -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 97 | -moz-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 98 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 99 | -webkit-border-radius: 2px; 100 | -moz-border-radius: 2px; 101 | border-radius: 2px; 102 | text-transform: capitalize; 103 | border: 0; 104 | cursor: pointer; 105 | text-align: center; 106 | } 107 | 108 | * { 109 | box-sizing: border-box; 110 | } 111 | 112 | *:focus { 113 | outline: none; 114 | } 115 | body { 116 | font-family: Arial; 117 | background-color: #3498DB; 118 | padding: 50px; 119 | } 120 | .login { 121 | margin: 20px auto; 122 | width: 300px; 123 | } 124 | .login-screen { 125 | background-color: #FFF; 126 | padding: 20px; 127 | border-radius: 5px 128 | } 129 | 130 | .app-title { 131 | text-align: center; 132 | color: #777; 133 | } 134 | 135 | .login-form { 136 | text-align: center; 137 | } 138 | .control-group { 139 | margin-bottom: 10px; 140 | } 141 | 142 | input { 143 | text-align: center; 144 | background-color: #ECF0F1; 145 | border: 2px solid transparent; 146 | border-radius: 3px; 147 | font-size: 16px; 148 | font-weight: 200; 149 | padding: 10px 0; 150 | width: 250px; 151 | transition: border .5s; 152 | } 153 | 154 | input:focus { 155 | border: 2px solid #3498DB; 156 | box-shadow: none; 157 | } 158 | 159 | .btn { 160 | border: 2px solid transparent; 161 | background: #3498DB; 162 | color: #ffffff; 163 | font-size: 16px; 164 | line-height: 25px; 165 | padding: 10px 0; 166 | text-decoration: none; 167 | text-shadow: none; 168 | border-radius: 3px; 169 | box-shadow: none; 170 | transition: 0.25s; 171 | display: block; 172 | width: 250px; 173 | margin: 0 auto; 174 | } 175 | 176 | .btn:hover { 177 | background-color: #2980B9; 178 | } 179 | 180 | .login-link { 181 | font-size: 12px; 182 | color: #444; 183 | display: block; 184 | margin-top: 12px; 185 | } 186 | -------------------------------------------------------------------------------- /Chapter07/static/style.css: -------------------------------------------------------------------------------- 1 | ::selection{ background-color: #E13300; color: white; } 2 | ::moz-selection{ background-color: #E13300; color: white; } 3 | ::webkit-selection{ background-color: #E13300; color: white; } 4 | 5 | body { 6 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 7 | color: #888; 8 | font-style: normal; 9 | font-size: 14px; 10 | line-height: px; 11 | } 12 | 13 | a { 14 | color: #003399; 15 | background-color: transparent; 16 | font-weight: normal; 17 | } 18 | 19 | .title { 20 | padding: 0 20px; 21 | background: #32373a; 22 | position: relative; 23 | height: 50px; 24 | } 25 | 26 | h1 { 27 | color: #fff; 28 | margin: 0; 29 | font-size: 18px; 30 | font-weight: 400; 31 | line-height: 50px; 32 | text-transform: capitalize; 33 | } 34 | 35 | code { 36 | font-family: Consolas, Monaco, Courier New, Courier, monospace; 37 | font-size: 12px; 38 | background-color: #f9f9f9; 39 | border: 1px solid #D0D0D0; 40 | color: #002166; 41 | display: block; 42 | padding: 12px 10px 12px 10px; 43 | } 44 | 45 | #content { 46 | padding: 20px; 47 | zoom: 1; 48 | } 49 | 50 | #body{ 51 | margin: 0 15px 0 15px; 52 | } 53 | 54 | p.footer{ 55 | text-align: right; 56 | font-size: 11px; 57 | border-top: 1px solid #D0D0D0; 58 | line-height: 32px; 59 | padding: 0 10px 0 10px; 60 | margin: 20px 0 0 0; 61 | } 62 | 63 | #container{ 64 | margin: 10px; 65 | border: 1px solid #D0D0D0; 66 | -webkit-box-shadow: 0 0 8px #D0D0D0; 67 | } 68 | 69 | /* Form Styles */ 70 | form label{ 71 | display: block; 72 | margin-bottom: 5px; 73 | } 74 | form input[type=text]{ 75 | border: 1px solid #aaa; 76 | border-radius: 2px; 77 | box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 78 | box-sizing: border-box; 79 | padding: 5px; 80 | margin-bottom: 20px; 81 | outline: 0; 82 | -webkit-border-radius: 2px; 83 | -moz-border-radius: 2px; 84 | -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 85 | -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 86 | } 87 | form input[type=submit]{ 88 | background: #198ad1; 89 | color: #fff; 90 | display: inline-block; 91 | padding: 0 20px; 92 | font-size: 16px; 93 | line-height: 2.6em; 94 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 95 | font-weight: 400; 96 | -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 97 | -moz-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 98 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 99 | -webkit-border-radius: 2px; 100 | -moz-border-radius: 2px; 101 | border-radius: 2px; 102 | text-transform: capitalize; 103 | border: 0; 104 | cursor: pointer; 105 | text-align: center; 106 | } 107 | 108 | * { 109 | box-sizing: border-box; 110 | } 111 | 112 | *:focus { 113 | outline: none; 114 | } 115 | body { 116 | font-family: Arial; 117 | background-color: #3498DB; 118 | padding: 50px; 119 | } 120 | .login { 121 | margin: 20px auto; 122 | width: 300px; 123 | } 124 | .login-screen { 125 | background-color: #FFF; 126 | padding: 20px; 127 | border-radius: 5px 128 | } 129 | 130 | .app-title { 131 | text-align: center; 132 | color: #777; 133 | } 134 | 135 | .login-form { 136 | text-align: center; 137 | } 138 | .control-group { 139 | margin-bottom: 10px; 140 | } 141 | 142 | input { 143 | text-align: center; 144 | background-color: #ECF0F1; 145 | border: 2px solid transparent; 146 | border-radius: 3px; 147 | font-size: 16px; 148 | font-weight: 200; 149 | padding: 10px 0; 150 | width: 250px; 151 | transition: border .5s; 152 | } 153 | 154 | input:focus { 155 | border: 2px solid #3498DB; 156 | box-shadow: none; 157 | } 158 | 159 | .btn { 160 | border: 2px solid transparent; 161 | background: #3498DB; 162 | color: #ffffff; 163 | font-size: 16px; 164 | line-height: 25px; 165 | padding: 10px 0; 166 | text-decoration: none; 167 | text-shadow: none; 168 | border-radius: 3px; 169 | box-shadow: none; 170 | transition: 0.25s; 171 | display: block; 172 | width: 250px; 173 | margin: 0 auto; 174 | } 175 | 176 | .btn:hover { 177 | background-color: #2980B9; 178 | } 179 | 180 | .login-link { 181 | font-size: 12px; 182 | color: #444; 183 | display: block; 184 | margin-top: 12px; 185 | } 186 | -------------------------------------------------------------------------------- /Chapter08/static/style.css: -------------------------------------------------------------------------------- 1 | ::selection{ background-color: #E13300; color: white; } 2 | ::moz-selection{ background-color: #E13300; color: white; } 3 | ::webkit-selection{ background-color: #E13300; color: white; } 4 | 5 | body { 6 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 7 | color: #888; 8 | font-style: normal; 9 | font-size: 14px; 10 | line-height: px; 11 | } 12 | 13 | a { 14 | color: #003399; 15 | background-color: transparent; 16 | font-weight: normal; 17 | } 18 | 19 | .title { 20 | padding: 0 20px; 21 | background: #32373a; 22 | position: relative; 23 | height: 50px; 24 | } 25 | 26 | h1 { 27 | color: #fff; 28 | margin: 0; 29 | font-size: 18px; 30 | font-weight: 400; 31 | line-height: 50px; 32 | text-transform: capitalize; 33 | } 34 | 35 | code { 36 | font-family: Consolas, Monaco, Courier New, Courier, monospace; 37 | font-size: 12px; 38 | background-color: #f9f9f9; 39 | border: 1px solid #D0D0D0; 40 | color: #002166; 41 | display: block; 42 | padding: 12px 10px 12px 10px; 43 | } 44 | 45 | #content { 46 | padding: 20px; 47 | zoom: 1; 48 | } 49 | 50 | #body{ 51 | margin: 0 15px 0 15px; 52 | } 53 | 54 | p.footer{ 55 | text-align: right; 56 | font-size: 11px; 57 | border-top: 1px solid #D0D0D0; 58 | line-height: 32px; 59 | padding: 0 10px 0 10px; 60 | margin: 20px 0 0 0; 61 | } 62 | 63 | #container{ 64 | margin: 10px; 65 | border: 1px solid #D0D0D0; 66 | -webkit-box-shadow: 0 0 8px #D0D0D0; 67 | } 68 | 69 | /* Form Styles */ 70 | form label{ 71 | display: block; 72 | margin-bottom: 5px; 73 | } 74 | form input[type=text]{ 75 | border: 1px solid #aaa; 76 | border-radius: 2px; 77 | box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 78 | box-sizing: border-box; 79 | padding: 5px; 80 | margin-bottom: 20px; 81 | outline: 0; 82 | -webkit-border-radius: 2px; 83 | -moz-border-radius: 2px; 84 | -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 85 | -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 86 | } 87 | form input[type=submit]{ 88 | background: #198ad1; 89 | color: #fff; 90 | display: inline-block; 91 | padding: 0 20px; 92 | font-size: 16px; 93 | line-height: 2.6em; 94 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 95 | font-weight: 400; 96 | -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 97 | -moz-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 98 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 99 | -webkit-border-radius: 2px; 100 | -moz-border-radius: 2px; 101 | border-radius: 2px; 102 | text-transform: capitalize; 103 | border: 0; 104 | cursor: pointer; 105 | text-align: center; 106 | } 107 | 108 | * { 109 | box-sizing: border-box; 110 | } 111 | 112 | *:focus { 113 | outline: none; 114 | } 115 | body { 116 | font-family: Arial; 117 | background-color: #3498DB; 118 | padding: 50px; 119 | } 120 | .login { 121 | margin: 20px auto; 122 | width: 300px; 123 | } 124 | .login-screen { 125 | background-color: #FFF; 126 | padding: 20px; 127 | border-radius: 5px 128 | } 129 | 130 | .app-title { 131 | text-align: center; 132 | color: #777; 133 | } 134 | 135 | .login-form { 136 | text-align: center; 137 | } 138 | .control-group { 139 | margin-bottom: 10px; 140 | } 141 | 142 | input { 143 | text-align: center; 144 | background-color: #ECF0F1; 145 | border: 2px solid transparent; 146 | border-radius: 3px; 147 | font-size: 16px; 148 | font-weight: 200; 149 | padding: 10px 0; 150 | width: 250px; 151 | transition: border .5s; 152 | } 153 | 154 | input:focus { 155 | border: 2px solid #3498DB; 156 | box-shadow: none; 157 | } 158 | 159 | .btn { 160 | border: 2px solid transparent; 161 | background: #3498DB; 162 | color: #ffffff; 163 | font-size: 16px; 164 | line-height: 25px; 165 | padding: 10px 0; 166 | text-decoration: none; 167 | text-shadow: none; 168 | border-radius: 3px; 169 | box-shadow: none; 170 | transition: 0.25s; 171 | display: block; 172 | width: 250px; 173 | margin: 0 auto; 174 | } 175 | 176 | .btn:hover { 177 | background-color: #2980B9; 178 | } 179 | 180 | .login-link { 181 | font-size: 12px; 182 | color: #444; 183 | display: block; 184 | margin-top: 12px; 185 | } 186 | -------------------------------------------------------------------------------- /Chapter10/app/cloud-native-app/static/style.css: -------------------------------------------------------------------------------- 1 | ::selection{ background-color: #E13300; color: white; } 2 | ::moz-selection{ background-color: #E13300; color: white; } 3 | ::webkit-selection{ background-color: #E13300; color: white; } 4 | 5 | body { 6 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 7 | color: #888; 8 | font-style: normal; 9 | font-size: 14px; 10 | line-height: px; 11 | } 12 | 13 | a { 14 | color: #003399; 15 | background-color: transparent; 16 | font-weight: normal; 17 | } 18 | 19 | .title { 20 | padding: 0 20px; 21 | background: #32373a; 22 | position: relative; 23 | height: 50px; 24 | } 25 | 26 | h1 { 27 | color: #fff; 28 | margin: 0; 29 | font-size: 18px; 30 | font-weight: 400; 31 | line-height: 50px; 32 | text-transform: capitalize; 33 | } 34 | 35 | code { 36 | font-family: Consolas, Monaco, Courier New, Courier, monospace; 37 | font-size: 12px; 38 | background-color: #f9f9f9; 39 | border: 1px solid #D0D0D0; 40 | color: #002166; 41 | display: block; 42 | padding: 12px 10px 12px 10px; 43 | } 44 | 45 | #content { 46 | padding: 20px; 47 | zoom: 1; 48 | } 49 | 50 | #body{ 51 | margin: 0 15px 0 15px; 52 | } 53 | 54 | p.footer{ 55 | text-align: right; 56 | font-size: 11px; 57 | border-top: 1px solid #D0D0D0; 58 | line-height: 32px; 59 | padding: 0 10px 0 10px; 60 | margin: 20px 0 0 0; 61 | } 62 | 63 | #container{ 64 | margin: 10px; 65 | border: 1px solid #D0D0D0; 66 | -webkit-box-shadow: 0 0 8px #D0D0D0; 67 | } 68 | 69 | /* Form Styles */ 70 | form label{ 71 | display: block; 72 | margin-bottom: 5px; 73 | } 74 | form input[type=text]{ 75 | border: 1px solid #aaa; 76 | border-radius: 2px; 77 | box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 78 | box-sizing: border-box; 79 | padding: 5px; 80 | margin-bottom: 20px; 81 | outline: 0; 82 | -webkit-border-radius: 2px; 83 | -moz-border-radius: 2px; 84 | -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 85 | -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 86 | } 87 | form input[type=submit]{ 88 | background: #198ad1; 89 | color: #fff; 90 | display: inline-block; 91 | padding: 0 20px; 92 | font-size: 16px; 93 | line-height: 2.6em; 94 | font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif; 95 | font-weight: 400; 96 | -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 97 | -moz-box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 98 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.1); 99 | -webkit-border-radius: 2px; 100 | -moz-border-radius: 2px; 101 | border-radius: 2px; 102 | text-transform: capitalize; 103 | border: 0; 104 | cursor: pointer; 105 | text-align: center; 106 | } 107 | 108 | * { 109 | box-sizing: border-box; 110 | } 111 | 112 | *:focus { 113 | outline: none; 114 | } 115 | body { 116 | font-family: Arial; 117 | background-color: #3498DB; 118 | padding: 50px; 119 | } 120 | .login { 121 | margin: 20px auto; 122 | width: 300px; 123 | } 124 | .login-screen { 125 | background-color: #FFF; 126 | padding: 20px; 127 | border-radius: 5px 128 | } 129 | 130 | .app-title { 131 | text-align: center; 132 | color: #777; 133 | } 134 | 135 | .login-form { 136 | text-align: center; 137 | } 138 | .control-group { 139 | margin-bottom: 10px; 140 | } 141 | 142 | input { 143 | text-align: center; 144 | background-color: #ECF0F1; 145 | border: 2px solid transparent; 146 | border-radius: 3px; 147 | font-size: 16px; 148 | font-weight: 200; 149 | padding: 10px 0; 150 | width: 250px; 151 | transition: border .5s; 152 | } 153 | 154 | input:focus { 155 | border: 2px solid #3498DB; 156 | box-shadow: none; 157 | } 158 | 159 | .btn { 160 | border: 2px solid transparent; 161 | background: #3498DB; 162 | color: #ffffff; 163 | font-size: 16px; 164 | line-height: 25px; 165 | padding: 10px 0; 166 | text-decoration: none; 167 | text-shadow: none; 168 | border-radius: 3px; 169 | box-shadow: none; 170 | transition: 0.25s; 171 | display: block; 172 | width: 250px; 173 | margin: 0 auto; 174 | } 175 | 176 | .btn:hover { 177 | background-color: #2980B9; 178 | } 179 | 180 | .login-link { 181 | font-size: 12px; 182 | color: #444; 183 | display: block; 184 | margin-top: 12px; 185 | } 186 | -------------------------------------------------------------------------------- /Chapter11/terraform-app/main.tf: -------------------------------------------------------------------------------- 1 | #Author: Manish Sethi 2 | # Specify the provider and access details 3 | provider "aws" { 4 | region = "${var.aws_region}" 5 | access_key = "${var.aws_access_key}" 6 | secret_key = "${var.aws_secret_key}" 7 | } 8 | 9 | # Create a VPC to launch our instances into 10 | resource "aws_vpc" "default" { 11 | cidr_block = "${var.vpc_cidr}" 12 | enable_dns_hostnames = true 13 | tags { 14 | Name = "ms-cloud-native-app" 15 | } 16 | } 17 | 18 | # Create an internet gateway to give our subnet access to the outside world 19 | resource "aws_internet_gateway" "default" { 20 | vpc_id = "${aws_vpc.default.id}" 21 | } 22 | 23 | # Grant the VPC internet access on its main route table 24 | resource "aws_route" "internet_access" { 25 | route_table_id = "${aws_vpc.default.main_route_table_id}" 26 | destination_cidr_block = "0.0.0.0/0" 27 | gateway_id = "${aws_internet_gateway.default.id}" 28 | } 29 | 30 | # Create a subnet to launch our instances into 31 | resource "aws_subnet" "default" { 32 | vpc_id = "${aws_vpc.default.id}" 33 | cidr_block = "${var.subnet_cidr}" 34 | map_public_ip_on_launch = true 35 | } 36 | 37 | 38 | # A security group for the ELB so it is accessible via the web 39 | resource "aws_security_group" "elb" { 40 | name = "cna_sg_elb" 41 | description = "Security_group_elb" 42 | vpc_id = "${aws_vpc.default.id}" 43 | 44 | # HTTP access from anywhere 45 | ingress { 46 | from_port = 5000 47 | to_port = 5000 48 | protocol = "tcp" 49 | cidr_blocks = ["0.0.0.0/0"] 50 | } 51 | 52 | # outbound internet access 53 | egress { 54 | from_port = 0 55 | to_port = 0 56 | protocol = "-1" 57 | cidr_blocks = ["0.0.0.0/0"] 58 | } 59 | 60 | } 61 | 62 | # Our default security group to access 63 | # the instances over SSH and HTTP 64 | resource "aws_security_group" "default" { 65 | name = "cna-sg-ec2" 66 | description = "Security group of app servers" 67 | vpc_id = "${aws_vpc.default.id}" 68 | 69 | # SSH access from anywhere 70 | ingress { 71 | from_port = 22 72 | to_port = 22 73 | protocol = "tcp" 74 | cidr_blocks = ["0.0.0.0/0"] 75 | } 76 | 77 | # HTTP access from the VPC 78 | ingress { 79 | from_port = 5000 80 | to_port = 5000 81 | protocol = "tcp" 82 | cidr_blocks = ["${var.vpc_cidr}"] 83 | } 84 | 85 | # outbound internet access 86 | egress { 87 | from_port = 0 88 | to_port = 0 89 | protocol = "-1" 90 | cidr_blocks = ["0.0.0.0/0"] 91 | } 92 | } 93 | 94 | resource "aws_security_group" "mongodb" { 95 | name = "cna-sg-mongodb" 96 | description = "Security group of mongodb server" 97 | vpc_id = "${aws_vpc.default.id}" 98 | 99 | # SSH access from anywhere 100 | ingress { 101 | from_port = 22 102 | to_port = 22 103 | protocol = "tcp" 104 | cidr_blocks = ["0.0.0.0/0"] 105 | } 106 | 107 | # HTTP access from the VPC 108 | ingress { 109 | from_port = 27017 110 | to_port = 27017 111 | protocol = "tcp" 112 | cidr_blocks = ["${var.vpc_cidr}"] 113 | } 114 | # HTTP access from the VPC 115 | ingress { 116 | from_port = 28017 117 | to_port = 28017 118 | protocol = "tcp" 119 | cidr_blocks = ["${var.vpc_cidr}"] 120 | } 121 | 122 | # outbound internet access 123 | egress { 124 | from_port = 0 125 | to_port = 0 126 | protocol = "-1" 127 | cidr_blocks = ["0.0.0.0/0"] 128 | } 129 | } 130 | 131 | resource "aws_elb" "web" { 132 | name = "cna-elb" 133 | 134 | subnets = ["${aws_subnet.default.id}"] 135 | security_groups = ["${aws_security_group.elb.id}"] 136 | instances = ["${aws_instance.web.*.id}"] 137 | listener { 138 | instance_port = 5000 139 | instance_protocol = "http" 140 | lb_port = 80 141 | lb_protocol = "http" 142 | } 143 | } 144 | 145 | resource "aws_key_pair" "auth" { 146 | key_name = "${var.key_name}" 147 | public_key = "${file(var.public_key_path)}" 148 | } 149 | 150 | resource "aws_instance" "web" { 151 | # The connection block tells our provisioner how to 152 | # communicate with the resource (instance) 153 | connection { 154 | # The default username for our AMI 155 | user = "ubuntu" 156 | key_file = "${var.key_file_path}" 157 | timeout = "5m" 158 | } 159 | # Tags for machine 160 | tags {Name = "cna-web"} 161 | instance_type = "t2.micro" 162 | # Number of EC2 to spin up 163 | count = "1" 164 | ami = "${lookup(var.aws_amis, var.aws_region)}" 165 | iam_instance_profile = "CodeDeploy-Instance-Role" 166 | # The name of our SSH keypair we created above. 167 | key_name = "${aws_key_pair.auth.id}" 168 | 169 | # Our Security group to allow HTTP and SSH access 170 | vpc_security_group_ids = ["${aws_security_group.default.id}"] 171 | subnet_id = "${aws_subnet.default.id}" 172 | } 173 | resource "aws_instance" "mongodb" { 174 | # The connection block tells our provisioner how to 175 | # communicate with the resource (instance) 176 | connection { 177 | # The default username for our AMI 178 | user = "ubuntu" 179 | private_key = "${file(var.key_file_path)}" 180 | timeout = "5m" 181 | # The connection will use the local SSH agent for authentication. 182 | } 183 | # Tags for machine 184 | tags {Name = "cna-web-mongodb"} 185 | instance_type = "t2.micro" 186 | # Number of EC2 to spin up 187 | count = "1" 188 | # Lookup the correct AMI based on the region 189 | # we specified 190 | ami = "${lookup(var.aws_amis, var.aws_region)}" 191 | iam_instance_profile = "CodeDeploy-Instance-Role" 192 | # The name of our SSH keypair we created above. 193 | key_name = "${aws_key_pair.auth.id}" 194 | 195 | # Our Security group to allow HTTP and SSH access 196 | vpc_security_group_ids = ["${aws_security_group.mongodb.id}"] 197 | 198 | subnet_id = "${aws_subnet.default.id}" 199 | provisioner "remote-exec" { 200 | inline = [ 201 | "sudo echo -ne '\n' | apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10", 202 | "echo 'deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.2 multiverse' | sudo tee /etc/apt/sources.list.d/mongodb-org-3.2.list", 203 | "sudo apt-get update -y && sudo apt-get install mongodb-org --force-yes -y", 204 | ] 205 | } 206 | 207 | } 208 | -------------------------------------------------------------------------------- /Chapter02/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, jsonify 2 | from flask import abort 3 | from flask import make_response, url_for 4 | import json 5 | from time import gmtime, strftime 6 | import sqlite3 7 | 8 | 9 | 10 | app = Flask(__name__) 11 | 12 | def list_users(): 13 | conn = sqlite3.connect('mydb.db') 14 | print ("Opened database successfully"); 15 | api_list=[] 16 | cursor = conn.execute("SELECT username, full_name, email, password, id from users") 17 | for row in cursor: 18 | a_dict = {} 19 | a_dict['username'] = row[0] 20 | a_dict['name'] = row[1] 21 | a_dict['email'] = row[2] 22 | a_dict['password'] = row[3] 23 | a_dict['id'] = row[4] 24 | api_list.append(a_dict) 25 | 26 | conn.close() 27 | return jsonify({'user_list': api_list}) 28 | 29 | def list_user(user_id): 30 | conn = sqlite3.connect('mydb.db') 31 | print ("Opened database successfully"); 32 | api_list=[] 33 | cursor=conn.cursor() 34 | cursor.execute("SELECT * from users where id=?",(user_id,)) 35 | data = cursor.fetchall() 36 | print (data) 37 | if len(data) == 0: 38 | abort(404) 39 | else: 40 | 41 | user = {} 42 | user['username'] = data[0][0] 43 | user['name'] = data[0][1] 44 | user['email'] = data[0][2] 45 | user['password'] = data[0][3] 46 | user['id'] = data[0][4] 47 | 48 | conn.close() 49 | return jsonify(user) 50 | 51 | 52 | def list_tweet(user_id): 53 | print (user_id) 54 | conn = sqlite3.connect('mydb.db') 55 | print ("Opened database successfully"); 56 | api_list=[] 57 | cursor=conn.cursor() 58 | cursor.execute("SELECT * from tweets where id=?",(user_id,)) 59 | data = cursor.fetchall() 60 | print (data) 61 | if len(data) == 0: 62 | abort(404) 63 | else: 64 | 65 | user = {} 66 | user['id'] = data[0][0] 67 | user['username'] = data[0][1] 68 | user['body'] = data[0][2] 69 | user['tweet_time'] = data[0][3] 70 | 71 | conn.close() 72 | return jsonify(user) 73 | 74 | def add_user(new_user): 75 | conn = sqlite3.connect('mydb.db') 76 | print ("Opened database successfully"); 77 | api_list=[] 78 | cursor=conn.cursor() 79 | cursor.execute("SELECT * from users where username=? or email=?",(new_user['username'],new_user['email'])) 80 | data = cursor.fetchall() 81 | if len(data) != 0: 82 | abort(409) 83 | else: 84 | cursor.execute("insert into users (username, email, password, full_name) values(?,?,?,?)",(new_user['username'],new_user['email'], new_user['password'], new_user['name'])) 85 | conn.commit() 86 | return "Success" 87 | conn.close() 88 | return jsonify(a_dict) 89 | 90 | 91 | def del_user(del_user): 92 | conn = sqlite3.connect('mydb.db') 93 | print ("Opened database successfully"); 94 | cursor=conn.cursor() 95 | cursor.execute("SELECT * from users where username=? ",(del_user,)) 96 | data = cursor.fetchall() 97 | print ("Data" ,data) 98 | if len(data) == 0: 99 | abort(404) 100 | else: 101 | cursor.execute("delete from users where username==?",(del_user,)) 102 | conn.commit() 103 | return "Success" 104 | 105 | def list_tweets(): 106 | conn = sqlite3.connect('mydb.db') 107 | print ("Opened database successfully"); 108 | api_list=[] 109 | cursor=conn.cursor() 110 | cursor.execute("SELECT username, body, tweet_time, id from tweets") 111 | data = cursor.fetchall() 112 | print (data) 113 | print (len(data)) 114 | if len(data) == 0: 115 | return api_list 116 | else: 117 | for row in data: 118 | tweets = {} 119 | 120 | tweets['tweetedby'] = row[0] 121 | tweets['body'] = row[1] 122 | tweets['timestamp'] = row[2] 123 | tweets['id'] = row[3] 124 | 125 | print (tweets) 126 | api_list.append(tweets) 127 | 128 | conn.close() 129 | print (api_list) 130 | return jsonify({'tweets_list': api_list}) 131 | 132 | def add_tweet(new_tweets): 133 | conn = sqlite3.connect('mydb.db') 134 | print ("Opened database successfully"); 135 | cursor=conn.cursor() 136 | cursor.execute("SELECT * from users where username=? ",(new_tweets['username'],)) 137 | data = cursor.fetchall() 138 | 139 | if len(data) == 0: 140 | abort(404) 141 | else: 142 | cursor.execute("INSERT into tweets (username, body, tweet_time) values(?,?,?)",(new_tweets['username'],new_tweets['body'], new_tweets['created_at'])) 143 | conn.commit() 144 | return "Success" 145 | 146 | def upd_user(user): 147 | conn = sqlite3.connect('mydb.db') 148 | print ("Opened database successfully"); 149 | cursor=conn.cursor() 150 | cursor.execute("SELECT * from users where id=? ",(user['id'],)) 151 | data = cursor.fetchall() 152 | print (data) 153 | if len(data) == 0: 154 | abort(404) 155 | else: 156 | key_list=user.keys() 157 | for i in key_list: 158 | if i != "id": 159 | print (user, i) 160 | # cursor.execute("UPDATE users set {0}=? where id=? ", (i, user[i], user['id'])) 161 | cursor.execute("""UPDATE users SET {0} = ? WHERE id = ?""".format(i), (user[i], user['id'])) 162 | conn.commit() 163 | return "Success" 164 | 165 | 166 | 167 | @app.route("/api/v1/info") 168 | def home_index(): 169 | conn = sqlite3.connect('mydb.db') 170 | print ("Opened database successfully"); 171 | api_list=[] 172 | cursor = conn.execute("SELECT buildtime, version, methods, links from apirelease") 173 | for row in cursor: 174 | api = {} 175 | api['version'] = row[0] 176 | api['buildtime'] = row[1] 177 | api['methods'] = row[2] 178 | api['links'] = row[3] 179 | api_list.append(api) 180 | conn.close() 181 | return jsonify({'api_version': api_list}), 200 182 | 183 | 184 | 185 | @app.route('/api/v1/users', methods=['GET']) 186 | def get_users(): 187 | return list_users() 188 | 189 | @app.route('/api/v1/users/', methods=['GET']) 190 | def get_user(user_id): 191 | return list_user(user_id) 192 | 193 | 194 | @app.route('/api/v1/users', methods=['POST']) 195 | def create_user(): 196 | if not request.json or not 'username' in request.json or not 'email' in request.json or not 'password' in request.json: 197 | abort(400) 198 | user = { 199 | 'username': request.json['username'], 200 | 'email': request.json['email'], 201 | 'name': request.json.get('name',""), 202 | 'password': request.json['password'] 203 | } 204 | return jsonify({'status': add_user(user)}), 201 205 | 206 | @app.route('/api/v1/users', methods=['DELETE']) 207 | def delete_user(): 208 | if not request.json or not 'username' in request.json: 209 | abort(400) 210 | user=request.json['username'] 211 | return jsonify({'status': del_user(user)}), 200 212 | 213 | 214 | @app.route('/api/v1/users/', methods=['PUT']) 215 | def update_user(user_id): 216 | user = {} 217 | # if not request.json: 218 | # abort(400) 219 | user['id']=user_id 220 | key_list = request.json.keys() 221 | for i in key_list: 222 | user[i] = request.json[i] 223 | print (user) 224 | 225 | return jsonify({'status': upd_user(user)}), 200 226 | 227 | 228 | 229 | 230 | 231 | @app.route('/api/v2/tweets', methods=['GET']) 232 | def get_tweets(): 233 | return list_tweets() 234 | 235 | @app.route('/api/v2/tweets', methods=['POST']) 236 | def add_tweets(): 237 | 238 | user_tweet = {} 239 | if not request.json or not 'username' in request.json or not 'body' in request.json: 240 | abort(400) 241 | user_tweet['username'] = request.json['username'] 242 | user_tweet['body'] = request.json['body'] 243 | user_tweet['created_at']=strftime("%Y-%m-%dT%H:%M:%SZ", gmtime()) 244 | print (user_tweet) 245 | return jsonify({'status': add_tweet(user_tweet)}), 201 246 | 247 | @app.route('/api/v2/tweets/', methods=['GET']) 248 | def get_tweet(id): 249 | return list_tweet(id) 250 | 251 | 252 | @app.errorhandler(404) 253 | def resource_not_found(error): 254 | return make_response(jsonify({'error': 'Resource not found!'}), 404) 255 | 256 | @app.errorhandler(409) 257 | def user_found(error): 258 | return make_response(jsonify({'error': 'Conflict! Record exist'}), 409) 259 | 260 | @app.errorhandler(400) 261 | def invalid_request(error): 262 | return make_response(jsonify({'error': 'Bad Request'}), 400) 263 | 264 | if __name__ == '__main__': 265 | app.run(host='0.0.0.0', port=5000, debug=True) 266 | -------------------------------------------------------------------------------- /Chapter05/app.py: -------------------------------------------------------------------------------- 1 | # Importing modules 2 | from flask import Flask, flash, render_template, flash, request, jsonify, redirect, session 3 | from flask import abort 4 | import bcrypt 5 | from flask_cors import CORS, cross_origin 6 | from flask import make_response, url_for 7 | import json 8 | import random 9 | from requests import Requests 10 | from pymongo import MongoClient 11 | from flask.ext.pymongo import PyMongo 12 | from time import gmtime, strftime 13 | 14 | from flask.ext.mongoalchemy import MongoAlchemy 15 | 16 | 17 | # Object creation 18 | app = Flask(__name__) 19 | app.config.from_object(__name__) 20 | app.secret_key = '' 21 | CORS(app) 22 | 23 | app.config['MONGOALCHEMY_DATABASE'] = 'app' 24 | app.config['MONGOALCHEMY_CONNECTION_STRING'] = 'mongodb://localhost:27017/' 25 | connection = MongoClient("mongodb://localhost:27017/") 26 | 27 | 28 | db = MongoAlchemy() 29 | 30 | mongo=PyMongo(app) 31 | # Initialize Database 32 | def create_mongodatabase(): 33 | try: 34 | dbnames = connection.database_names() 35 | if 'app' not in dbnames: 36 | db_api = connection.app.apirelease 37 | db_api.insert( { 38 | "buildtime": "2017-01-01 10:00:00", 39 | "links": "/api/v1/users", 40 | "methods": "get, post, put, delete", 41 | "version": "v1" 42 | }) 43 | db_api.insert( { 44 | "buildtime": "2017-02-11 10:00:00", 45 | "links": "api/v2/tweets", 46 | "methods": "get, post", 47 | "version": "2017-01-10 10:00:00" 48 | }) 49 | print ("Database Initialize completed!") 50 | else: 51 | print ("Database already Initialized!") 52 | except: 53 | print ("Database creation failed!!") 54 | 55 | 56 | # API Routes 57 | @app.route('/') 58 | def home(): 59 | if not session.get('logged_in'): 60 | return render_template('login.html') 61 | else: 62 | return render_template('index.html', session = session['username']) 63 | 64 | @app.route('/index') 65 | def index(): 66 | return render_template('index.html', session = session['username']) 67 | 68 | @app.route('/login', methods=['POST']) 69 | def do_admin_login(): 70 | users = mongo.db.users 71 | api_list=[] 72 | login_user = users.find({'username': request.form['username']}) 73 | for i in login_user: 74 | api_list.append(i) 75 | print (api_list) 76 | if api_list != []: 77 | # print (api_list[0]['password'].decode('utf-8'), bcrypt.hashpw(request.form['password'].encode('utf-8'), api_list[0]['password']).decode('utf-8')) 78 | if api_list[0]['password'].decode('utf-8') == bcrypt.hashpw(request.form['password'].encode('utf-8'), api_list[0]['password']).decode('utf-8'): 79 | session['logged_in'] = api_list[0]['username'] 80 | return redirect(url_for('index')) 81 | return 'Invalide username/password!' 82 | else: 83 | flash("Invalid Authentication") 84 | 85 | return 'Invalid User!' 86 | 87 | 88 | 89 | @app.route('/signup', methods=['GET', 'POST']) 90 | def signup(): 91 | if request.method=='POST': 92 | users = mongo.db.users 93 | api_list=[] 94 | existing_user = users.find({'$or':[{"username":request.form['username']} ,{"email":request.form['email']}]}) 95 | for i in existing_user: 96 | # print (str(i)) 97 | api_list.append(str(i)) 98 | 99 | # print (api_list) 100 | if api_list == []: 101 | users.insert({ 102 | "email": request.form['email'], 103 | "id": random.randint(1,1000), 104 | "name": request.form['name'], 105 | "password": bcrypt.hashpw(request.form['pass'].encode('utf-8'), bcrypt.gensalt()), 106 | "username": request.form['username'] 107 | }) 108 | session['username'] = request.form['username'] 109 | return redirect(url_for('home')) 110 | 111 | return 'That user already exists' 112 | else : 113 | return render_template('signup.html') 114 | 115 | 116 | 117 | 118 | @app.route("/logout") 119 | def logout(): 120 | session['logged_in'] = False 121 | return redirect(url_for('home')) 122 | 123 | @app.route('/profile', methods=['GET', 'POST']) 124 | def profile(): 125 | if request.method=='POST': 126 | users = mongo.db.users 127 | api_list=[] 128 | existing_users = users.find({"username":session['username']}) 129 | for i in existing_users: 130 | # print (str(i)) 131 | api_list.append(str(i)) 132 | user = {} 133 | print (api_list) 134 | if api_list != []: 135 | print (request.form['email']) 136 | user['email']=request.form['email'] 137 | user['name']= request.form['name'] 138 | user['password']=request.form['pass'] 139 | users.update({'username':session['username']},{'$set': user} ) 140 | else: 141 | return 'User not found!' 142 | return redirect(url_for('index')) 143 | if request.method=='GET': 144 | users = mongo.db.users 145 | user=[] 146 | print (session['username']) 147 | existing_user = users.find({"username":session['username']}) 148 | for i in existing_user: 149 | user.append(i) 150 | return render_template('profile.html', name=user[0]['name'], username=user[0]['username'], password=user[0]['password'], email=user[0]['email']) 151 | 152 | 153 | 154 | @app.route("/api/v1/info") 155 | def home_index(): 156 | api_list=[] 157 | db = connection.app.apirelease 158 | for row in db.find(): 159 | print (row) 160 | # api_list['buildtime']. str(row['buildtime']) 161 | # api_list['version'] = str(row['version']) 162 | # api_list['links'] = str(row['links']) 163 | # api_list['methods'] = str(row['methods']) 164 | api_list.append(str(row)) 165 | print (api_list) 166 | return json.dumps(api_list), 200 167 | 168 | 169 | 170 | @app.route('/api/v1/users', methods=['GET']) 171 | def get_users(): 172 | return Requests.list_users() 173 | 174 | @app.route('/api/v1/users/', methods=['GET']) 175 | def get_user(user_id): 176 | return Requests.list_user(user_id) 177 | 178 | 179 | @app.route('/api/v1/users', methods=['POST']) 180 | def create_user(): 181 | if not request.json or not 'username' in request.json or not 'email' in request.json or not 'password' in request.json: 182 | abort(400) 183 | user = { 184 | 'username': request.json['username'], 185 | 'email': request.json['email'], 186 | 'name': request.json.get('name',""), 187 | 'password': request.json['password'], 188 | 'id': random.randint(1,1000) 189 | } 190 | return jsonify({'status': Requests.add_user(user)}), 201 191 | 192 | @app.route('/api/v1/users', methods=['DELETE']) 193 | def delete_user(): 194 | if not request.json or not 'username' in request.json: 195 | abort(400) 196 | user=request.json['username'] 197 | return jsonify({'status': Requests.del_user(user)}), 200 198 | 199 | 200 | @app.route('/api/v1/users/', methods=['PUT']) 201 | def update_user(user_id): 202 | user = {} 203 | user['id']=user_id 204 | key_list = request.json.keys() 205 | for i in key_list: 206 | user[i] = request.json[i] 207 | return jsonify({'status': Requests.upd_user(user)}), 200 208 | 209 | @app.route('/api/v2/tweets', methods=['GET']) 210 | def get_tweets(): 211 | return Requests.list_tweets() 212 | 213 | @app.route('/api/v2/tweets', methods=['POST']) 214 | def add_tweets(): 215 | 216 | user_tweet = {} 217 | if not request.json or not 'username' in request.json or not 'body' in request.json: 218 | abort(400) 219 | user_tweet['tweetedby'] = request.json['username'] 220 | user_tweet['body'] = request.json['body'] 221 | user_tweet['timestamp']=strftime("%Y-%m-%dT%H:%M:%SZ", gmtime()) 222 | user_tweet['id'] = random.randint(1,1000) 223 | 224 | return jsonify({'status': Requests.add_tweet(user_tweet)}), 201 225 | 226 | @app.route('/api/v2/tweets/', methods=['GET']) 227 | def get_tweet(tweetedby): 228 | return Requests.list_tweet(tweetedby) 229 | 230 | # Error handling 231 | @app.errorhandler(404) 232 | def resource_not_found(error): 233 | return make_response(jsonify({'error': 'Resource not found!'}), 404) 234 | 235 | @app.errorhandler(409) 236 | def user_found(error): 237 | return make_response(jsonify({'error': 'Conflict! Record exist'}), 409) 238 | 239 | @app.errorhandler(400) 240 | def invalid_request(error): 241 | return make_response(jsonify({'error': 'Bad Request'}), 400) 242 | 243 | # Main Function 244 | if __name__ == '__main__': 245 | create_mongodatabase() 246 | app.run(host='0.0.0.0', port=5000, debug=True) 247 | -------------------------------------------------------------------------------- /Chapter06/app.py: -------------------------------------------------------------------------------- 1 | # Importing modules 2 | from flask import Flask, flash, render_template, flash, request, jsonify, redirect, session 3 | from flask import abort 4 | import bcrypt 5 | from flask_cors import CORS, cross_origin 6 | from flask import make_response, url_for 7 | import json 8 | import random 9 | from requests import Requests 10 | from pymongo import MongoClient 11 | from flask.ext.pymongo import PyMongo 12 | from time import gmtime, strftime 13 | 14 | from flask.ext.mongoalchemy import MongoAlchemy 15 | 16 | 17 | # Object creation 18 | app = Flask(__name__) 19 | app.config.from_object(__name__) 20 | app.secret_key = '' 21 | CORS(app) 22 | 23 | app.config['MONGOALCHEMY_DATABASE'] = 'app' 24 | app.config['MONGOALCHEMY_CONNECTION_STRING'] = 'mongodb://localhost:27017/' 25 | connection = MongoClient("mongodb://localhost:27017/") 26 | 27 | 28 | db = MongoAlchemy() 29 | 30 | mongo=PyMongo(app) 31 | # Initialize Database 32 | def create_mongodatabase(): 33 | try: 34 | dbnames = connection.database_names() 35 | if 'app' not in dbnames: 36 | db_api = connection.app.apirelease 37 | db_api.insert( { 38 | "buildtime": "2017-01-01 10:00:00", 39 | "links": "/api/v1/users", 40 | "methods": "get, post, put, delete", 41 | "version": "v1" 42 | }) 43 | db_api.insert( { 44 | "buildtime": "2017-02-11 10:00:00", 45 | "links": "api/v2/tweets", 46 | "methods": "get, post", 47 | "version": "2017-01-10 10:00:00" 48 | }) 49 | print ("Database Initialize completed!") 50 | else: 51 | print ("Database already Initialized!") 52 | except: 53 | print ("Database creation failed!!") 54 | 55 | 56 | # API Routes 57 | @app.route('/') 58 | def home(): 59 | if not session.get('logged_in'): 60 | return render_template('login.html') 61 | else: 62 | return render_template('index.html', session = session['logged_in']) 63 | 64 | @app.route('/index') 65 | def index(): 66 | return render_template('index.html', session = session['logged_in']) 67 | 68 | @app.route('/login', methods=['POST']) 69 | def do_admin_login(): 70 | users = mongo.db.users 71 | api_list=[] 72 | login_user = users.find({'username': request.form['username']}) 73 | for i in login_user: 74 | api_list.append(i) 75 | print (api_list) 76 | if api_list != []: 77 | #print (api_list[0]['password'].decode('utf-8'), bcrypt.hashpw(request.form['password'].encode('utf-8'), api_list[0]['password']).decode('utf-8')) 78 | if api_list[0]['password'].decode('utf-8') == bcrypt.hashpw(request.form['password'].encode('utf-8'), api_list[0]['password']).decode('utf-8'): 79 | session['logged_in'] = api_list[0]['username'] 80 | return redirect(url_for('index')) 81 | return 'Invalide username/password!' 82 | else: 83 | flash("Invalid Authentication") 84 | 85 | return 'Invalid User!' 86 | 87 | 88 | 89 | @app.route('/signup', methods=['GET', 'POST']) 90 | def signup(): 91 | if request.method=='POST': 92 | users = mongo.db.users 93 | api_list=[] 94 | existing_user = users.find({'$or':[{"username":request.form['username']} ,{"email":request.form['email']}]}) 95 | for i in existing_user: 96 | # print (str(i)) 97 | api_list.append(str(i)) 98 | 99 | # print (api_list) 100 | if api_list == []: 101 | users.insert({ 102 | "email": (request.form['email']).lower(), 103 | "id": random.randint(1,1000), 104 | "name": request.form['name'], 105 | "password": bcrypt.hashpw(request.form['pass'].encode('utf-8'), bcrypt.gensalt()), 106 | "username": request.form['username'] 107 | }) 108 | session['username'] = request.form['username'] 109 | return redirect(url_for('home')) 110 | 111 | return 'That user already exists' 112 | else : 113 | return render_template('signup.html') 114 | 115 | 116 | 117 | 118 | @app.route("/logout") 119 | def logout(): 120 | session['logged_in'] = False 121 | return redirect(url_for('home')) 122 | 123 | @app.route('/profile', methods=['GET', 'POST']) 124 | def profile(): 125 | if request.method=='POST': 126 | users = mongo.db.users 127 | api_list=[] 128 | existing_users = users.find({"username":session['username']}) 129 | for i in existing_users: 130 | # print (str(i)) 131 | api_list.append(str(i)) 132 | user = {} 133 | print (api_list) 134 | if api_list != []: 135 | print (request.form['email']) 136 | user['email']=(request.form['email']).lower() 137 | user['name']= request.form['name'] 138 | user['password']=bcrypt.hashpw(request.form['pass'].encode('utf-8'), bcrypt.gensalt()) 139 | users.update({'username':session['username']},{'$set': user} ) 140 | else: 141 | return 'User not found!' 142 | return redirect(url_for('index')) 143 | if request.method=='GET': 144 | users = mongo.db.users 145 | user=[] 146 | print (session['username']) 147 | existing_user = users.find({"username":session['username']}) 148 | for i in existing_user: 149 | user.append(i) 150 | return render_template('profile.html', name=user[0]['name'], username=user[0]['username'], password=user[0]['password'], email=user[0]['email']) 151 | 152 | 153 | 154 | @app.route("/api/v1/info") 155 | def home_index(): 156 | api_list=[] 157 | db = connection.app.apirelease 158 | for row in db.find(): 159 | print (row) 160 | # api_list['buildtime']. str(row['buildtime']) 161 | # api_list['version'] = str(row['version']) 162 | # api_list['links'] = str(row['links']) 163 | # api_list['methods'] = str(row['methods']) 164 | api_list.append(str(row)) 165 | print (api_list) 166 | return json.dumps(api_list), 200 167 | 168 | 169 | 170 | @app.route('/api/v1/users', methods=['GET']) 171 | def get_users(): 172 | return Requests.list_users() 173 | 174 | @app.route('/api/v1/users/', methods=['GET']) 175 | def get_user(user_id): 176 | return Requests.list_user(user_id) 177 | 178 | 179 | @app.route('/api/v1/users', methods=['POST']) 180 | def create_user(): 181 | if not request.json or not 'username' in request.json or not 'email' in request.json or not 'password' in request.json: 182 | abort(400) 183 | user = { 184 | 'username': request.json['username'], 185 | 'email': request.json['email'], 186 | 'name': request.json.get('name',""), 187 | 'password': request.json['password'], 188 | 'id': random.randint(1,1000) 189 | } 190 | return jsonify({'status': Requests.add_user(user)}), 201 191 | 192 | @app.route('/api/v1/users', methods=['DELETE']) 193 | def delete_user(): 194 | if not request.json or not 'username' in request.json: 195 | abort(400) 196 | user=request.json['username'] 197 | return jsonify({'status': Requests.del_user(user)}), 200 198 | 199 | 200 | @app.route('/api/v1/users/', methods=['PUT']) 201 | def update_user(user_id): 202 | user = {} 203 | user['id']=user_id 204 | key_list = request.json.keys() 205 | for i in key_list: 206 | user[i] = request.json[i] 207 | return jsonify({'status': Requests.upd_user(user)}), 200 208 | 209 | @app.route('/api/v2/tweets', methods=['GET']) 210 | def get_tweets(): 211 | return Requests.list_tweets() 212 | 213 | @app.route('/api/v2/tweets', methods=['POST']) 214 | def add_tweets(): 215 | 216 | user_tweet = {} 217 | if not request.json or not 'username' in request.json or not 'body' in request.json: 218 | abort(400) 219 | user_tweet['tweetedby'] = request.json['username'] 220 | user_tweet['body'] = request.json['body'] 221 | user_tweet['timestamp']=strftime("%Y-%m-%dT%H:%M:%SZ", gmtime()) 222 | user_tweet['id'] = random.randint(1,1000) 223 | 224 | return jsonify({'status': Requests.add_tweet(user_tweet)}), 201 225 | 226 | @app.route('/api/v2/tweets/', methods=['GET']) 227 | def get_tweet(tweetedby): 228 | return Requests.list_tweet(tweetedby) 229 | 230 | 231 | 232 | # Error handling 233 | @app.errorhandler(404) 234 | def resource_not_found(error): 235 | return make_response(jsonify({'error': 'Resource not found!'}), 404) 236 | 237 | @app.errorhandler(409) 238 | def user_found(error): 239 | return make_response(jsonify({'error': 'Conflict! Record exist'}), 409) 240 | 241 | @app.errorhandler(400) 242 | def invalid_request(error): 243 | return make_response(jsonify({'error': 'Bad Request'}), 400) 244 | 245 | # Main Function 246 | if __name__ == '__main__': 247 | create_mongodatabase() 248 | app.run(host='0.0.0.0', port=5000, debug=True) 249 | -------------------------------------------------------------------------------- /Chapter07/app.py: -------------------------------------------------------------------------------- 1 | # Importing modules 2 | from flask import Flask, flash, render_template, flash, request, jsonify, redirect, session 3 | from flask import abort 4 | import bcrypt 5 | from flask_cors import CORS, cross_origin 6 | from flask import make_response, url_for 7 | import json 8 | import random 9 | from requests import Requests 10 | from pymongo import MongoClient 11 | from flask.ext.pymongo import PyMongo 12 | from time import gmtime, strftime 13 | 14 | from flask.ext.mongoalchemy import MongoAlchemy 15 | 16 | 17 | # Object creation 18 | app = Flask(__name__) 19 | app.config.from_object(__name__) 20 | app.secret_key = '' 21 | CORS(app) 22 | 23 | app.config['MONGOALCHEMY_DATABASE'] = 'app' 24 | app.config['MONGOALCHEMY_CONNECTION_STRING'] = 'mongodb://localhost:27017/' 25 | connection = MongoClient("mongodb://localhost:27017/") 26 | 27 | 28 | db = MongoAlchemy() 29 | 30 | mongo=PyMongo(app) 31 | # Initialize Database 32 | def create_mongodatabase(): 33 | try: 34 | dbnames = connection.database_names() 35 | if 'app' not in dbnames: 36 | db_api = connection.app.apirelease 37 | db_api.insert( { 38 | "buildtime": "2017-01-01 10:00:00", 39 | "links": "/api/v1/users", 40 | "methods": "get, post, put, delete", 41 | "version": "v1" 42 | }) 43 | db_api.insert( { 44 | "buildtime": "2017-02-11 10:00:00", 45 | "links": "api/v2/tweets", 46 | "methods": "get, post", 47 | "version": "2017-01-10 10:00:00" 48 | }) 49 | print ("Database Initialize completed!") 50 | else: 51 | print ("Database already Initialized!") 52 | except: 53 | print ("Database creation failed!!") 54 | 55 | 56 | # API Routes 57 | @app.route('/') 58 | def home(): 59 | if not session.get('logged_in'): 60 | return render_template('login.html') 61 | else: 62 | return render_template('index.html', session = session['logged_in']) 63 | 64 | @app.route('/index') 65 | def index(): 66 | return render_template('index.html', session = session['logged_in']) 67 | 68 | @app.route('/login', methods=['POST']) 69 | def do_admin_login(): 70 | users = mongo.db.users 71 | api_list=[] 72 | login_user = users.find({'username': request.form['username']}) 73 | for i in login_user: 74 | api_list.append(i) 75 | print (api_list) 76 | if api_list != []: 77 | #print (api_list[0]['password'].decode('utf-8'), bcrypt.hashpw(request.form['password'].encode('utf-8'), api_list[0]['password']).decode('utf-8')) 78 | if api_list[0]['password'].decode('utf-8') == bcrypt.hashpw(request.form['password'].encode('utf-8'), api_list[0]['password']).decode('utf-8'): 79 | session['logged_in'] = api_list[0]['username'] 80 | return redirect(url_for('index')) 81 | return 'Invalide username/password!' 82 | else: 83 | flash("Invalid Authentication") 84 | 85 | return 'Invalid User!' 86 | 87 | 88 | 89 | @app.route('/signup', methods=['GET', 'POST']) 90 | def signup(): 91 | if request.method=='POST': 92 | users = mongo.db.users 93 | api_list=[] 94 | existing_user = users.find({'$or':[{"username":request.form['username']} ,{"email":request.form['email']}]}) 95 | for i in existing_user: 96 | # print (str(i)) 97 | api_list.append(str(i)) 98 | 99 | # print (api_list) 100 | if api_list == []: 101 | users.insert({ 102 | "email": (request.form['email']).lower(), 103 | "id": random.randint(1,1000), 104 | "name": request.form['name'], 105 | "password": bcrypt.hashpw(request.form['pass'].encode('utf-8'), bcrypt.gensalt()), 106 | "username": request.form['username'] 107 | }) 108 | session['username'] = request.form['username'] 109 | return redirect(url_for('home')) 110 | 111 | return 'That user already exists' 112 | else : 113 | return render_template('signup.html') 114 | 115 | 116 | 117 | 118 | @app.route("/logout") 119 | def logout(): 120 | session['logged_in'] = False 121 | return redirect(url_for('home')) 122 | 123 | @app.route('/profile', methods=['GET', 'POST']) 124 | def profile(): 125 | if request.method=='POST': 126 | users = mongo.db.users 127 | api_list=[] 128 | existing_users = users.find({"username":session['username']}) 129 | for i in existing_users: 130 | # print (str(i)) 131 | api_list.append(str(i)) 132 | user = {} 133 | print (api_list) 134 | if api_list != []: 135 | print (request.form['email']) 136 | user['email']=(request.form['email']).lower() 137 | user['name']= request.form['name'] 138 | user['password']=bcrypt.hashpw(request.form['pass'].encode('utf-8'), bcrypt.gensalt()) 139 | users.update({'username':session['username']},{'$set': user} ) 140 | else: 141 | return 'User not found!' 142 | return redirect(url_for('index')) 143 | if request.method=='GET': 144 | users = mongo.db.users 145 | user=[] 146 | print (session['username']) 147 | existing_user = users.find({"username":session['username']}) 148 | for i in existing_user: 149 | user.append(i) 150 | return render_template('profile.html', name=user[0]['name'], username=user[0]['username'], password=user[0]['password'], email=user[0]['email']) 151 | 152 | 153 | 154 | @app.route("/api/v1/info") 155 | def home_index(): 156 | api_list=[] 157 | db = connection.app.apirelease 158 | for row in db.find(): 159 | print (row) 160 | # api_list['buildtime']. str(row['buildtime']) 161 | # api_list['version'] = str(row['version']) 162 | # api_list['links'] = str(row['links']) 163 | # api_list['methods'] = str(row['methods']) 164 | api_list.append(str(row)) 165 | print (api_list) 166 | return json.dumps(api_list), 200 167 | 168 | 169 | 170 | @app.route('/api/v1/users', methods=['GET']) 171 | def get_users(): 172 | return Requests.list_users() 173 | 174 | @app.route('/api/v1/users/', methods=['GET']) 175 | def get_user(user_id): 176 | return Requests.list_user(user_id) 177 | 178 | 179 | @app.route('/api/v1/users', methods=['POST']) 180 | def create_user(): 181 | if not request.json or not 'username' in request.json or not 'email' in request.json or not 'password' in request.json: 182 | abort(400) 183 | user = { 184 | 'username': request.json['username'], 185 | 'email': request.json['email'], 186 | 'name': request.json.get('name',""), 187 | 'password': request.json['password'], 188 | 'id': random.randint(1,1000) 189 | } 190 | return jsonify({'status': Requests.add_user(user)}), 201 191 | 192 | @app.route('/api/v1/users', methods=['DELETE']) 193 | def delete_user(): 194 | if not request.json or not 'username' in request.json: 195 | abort(400) 196 | user=request.json['username'] 197 | return jsonify({'status': Requests.del_user(user)}), 200 198 | 199 | 200 | @app.route('/api/v1/users/', methods=['PUT']) 201 | def update_user(user_id): 202 | user = {} 203 | user['id']=user_id 204 | key_list = request.json.keys() 205 | for i in key_list: 206 | user[i] = request.json[i] 207 | return jsonify({'status': Requests.upd_user(user)}), 200 208 | 209 | @app.route('/api/v2/tweets', methods=['GET']) 210 | def get_tweets(): 211 | return Requests.list_tweets() 212 | 213 | @app.route('/api/v2/tweets', methods=['POST']) 214 | def add_tweets(): 215 | 216 | user_tweet = {} 217 | if not request.json or not 'username' in request.json or not 'body' in request.json: 218 | abort(400) 219 | user_tweet['tweetedby'] = request.json['username'] 220 | user_tweet['body'] = request.json['body'] 221 | user_tweet['timestamp']=strftime("%Y-%m-%dT%H:%M:%SZ", gmtime()) 222 | user_tweet['id'] = random.randint(1,1000) 223 | 224 | return jsonify({'status': Requests.add_tweet(user_tweet)}), 201 225 | 226 | @app.route('/api/v2/tweets/', methods=['GET']) 227 | def get_tweet(tweetedby): 228 | return Requests.list_tweet(tweetedby) 229 | 230 | 231 | 232 | # Error handling 233 | @app.errorhandler(404) 234 | def resource_not_found(error): 235 | return make_response(jsonify({'error': 'Resource not found!'}), 404) 236 | 237 | @app.errorhandler(409) 238 | def user_found(error): 239 | return make_response(jsonify({'error': 'Conflict! Record exist'}), 409) 240 | 241 | @app.errorhandler(400) 242 | def invalid_request(error): 243 | return make_response(jsonify({'error': 'Bad Request'}), 400) 244 | 245 | # Main Function 246 | if __name__ == '__main__': 247 | create_mongodatabase() 248 | app.run(host='0.0.0.0', port=5000, debug=True) 249 | --------------------------------------------------------------------------------