├── README.md ├── app-engine-lab-2 ├── acggiftart │ ├── __init__.py │ ├── crud.py │ ├── model_cloudsql.py │ ├── model_datastore.py │ ├── model_mongodb.py │ ├── static │ │ ├── images │ │ │ ├── GuruGiftArt.png │ │ │ ├── acg-logo-small.png │ │ │ ├── acg-logo.png │ │ │ └── add-icon.png │ │ └── styles │ │ │ └── main.css │ ├── storage.py │ └── templates │ │ ├── base.html │ │ ├── form.html │ │ ├── list.html │ │ └── view.html ├── app.yaml ├── assets │ └── generic-ACG-album.png ├── config.py ├── main.py ├── requirements-dev.txt └── requirements.txt ├── app-engine-lab ├── app.yaml ├── assets │ ├── LaGiftArt.png │ ├── albums │ │ ├── Grace-Jones-Island-Life-album-cover.jpg │ │ ├── The-Beatles-Sgt-Peppers-Lonely-Hearts-Club-Band-Album-Cover-530.jpg │ │ ├── aladdin-sane-david-bowie-768x768.jpg │ │ ├── apollo-18.jpg │ │ └── houses-of-the-holy.jpg │ └── generic-LA-album.png ├── config.py ├── lagiftart │ ├── __init__.py │ ├── crud.py │ ├── model_cloudsql.py │ ├── model_datastore.py │ ├── model_mongodb.py │ ├── static │ │ ├── images │ │ │ ├── LA-MusicGallery-logo.png │ │ │ ├── LA-logo.png │ │ │ ├── LaGiftArt.png │ │ │ └── add-icon.png │ │ └── styles │ │ │ └── main.css │ ├── storage.py │ └── templates │ │ ├── base.html │ │ ├── form.html │ │ ├── list.html │ │ └── view.html ├── main.py ├── requirements-dev.txt └── requirements.txt ├── cicd-lab ├── README.md ├── cloudbuild.yaml ├── main.py └── requirements.txt ├── cloud-functions-lab ├── README.md ├── main.py └── requirements.txt ├── kubernetes-engine-lab ├── app.py ├── config.yaml ├── dockerfile └── requirements.txt └── sql-lab ├── MetObjects_Table.sql └── MetObjects_subset.csv /README.md: -------------------------------------------------------------------------------- 1 | # content-gcpro-developer 2 | The files in this repository are for use with the Google Certified Professional Cloud Developer course at Linux Academy. 3 | -------------------------------------------------------------------------------- /app-engine-lab-2/acggiftart/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import logging 16 | 17 | from flask import current_app, Flask, redirect, url_for 18 | 19 | 20 | def create_app(config, debug=False, testing=False, config_overrides=None): 21 | app = Flask(__name__) 22 | app.config.from_object(config) 23 | 24 | app.debug = debug 25 | app.testing = testing 26 | 27 | if config_overrides: 28 | app.config.update(config_overrides) 29 | 30 | # Configure logging 31 | if not app.testing: 32 | logging.basicConfig(level=logging.INFO) 33 | 34 | # Setup the data model. 35 | with app.app_context(): 36 | model = get_model() 37 | model.init_app(app) 38 | 39 | # Register the ACGGiftArt CRUD blueprint. 40 | from .crud import crud 41 | app.register_blueprint(crud, url_prefix='/artworks') 42 | 43 | # Add a default root route. 44 | @app.route("/") 45 | def index(): 46 | return redirect(url_for('crud.list')) 47 | 48 | # Add an error handler. This is useful for debugging the live application, 49 | # however, you should disable the output of the exception for production 50 | # applications. 51 | @app.errorhandler(500) 52 | def server_error(e): 53 | return """ 54 | An internal error occurred:
{}
55 | See logs for full stacktrace. 56 | """.format(e), 500 57 | 58 | return app 59 | 60 | 61 | def get_model(): 62 | model_backend = current_app.config['DATA_BACKEND'] 63 | if model_backend == 'cloudsql': 64 | from . import model_cloudsql 65 | model = model_cloudsql 66 | elif model_backend == 'datastore': 67 | from . import model_datastore 68 | model = model_datastore 69 | elif model_backend == 'mongodb': 70 | from . import model_mongodb 71 | model = model_mongodb 72 | else: 73 | raise ValueError( 74 | "No appropriate databackend configured. " 75 | "Please specify datastore, cloudsql, or mongodb") 76 | 77 | return model 78 | -------------------------------------------------------------------------------- /app-engine-lab-2/acggiftart/crud.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from acggiftart import get_model, storage 16 | from flask import Blueprint, current_app, redirect, render_template, request, \ 17 | url_for 18 | 19 | 20 | crud = Blueprint('crud', __name__) 21 | 22 | 23 | # [START upload_image_file] 24 | def upload_image_file(file): 25 | """ 26 | Upload the user-uploaded file to Google Cloud Storage and retrieve its 27 | publicly-accessible URL. 28 | """ 29 | if not file: 30 | return None 31 | 32 | public_url = storage.upload_file( 33 | file.read(), 34 | file.filename, 35 | file.content_type 36 | ) 37 | 38 | current_app.logger.info( 39 | "Uploaded file %s as %s.", file.filename, public_url) 40 | 41 | return public_url 42 | # [END upload_image_file] 43 | 44 | 45 | @crud.route("/") 46 | def list(): 47 | token = request.args.get('page_token', None) 48 | if token: 49 | token = token.encode('utf-8') 50 | 51 | artworks, next_page_token = get_model().list(cursor=token) 52 | 53 | return render_template( 54 | "list.html", 55 | artworks=artworks, 56 | next_page_token=next_page_token) 57 | 58 | 59 | @crud.route('/') 60 | def view(id): 61 | artwork = get_model().read(id) 62 | return render_template("view.html", artwork=artwork) 63 | 64 | 65 | @crud.route('/add', methods=['GET', 'POST']) 66 | def add(): 67 | if request.method == 'POST': 68 | data = request.form.to_dict(flat=True) 69 | 70 | # If an image was uploaded, update the data to point to the new image. 71 | # [START image_url] 72 | image_url = upload_image_file(request.files.get('photo')) 73 | # [END image_url] 74 | 75 | # [START image_url2] 76 | if image_url: 77 | data['photoUrl'] = image_url 78 | # [END image_url2] 79 | 80 | artwork = get_model().create(data) 81 | 82 | return redirect(url_for('.view', id=artwork['id'])) 83 | 84 | return render_template("form.html", action="Add", artwork={}) 85 | 86 | 87 | @crud.route('//edit', methods=['GET', 'POST']) 88 | def edit(id): 89 | artwork = get_model().read(id) 90 | 91 | if request.method == 'POST': 92 | data = request.form.to_dict(flat=True) 93 | 94 | image_url = upload_image_file(request.files.get('photo')) 95 | 96 | if image_url: 97 | data['photoUrl'] = image_url 98 | 99 | artwork = get_model().update(data, id) 100 | 101 | return redirect(url_for('.view', id=artwork['id'])) 102 | 103 | return render_template("form.html", action="Edit", artwork=artwork) 104 | 105 | 106 | @crud.route('//delete') 107 | def delete(id): 108 | get_model().delete(id) 109 | return redirect(url_for('.list')) 110 | -------------------------------------------------------------------------------- /app-engine-lab-2/acggiftart/model_cloudsql.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from flask import Flask 16 | from flask_sqlalchemy import SQLAlchemy 17 | 18 | 19 | builtin_list = list 20 | 21 | 22 | db = SQLAlchemy() 23 | 24 | 25 | def init_app(app): 26 | # Disable track modifications, as it unnecessarily uses memory. 27 | app.config.setdefault('SQLALCHEMY_TRACK_MODIFICATIONS', False) 28 | db.init_app(app) 29 | 30 | 31 | def from_sql(row): 32 | """Translates a SQLAlchemy model instance into a dictionary""" 33 | data = row.__dict__.copy() 34 | data['id'] = row.id 35 | data.pop('_sa_instance_state') 36 | return data 37 | 38 | 39 | class Book(db.Model): 40 | __tablename__ = 'albums' 41 | 42 | id = db.Column(db.Integer, primary_key=True) 43 | title = db.Column(db.String(255)) 44 | author = db.Column(db.String(255)) 45 | publishedDate = db.Column(db.String(255)) 46 | imageUrl = db.Column(db.String(255)) 47 | description = db.Column(db.String(4096)) 48 | createdBy = db.Column(db.String(255)) 49 | createdById = db.Column(db.String(255)) 50 | 51 | def __repr__(self): 52 | return " 18 | 19 | 20 | 21 | GuruGiftArt 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 |
31 | 34 |
35 | 36 | 37 | 38 |
39 |
40 | 41 | Add an Artwork 42 | 43 |
44 |
45 |
46 |
47 |
{% block content %}{% endblock %}
48 | {{user}} 49 | 50 | 51 | -------------------------------------------------------------------------------- /app-engine-lab-2/acggiftart/templates/form.html: -------------------------------------------------------------------------------- 1 | {# 2 | # Copyright 2015 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | #} 16 | 17 | {# [START form] #} 18 | {% extends "base.html" %} 19 | 20 | {% block content %} 21 |

{{action}} artwork

22 | 23 |
24 | 25 |
26 | 27 | 28 |
29 | 30 |
31 | 32 | 33 |
34 | 35 |
36 | 37 | 38 |
39 | 40 | 44 | 45 | 46 |
47 | 48 | {% endblock %} 49 | {# [END form] #} 50 | -------------------------------------------------------------------------------- /app-engine-lab-2/acggiftart/templates/list.html: -------------------------------------------------------------------------------- 1 | {# 2 | # Copyright 2015 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | #} 16 | 17 | {% extends "base.html" %} 18 | 19 | {% block content %} 20 |
21 |
22 |

Artworks

23 | 24 | 25 | Add artwork 26 | 27 |
28 |
29 | 30 |
31 | {% for artwork in artworks %} 32 | 47 | {% else %} 48 |

No artworks found

49 | {% endfor %} 50 |
51 | 52 | {% if next_page_token %} 53 | 58 | {% endif %} 59 | 60 | {% endblock %} 61 | -------------------------------------------------------------------------------- /app-engine-lab-2/acggiftart/templates/view.html: -------------------------------------------------------------------------------- 1 | {# 2 | # Copyright 2015 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | #} 16 | 17 | {% extends "base.html" %} 18 | 19 | {% block content %} 20 | 21 |

Artwork

22 | 23 | 33 | 34 |
35 | {# [START artwork_photo] #} 36 |
37 | {% if artwork.photoUrl %} 38 | 39 | {% else %} 40 | 41 | {% endif %} 42 |
43 | {# [END artwork_photo] #} 44 |
45 |

46 | {{artwork.title}} 47 |

48 |
49 |
50 | 51 | {% endblock %} 52 | -------------------------------------------------------------------------------- /app-engine-lab-2/app.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # This file specifies your Python application's runtime configuration. 16 | # See https://cloud.google.com/appengine/docs/managed-vms/config for details. 17 | 18 | runtime: python 19 | env: flex 20 | entrypoint: gunicorn -b :$PORT main:app 21 | 22 | runtime_config: 23 | python_version: 3 24 | 25 | beta_settings: 26 | # If using Cloud SQL, uncomment and set this value to the Cloud SQL 27 | # connection name, e.g. 28 | # "project:region:cloudsql-instance" 29 | # You must also update the values in config.py. 30 | # 31 | # cloud_sql_instances: "your-cloudsql-connection-name" 32 | -------------------------------------------------------------------------------- /app-engine-lab-2/assets/generic-ACG-album.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxacademy/content-gcpro-developer/87219790d5b064a0ea4fa12281d1e5c3fc10b869/app-engine-lab-2/assets/generic-ACG-album.png -------------------------------------------------------------------------------- /app-engine-lab-2/config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """ 16 | This file contains all of the configuration values for the application. 17 | Update this file with the values for your specific Google Cloud project. 18 | You can create and manage projects at https://console.developers.google.com 19 | """ 20 | 21 | import os 22 | 23 | # The secret key is used by Flask to encrypt session cookies. 24 | SECRET_KEY = 'secret' 25 | 26 | # There are three different ways to store the data in the application. 27 | # You can choose 'datastore', 'cloudsql', or 'mongodb'. Be sure to 28 | # configure the respective settings for the one you choose below. 29 | # You do not have to configure the other data backends. If unsure, choose 30 | # 'datastore' as it does not require any additional configuration. 31 | DATA_BACKEND = 'datastore' 32 | 33 | # Google Cloud Project ID. This can be found on the 'Overview' page at 34 | # https://console.developers.google.com 35 | PROJECT_ID = '[YOUR-PROJECT-ID]' 36 | 37 | # CloudSQL & SQLAlchemy configuration 38 | # Replace the following values the respective values of your Cloud SQL 39 | # instance. 40 | CLOUDSQL_USER = 'root' 41 | CLOUDSQL_PASSWORD = 'your-cloudsql-password' 42 | CLOUDSQL_DATABASE = 'acggiftart' 43 | # Set this value to the Cloud SQL connection name, e.g. 44 | # "project:region:cloudsql-instance". 45 | # You must also update the value in app.yaml. 46 | CLOUDSQL_CONNECTION_NAME = 'your-cloudsql-connection-name' 47 | 48 | # The CloudSQL proxy is used locally to connect to the cloudsql instance. 49 | # To start the proxy, use: 50 | # 51 | # $ cloud_sql_proxy -instances=your-connection-name=tcp:3306 52 | # 53 | # Port 3306 is the standard MySQL port. If you need to use a different port, 54 | # change the 3306 to a different port number. 55 | 56 | # Alternatively, you could use a local MySQL instance for testing. 57 | LOCAL_SQLALCHEMY_DATABASE_URI = ( 58 | 'mysql+pymysql://{user}:{password}@127.0.0.1:3306/{database}').format( 59 | user=CLOUDSQL_USER, password=CLOUDSQL_PASSWORD, 60 | database=CLOUDSQL_DATABASE) 61 | 62 | # When running on App Engine a unix socket is used to connect to the cloudsql 63 | # instance. 64 | LIVE_SQLALCHEMY_DATABASE_URI = ( 65 | 'mysql+pymysql://{user}:{password}@localhost/{database}' 66 | '?unix_socket=/cloudsql/{connection_name}').format( 67 | user=CLOUDSQL_USER, password=CLOUDSQL_PASSWORD, 68 | database=CLOUDSQL_DATABASE, connection_name=CLOUDSQL_CONNECTION_NAME) 69 | 70 | if os.environ.get('GAE_INSTANCE'): 71 | SQLALCHEMY_DATABASE_URI = LIVE_SQLALCHEMY_DATABASE_URI 72 | else: 73 | SQLALCHEMY_DATABASE_URI = LOCAL_SQLALCHEMY_DATABASE_URI 74 | 75 | # Mongo configuration 76 | # If using mongolab, the connection URI is available from the mongolab control 77 | # panel. If self-hosting on compute engine, replace the values below. 78 | MONGO_URI = 'mongodb://user:password@host:27017/database' 79 | 80 | # Google Cloud Storage and upload settings. 81 | # Typically, you'll name your bucket the same as your project. To create a 82 | # bucket: 83 | # 84 | # $ gsutil mb gs:// 85 | # 86 | # You also need to make sure that the default ACL is set to public-read, 87 | # otherwise users will not be able to see their upload images: 88 | # 89 | # $ gsutil defacl set public-read gs:// 90 | # 91 | # You can adjust the max content length and allow extensions settings to allow 92 | # larger or more varied file types if desired. 93 | CLOUD_STORAGE_BUCKET = '[YOUR-BUCKET-NAME]' 94 | MAX_CONTENT_LENGTH = 8 * 1024 * 1024 95 | ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif']) 96 | -------------------------------------------------------------------------------- /app-engine-lab-2/main.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import acggiftart 16 | import config 17 | 18 | 19 | app = acggiftart.create_app(config) 20 | 21 | 22 | # This is only used when running locally. When running live, gunicorn runs 23 | # the application. 24 | if __name__ == '__main__': 25 | app.run(host='127.0.0.1', port=8080, debug=True) 26 | -------------------------------------------------------------------------------- /app-engine-lab-2/requirements-dev.txt: -------------------------------------------------------------------------------- 1 | tox==2.9.1 2 | flake8==3.5.0 3 | flaky==3.4.0 4 | pytest==3.3.2 5 | pytest-cov==2.5.1 6 | retrying==1.3.3 7 | -------------------------------------------------------------------------------- /app-engine-lab-2/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask>=2.0.2 2 | google-cloud-datastore==2.3.0 3 | google-cloud-storage==1.42.3 4 | gunicorn==20.1.0 5 | oauth2client==4.1.3 6 | Flask-SQLAlchemy==2.5.1 7 | PyMySQL==1.0.2 8 | Flask-PyMongo==2.3.0 9 | PyMongo==3.12.1 10 | six==1.16.0 11 | -------------------------------------------------------------------------------- /app-engine-lab/app.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # This file specifies your Python application's runtime configuration. 16 | # See https://cloud.google.com/appengine/docs/managed-vms/config for details. 17 | 18 | runtime: python 19 | env: flex 20 | entrypoint: gunicorn -b :$PORT main:app 21 | 22 | runtime_config: 23 | python_version: 3 24 | 25 | beta_settings: 26 | # If using Cloud SQL, uncomment and set this value to the Cloud SQL 27 | # connection name, e.g. 28 | # "project:region:cloudsql-instance" 29 | # You must also update the values in config.py. 30 | # 31 | # cloud_sql_instances: "your-cloudsql-connection-name" 32 | -------------------------------------------------------------------------------- /app-engine-lab/assets/LaGiftArt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxacademy/content-gcpro-developer/87219790d5b064a0ea4fa12281d1e5c3fc10b869/app-engine-lab/assets/LaGiftArt.png -------------------------------------------------------------------------------- /app-engine-lab/assets/albums/Grace-Jones-Island-Life-album-cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxacademy/content-gcpro-developer/87219790d5b064a0ea4fa12281d1e5c3fc10b869/app-engine-lab/assets/albums/Grace-Jones-Island-Life-album-cover.jpg -------------------------------------------------------------------------------- /app-engine-lab/assets/albums/The-Beatles-Sgt-Peppers-Lonely-Hearts-Club-Band-Album-Cover-530.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxacademy/content-gcpro-developer/87219790d5b064a0ea4fa12281d1e5c3fc10b869/app-engine-lab/assets/albums/The-Beatles-Sgt-Peppers-Lonely-Hearts-Club-Band-Album-Cover-530.jpg -------------------------------------------------------------------------------- /app-engine-lab/assets/albums/aladdin-sane-david-bowie-768x768.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxacademy/content-gcpro-developer/87219790d5b064a0ea4fa12281d1e5c3fc10b869/app-engine-lab/assets/albums/aladdin-sane-david-bowie-768x768.jpg -------------------------------------------------------------------------------- /app-engine-lab/assets/albums/apollo-18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxacademy/content-gcpro-developer/87219790d5b064a0ea4fa12281d1e5c3fc10b869/app-engine-lab/assets/albums/apollo-18.jpg -------------------------------------------------------------------------------- /app-engine-lab/assets/albums/houses-of-the-holy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxacademy/content-gcpro-developer/87219790d5b064a0ea4fa12281d1e5c3fc10b869/app-engine-lab/assets/albums/houses-of-the-holy.jpg -------------------------------------------------------------------------------- /app-engine-lab/assets/generic-LA-album.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxacademy/content-gcpro-developer/87219790d5b064a0ea4fa12281d1e5c3fc10b869/app-engine-lab/assets/generic-LA-album.png -------------------------------------------------------------------------------- /app-engine-lab/config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """ 16 | This file contains all of the configuration values for the application. 17 | Update this file with the values for your specific Google Cloud project. 18 | You can create and manage projects at https://console.developers.google.com 19 | """ 20 | 21 | import os 22 | 23 | # The secret key is used by Flask to encrypt session cookies. 24 | SECRET_KEY = 'secret' 25 | 26 | # There are three different ways to store the data in the application. 27 | # You can choose 'datastore', 'cloudsql', or 'mongodb'. Be sure to 28 | # configure the respective settings for the one you choose below. 29 | # You do not have to configure the other data backends. If unsure, choose 30 | # 'datastore' as it does not require any additional configuration. 31 | DATA_BACKEND = 'datastore' 32 | 33 | # Google Cloud Project ID. This can be found on the 'Overview' page at 34 | # https://console.developers.google.com 35 | PROJECT_ID = '[YOUR-PROJECT-ID]' 36 | 37 | # CloudSQL & SQLAlchemy configuration 38 | # Replace the following values the respective values of your Cloud SQL 39 | # instance. 40 | CLOUDSQL_USER = 'root' 41 | CLOUDSQL_PASSWORD = 'your-cloudsql-password' 42 | CLOUDSQL_DATABASE = 'lagiftart' 43 | # Set this value to the Cloud SQL connection name, e.g. 44 | # "project:region:cloudsql-instance". 45 | # You must also update the value in app.yaml. 46 | CLOUDSQL_CONNECTION_NAME = 'your-cloudsql-connection-name' 47 | 48 | # The CloudSQL proxy is used locally to connect to the cloudsql instance. 49 | # To start the proxy, use: 50 | # 51 | # $ cloud_sql_proxy -instances=your-connection-name=tcp:3306 52 | # 53 | # Port 3306 is the standard MySQL port. If you need to use a different port, 54 | # change the 3306 to a different port number. 55 | 56 | # Alternatively, you could use a local MySQL instance for testing. 57 | LOCAL_SQLALCHEMY_DATABASE_URI = ( 58 | 'mysql+pymysql://{user}:{password}@127.0.0.1:3306/{database}').format( 59 | user=CLOUDSQL_USER, password=CLOUDSQL_PASSWORD, 60 | database=CLOUDSQL_DATABASE) 61 | 62 | # When running on App Engine a unix socket is used to connect to the cloudsql 63 | # instance. 64 | LIVE_SQLALCHEMY_DATABASE_URI = ( 65 | 'mysql+pymysql://{user}:{password}@localhost/{database}' 66 | '?unix_socket=/cloudsql/{connection_name}').format( 67 | user=CLOUDSQL_USER, password=CLOUDSQL_PASSWORD, 68 | database=CLOUDSQL_DATABASE, connection_name=CLOUDSQL_CONNECTION_NAME) 69 | 70 | if os.environ.get('GAE_INSTANCE'): 71 | SQLALCHEMY_DATABASE_URI = LIVE_SQLALCHEMY_DATABASE_URI 72 | else: 73 | SQLALCHEMY_DATABASE_URI = LOCAL_SQLALCHEMY_DATABASE_URI 74 | 75 | # Mongo configuration 76 | # If using mongolab, the connection URI is available from the mongolab control 77 | # panel. If self-hosting on compute engine, replace the values below. 78 | MONGO_URI = 'mongodb://user:password@host:27017/database' 79 | 80 | # Google Cloud Storage and upload settings. 81 | # Typically, you'll name your bucket the same as your project. To create a 82 | # bucket: 83 | # 84 | # $ gsutil mb gs:// 85 | # 86 | # You also need to make sure that the default ACL is set to public-read, 87 | # otherwise users will not be able to see their upload images: 88 | # 89 | # $ gsutil defacl set public-read gs:// 90 | # 91 | # You can adjust the max content length and allow extensions settings to allow 92 | # larger or more varied file types if desired. 93 | CLOUD_STORAGE_BUCKET = '[YOUR-BUCKET-NAME]' 94 | MAX_CONTENT_LENGTH = 8 * 1024 * 1024 95 | ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif']) 96 | -------------------------------------------------------------------------------- /app-engine-lab/lagiftart/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import logging 16 | 17 | from flask import current_app, Flask, redirect, url_for 18 | 19 | 20 | def create_app(config, debug=False, testing=False, config_overrides=None): 21 | app = Flask(__name__) 22 | app.config.from_object(config) 23 | 24 | app.debug = debug 25 | app.testing = testing 26 | 27 | if config_overrides: 28 | app.config.update(config_overrides) 29 | 30 | # Configure logging 31 | if not app.testing: 32 | logging.basicConfig(level=logging.INFO) 33 | 34 | # Setup the data model. 35 | with app.app_context(): 36 | model = get_model() 37 | model.init_app(app) 38 | 39 | # Register the LaGiftArt CRUD blueprint. 40 | from .crud import crud 41 | app.register_blueprint(crud, url_prefix='/artworks') 42 | 43 | # Add a default root route. 44 | @app.route("/") 45 | def index(): 46 | return redirect(url_for('crud.list')) 47 | 48 | # Add an error handler. This is useful for debugging the live application, 49 | # however, you should disable the output of the exception for production 50 | # applications. 51 | @app.errorhandler(500) 52 | def server_error(e): 53 | return """ 54 | An internal error occurred:
{}
55 | See logs for full stacktrace. 56 | """.format(e), 500 57 | 58 | return app 59 | 60 | 61 | def get_model(): 62 | model_backend = current_app.config['DATA_BACKEND'] 63 | if model_backend == 'cloudsql': 64 | from . import model_cloudsql 65 | model = model_cloudsql 66 | elif model_backend == 'datastore': 67 | from . import model_datastore 68 | model = model_datastore 69 | elif model_backend == 'mongodb': 70 | from . import model_mongodb 71 | model = model_mongodb 72 | else: 73 | raise ValueError( 74 | "No appropriate databackend configured. " 75 | "Please specify datastore, cloudsql, or mongodb") 76 | 77 | return model 78 | -------------------------------------------------------------------------------- /app-engine-lab/lagiftart/crud.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from lagiftart import get_model, storage 16 | from flask import Blueprint, current_app, redirect, render_template, request, \ 17 | url_for 18 | 19 | 20 | crud = Blueprint('crud', __name__) 21 | 22 | 23 | # [START upload_image_file] 24 | def upload_image_file(file): 25 | """ 26 | Upload the user-uploaded file to Google Cloud Storage and retrieve its 27 | publicly-accessible URL. 28 | """ 29 | if not file: 30 | return None 31 | 32 | public_url = storage.upload_file( 33 | file.read(), 34 | file.filename, 35 | file.content_type 36 | ) 37 | 38 | current_app.logger.info( 39 | "Uploaded file %s as %s.", file.filename, public_url) 40 | 41 | return public_url 42 | # [END upload_image_file] 43 | 44 | 45 | @crud.route("/") 46 | def list(): 47 | token = request.args.get('page_token', None) 48 | if token: 49 | token = token.encode('utf-8') 50 | 51 | artworks, next_page_token = get_model().list(cursor=token) 52 | 53 | return render_template( 54 | "list.html", 55 | artworks=artworks, 56 | next_page_token=next_page_token) 57 | 58 | 59 | @crud.route('/') 60 | def view(id): 61 | artwork = get_model().read(id) 62 | return render_template("view.html", artwork=artwork) 63 | 64 | 65 | @crud.route('/add', methods=['GET', 'POST']) 66 | def add(): 67 | if request.method == 'POST': 68 | data = request.form.to_dict(flat=True) 69 | 70 | # If an image was uploaded, update the data to point to the new image. 71 | # [START image_url] 72 | image_url = upload_image_file(request.files.get('photo')) 73 | # [END image_url] 74 | 75 | # [START image_url2] 76 | if image_url: 77 | data['photoUrl'] = image_url 78 | # [END image_url2] 79 | 80 | artwork = get_model().create(data) 81 | 82 | return redirect(url_for('.view', id=artwork['id'])) 83 | 84 | return render_template("form.html", action="Add", artwork={}) 85 | 86 | 87 | @crud.route('//edit', methods=['GET', 'POST']) 88 | def edit(id): 89 | artwork = get_model().read(id) 90 | 91 | if request.method == 'POST': 92 | data = request.form.to_dict(flat=True) 93 | 94 | image_url = upload_image_file(request.files.get('photo')) 95 | 96 | if image_url: 97 | data['photoUrl'] = image_url 98 | 99 | artwork = get_model().update(data, id) 100 | 101 | return redirect(url_for('.view', id=artwork['id'])) 102 | 103 | return render_template("form.html", action="Edit", artwork=artwork) 104 | 105 | 106 | @crud.route('//delete') 107 | def delete(id): 108 | get_model().delete(id) 109 | return redirect(url_for('.list')) 110 | -------------------------------------------------------------------------------- /app-engine-lab/lagiftart/model_cloudsql.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from flask import Flask 16 | from flask_sqlalchemy import SQLAlchemy 17 | 18 | 19 | builtin_list = list 20 | 21 | 22 | db = SQLAlchemy() 23 | 24 | 25 | def init_app(app): 26 | # Disable track modifications, as it unnecessarily uses memory. 27 | app.config.setdefault('SQLALCHEMY_TRACK_MODIFICATIONS', False) 28 | db.init_app(app) 29 | 30 | 31 | def from_sql(row): 32 | """Translates a SQLAlchemy model instance into a dictionary""" 33 | data = row.__dict__.copy() 34 | data['id'] = row.id 35 | data.pop('_sa_instance_state') 36 | return data 37 | 38 | 39 | class Book(db.Model): 40 | __tablename__ = 'albums' 41 | 42 | id = db.Column(db.Integer, primary_key=True) 43 | title = db.Column(db.String(255)) 44 | author = db.Column(db.String(255)) 45 | publishedDate = db.Column(db.String(255)) 46 | imageUrl = db.Column(db.String(255)) 47 | description = db.Column(db.String(4096)) 48 | createdBy = db.Column(db.String(255)) 49 | createdById = db.Column(db.String(255)) 50 | 51 | def __repr__(self): 52 | return " 17 | 18 | 19 | LaGiftArt 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 |
29 | 32 |
33 | 34 | 35 | 36 |
37 |
38 | 39 | Add an Artwork 40 | 41 |
42 |
43 |
44 |
45 |
{% block content %}{% endblock %}
46 | {{user}} 47 | 48 | 49 | -------------------------------------------------------------------------------- /app-engine-lab/lagiftart/templates/form.html: -------------------------------------------------------------------------------- 1 | {# 2 | # Copyright 2015 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | #} 16 | 17 | {# [START form] #} 18 | {% extends "base.html" %} 19 | 20 | {% block content %} 21 |

{{action}} artwork

22 | 23 |
24 | 25 |
26 | 27 | 28 |
29 | 30 |
31 | 32 | 33 |
34 | 35 |
36 | 37 | 38 |
39 | 40 | 44 | 45 | 46 |
47 | 48 | {% endblock %} 49 | {# [END form] #} 50 | -------------------------------------------------------------------------------- /app-engine-lab/lagiftart/templates/list.html: -------------------------------------------------------------------------------- 1 | {# 2 | # Copyright 2015 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | #} 16 | 17 | {% extends "base.html" %} 18 | 19 | {% block content %} 20 |
21 |
22 |

Artworks

23 | 24 | 25 | Add artwork 26 | 27 |
28 |
29 | 30 |
31 | {% for artwork in artworks %} 32 | 47 | {% else %} 48 |

No artworks found

49 | {% endfor %} 50 |
51 | 52 | {% if next_page_token %} 53 | 58 | {% endif %} 59 | 60 | {% endblock %} 61 | -------------------------------------------------------------------------------- /app-engine-lab/lagiftart/templates/view.html: -------------------------------------------------------------------------------- 1 | {# 2 | # Copyright 2015 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | #} 16 | 17 | {% extends "base.html" %} 18 | 19 | {% block content %} 20 | 21 |

Artwork

22 | 23 | 33 | 34 |
35 | {# [START artwork_photo] #} 36 |
37 | {% if artwork.photoUrl %} 38 | 39 | {% else %} 40 | 41 | {% endif %} 42 |
43 | {# [END artwork_photo] #} 44 |
45 |

46 | {{artwork.title}} 47 |

48 |
49 |
50 | 51 | {% endblock %} 52 | -------------------------------------------------------------------------------- /app-engine-lab/main.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import lagiftart 16 | import config 17 | 18 | 19 | app = lagiftart.create_app(config) 20 | 21 | 22 | # This is only used when running locally. When running live, gunicorn runs 23 | # the application. 24 | if __name__ == '__main__': 25 | app.run(host='127.0.0.1', port=8080, debug=True) 26 | -------------------------------------------------------------------------------- /app-engine-lab/requirements-dev.txt: -------------------------------------------------------------------------------- 1 | tox==2.9.1 2 | flake8==3.5.0 3 | flaky==3.4.0 4 | pytest==3.3.2 5 | pytest-cov==2.5.1 6 | retrying==1.3.3 7 | -------------------------------------------------------------------------------- /app-engine-lab/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask>=1.0.0 2 | google-cloud-datastore==1.4.0 3 | google-cloud-storage==1.7.0 4 | gunicorn==19.7.1 5 | oauth2client==4.1.2 6 | Flask-SQLAlchemy==2.3.2 7 | PyMySQL==0.8.0 8 | Flask-PyMongo==0.5.1 9 | PyMongo==3.6.0 10 | six==1.11.0 11 | -------------------------------------------------------------------------------- /cicd-lab/README.md: -------------------------------------------------------------------------------- 1 | # cloud-functions 2 | -------------------------------------------------------------------------------- /cicd-lab/cloudbuild.yaml: -------------------------------------------------------------------------------- 1 | steps: 2 | - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' 3 | args: 4 | - gcloud 5 | - functions 6 | - deploy 7 | - repo-function-1 8 | - --region=us-central1 9 | - --source=. 10 | - --trigger-http 11 | -------------------------------------------------------------------------------- /cicd-lab/main.py: -------------------------------------------------------------------------------- 1 | from flask import escape 2 | 3 | def greetings_http(request): 4 | request_json = request.get_json(silent=True) 5 | request_args = request.args 6 | if request_json and 'name' in request_json: 7 | name = request_json['name'] 8 | elif request_args and 'name' in request_args: 9 | name = request_args['name'] 10 | else: 11 | name = 'my friend' 12 | return '

Greetings from the Cloud, {}!

Via Source Control Repo and Cloud Build

'.format(escape(name)) 13 | -------------------------------------------------------------------------------- /cicd-lab/requirements.txt: -------------------------------------------------------------------------------- 1 | google-cloud-error-reporting==0.30.0 2 | -------------------------------------------------------------------------------- /cloud-functions-lab/README.md: -------------------------------------------------------------------------------- 1 | # cloud-functions 2 | -------------------------------------------------------------------------------- /cloud-functions-lab/main.py: -------------------------------------------------------------------------------- 1 | from flask import escape 2 | 3 | def greetings_http(request): 4 | request_json = request.get_json(silent=True) 5 | request_args = request.args 6 | if request_json and 'name' in request_json: 7 | name = request_json['name'] 8 | elif request_args and 'name' in request_args: 9 | name = request_args['name'] 10 | else: 11 | name = 'my friend' 12 | return '

Greetings from Linux Academy, {}!

Via Source Control Repo

'.format(escape(name)) 13 | -------------------------------------------------------------------------------- /cloud-functions-lab/requirements.txt: -------------------------------------------------------------------------------- 1 | google-cloud-error-reporting==0.30.0 2 | -------------------------------------------------------------------------------- /kubernetes-engine-lab/app.py: -------------------------------------------------------------------------------- 1 | # The Docker image contains the following code 2 | from flask import Flask 3 | import os 4 | import socket 5 | 6 | app = Flask(__name__) 7 | 8 | @app.route("/") 9 | def hello(): 10 | html = "

Greetings from Linux Academy!

" 11 | return html 12 | 13 | if __name__ == "__main__": 14 | app.run(host='0.0.0.0', port=80) -------------------------------------------------------------------------------- /kubernetes-engine-lab/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | deployment.kubernetes.io/revision: "1" 6 | creationTimestamp: 2018-08-20T19:49:31Z 7 | generation: 2 8 | labels: 9 | app: nginx-1 10 | name: nginx-1 11 | namespace: default 12 | resourceVersion: "904" 13 | selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/nginx-1 14 | uid: 2805a653-a4b2-11e8-a16d-42010a960fc7 15 | spec: 16 | replicas: 1 17 | selector: 18 | matchLabels: 19 | app: nginx-1 20 | strategy: 21 | rollingUpdate: 22 | maxSurge: 1 23 | maxUnavailable: 1 24 | type: RollingUpdate 25 | template: 26 | metadata: 27 | creationTimestamp: null 28 | labels: 29 | app: nginx-1 30 | spec: 31 | containers: 32 | - image: gcr.io/[PROJECT_ID]/la-container-image:v1 33 | imagePullPolicy: IfNotPresent 34 | name: la-container-image 35 | resources: {} 36 | terminationMessagePath: /dev/termination-log 37 | terminationMessagePolicy: File 38 | dnsPolicy: ClusterFirst 39 | restartPolicy: Always 40 | schedulerName: default-scheduler 41 | securityContext: {} 42 | terminationGracePeriodSeconds: 30 43 | status: 44 | availableReplicas: 1 45 | conditions: 46 | - lastTransitionTime: 2018-08-20T19:49:38Z 47 | lastUpdateTime: 2018-08-20T19:49:38Z 48 | message: Deployment has minimum availability. 49 | reason: MinimumReplicasAvailable 50 | status: "True" 51 | type: Available 52 | observedGeneration: 2 53 | readyReplicas: 1 54 | replicas: 1 55 | updatedReplicas: 1 56 | -------------------------------------------------------------------------------- /kubernetes-engine-lab/dockerfile: -------------------------------------------------------------------------------- 1 | # The Dockerfile defines the image's environment 2 | # Import Python runtime and set up working directory 3 | FROM python:2.7-slim 4 | WORKDIR /app 5 | ADD . /app 6 | 7 | # Install any necessary dependencies 8 | RUN pip install -r requirements.txt 9 | 10 | # Open port 80 for serving the webpage 11 | EXPOSE 80 12 | 13 | # Run app.py when the container launches 14 | CMD ["python", "app.py"] 15 | -------------------------------------------------------------------------------- /kubernetes-engine-lab/requirements.txt: -------------------------------------------------------------------------------- 1 | # This file defines the image's dependencies 2 | Flask 3 | -------------------------------------------------------------------------------- /sql-lab/MetObjects_Table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS MetObjects ( 2 | `Object_Number` VARCHAR(50) CHARACTER SET utf8, 3 | `Is_Highlight` VARCHAR(5) CHARACTER SET utf8, 4 | `Is_Public_Domain` VARCHAR(5) CHARACTER SET utf8, 5 | `Object_ID` INT, 6 | `Department` VARCHAR(41) CHARACTER SET utf8, 7 | `Object_Name` VARCHAR(80) CHARACTER SET utf8, 8 | `Title` VARCHAR(837) CHARACTER SET utf8, 9 | `Culture` VARCHAR(98) CHARACTER SET utf8, 10 | `Period` VARCHAR(70) CHARACTER SET utf8, 11 | `Dynasty` VARCHAR(45) CHARACTER SET utf8, 12 | `Reign` VARCHAR(55) CHARACTER SET utf8, 13 | `Portfolio` VARCHAR(835) CHARACTER SET utf8, 14 | `Artist_Role` VARCHAR(1249) CHARACTER SET utf8, 15 | `Artist_Prefix` VARCHAR(1239) CHARACTER SET utf8, 16 | `Artist_Display_Name` VARCHAR(3574) CHARACTER SET utf8, 17 | `Artist_Display_Bio` TEXT CHARACTER SET utf8, 18 | `Artist_Suffix` VARCHAR(1281) CHARACTER SET utf8, 19 | `Artist_Alpha_Sort` TEXT CHARACTER SET utf8, 20 | `Artist_Nationality` VARCHAR(1445) CHARACTER SET utf8, 21 | `Artist_Begin_Date` VARCHAR(1935) CHARACTER SET utf8, 22 | `Artist_End_Date` VARCHAR(1935) CHARACTER SET utf8, 23 | `Object_Date` VARCHAR(239) CHARACTER SET utf8, 24 | `Object_Begin_Date` INT, 25 | `Object_End_Date` INT, 26 | `Medium` TEXT CHARACTER SET utf8, 27 | `Dimensions` VARCHAR(2172) CHARACTER SET utf8, 28 | `Credit_Line` VARCHAR(1142) CHARACTER SET utf8, 29 | `Geography_Type` VARCHAR(72) CHARACTER SET utf8, 30 | `City` VARCHAR(62) CHARACTER SET utf8, 31 | `State` VARCHAR(33) CHARACTER SET utf8, 32 | `County` VARCHAR(49) CHARACTER SET utf8, 33 | `Country` VARCHAR(75) CHARACTER SET utf8, 34 | `Region` VARCHAR(64) CHARACTER SET utf8, 35 | `Subregion` VARCHAR(50) CHARACTER SET utf8, 36 | `Locale` VARCHAR(83) CHARACTER SET utf8, 37 | `Locus` VARCHAR(81) CHARACTER SET utf8, 38 | `Excavation` VARCHAR(100) CHARACTER SET utf8, 39 | `River` VARCHAR(42) CHARACTER SET utf8, 40 | `Classification` VARCHAR(74) CHARACTER SET utf8, 41 | `Rights_and_Reproduction` VARCHAR(223) CHARACTER SET utf8, 42 | `Link_Resource` VARCHAR(53) CHARACTER SET utf8, 43 | `Metadata_Date` DATETIME, 44 | `Repository` VARCHAR(40) CHARACTER SET utf8 45 | ); 46 | --------------------------------------------------------------------------------