├── .gitignore ├── .openshift_template ├── Readme.md ├── jboss_templates.json ├── python.template ├── template.json └── tomcat_templates.json ├── Arch.png ├── README.md ├── installscripts ├── 1.setVariable.sh ├── 2.deployEmailSvc-PythonMySQL.sh ├── 3.deployTwitter-Tomcat.sh ├── 4.deployUserRegBackend-NodejsMongo.sh ├── 5.deployFrontend-PHP.sh ├── readme.md └── x.cleanup ├── java-twitter-feed-api ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── example │ │ ├── MyResource.java │ │ └── User.java │ └── webapp │ ├── WEB-INF │ └── web.xml │ └── index.jsp ├── nodejs-mongodb-template.json ├── nodejs-users-api ├── app │ └── models │ │ └── user.js ├── config.js ├── package.json ├── server.js └── test.js ├── php-ui ├── friends.php ├── hack.php ├── head.php ├── index.php ├── login.php ├── profile.php ├── register.php ├── script.js ├── style.css └── tweets.php └── python-email-api ├── .sti └── environment ├── requirements.txt ├── sample.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | node_modules/ 3 | java-twitter-feed-api/target/ 4 | installscripts/0.sh 5 | -------------------------------------------------------------------------------- /.openshift_template/Readme.md: -------------------------------------------------------------------------------- 1 | https://raw.githubusercontent.com/jboss-openshift/application-templates/master/jboss-image-streams.json 2 | -------------------------------------------------------------------------------- /.openshift_template/jboss_templates.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "List", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "name": "jboss-image-streams", 6 | "annotations": { 7 | "description": "ImageStream definitions for JBoss Middleware products." 8 | } 9 | }, 10 | "items": [ 11 | { 12 | "kind": "ImageStream", 13 | "apiVersion": "v1", 14 | "metadata": { 15 | "name": "jboss-webserver30-tomcat7-openshift" 16 | }, 17 | "spec": { 18 | "dockerImageRepository": "registry.access.redhat.com/jboss-webserver-3/webserver30-tomcat7-openshift", 19 | "tags": [ 20 | { 21 | "name": "1.1", 22 | "annotations": { 23 | "description": "JBoss Web Server 3.0 Tomcat 7 S2I images.", 24 | "iconClass": "icon-jboss", 25 | "tags": "builder,tomcat,tomcat7,java,jboss,xpaas", 26 | "supports":"tomcat7:3.0,tomcat:7,java:8,xpaas:1.1", 27 | "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts.git", 28 | "sampleContextDir": "tomcat-websocket-chat", 29 | "version": "1.1" 30 | } 31 | }, 32 | { 33 | "name": "1.2", 34 | "annotations": { 35 | "description": "JBoss Web Server 3.0 Tomcat 7 S2I images.", 36 | "iconClass": "icon-jboss", 37 | "tags": "builder,tomcat,tomcat7,java,jboss,xpaas", 38 | "supports":"tomcat7:3.0,tomcat:7,java:8,xpaas:1.2", 39 | "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts.git", 40 | "sampleContextDir": "tomcat-websocket-chat", 41 | "version": "1.2" 42 | } 43 | } 44 | ] 45 | } 46 | }, 47 | { 48 | "kind": "ImageStream", 49 | "apiVersion": "v1", 50 | "metadata": { 51 | "name": "jboss-webserver30-tomcat8-openshift" 52 | }, 53 | "spec": { 54 | "dockerImageRepository": "registry.access.redhat.com/jboss-webserver-3/webserver30-tomcat8-openshift", 55 | "tags": [ 56 | { 57 | "name": "1.1", 58 | "annotations": { 59 | "description": "JBoss Web Server 3.0 Tomcat 8 S2I images.", 60 | "iconClass": "icon-jboss", 61 | "tags": "builder,tomcat,tomcat8,java,jboss,xpaas", 62 | "supports":"tomcat8:3.0,tomcat:8,java:8,xpaas:1.1", 63 | "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts.git", 64 | "sampleContextDir": "tomcat-websocket-chat", 65 | "version": "1.1" 66 | } 67 | }, 68 | { 69 | "name": "1.2", 70 | "annotations": { 71 | "description": "JBoss Web Server 3.0 Tomcat 8 S2I images.", 72 | "iconClass": "icon-jboss", 73 | "tags": "builder,tomcat,tomcat8,java,jboss,xpaas", 74 | "supports":"tomcat8:3.0,tomcat:8,java:8,xpaas:1.2", 75 | "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts.git", 76 | "sampleContextDir": "tomcat-websocket-chat", 77 | "version": "1.2" 78 | } 79 | } 80 | ] 81 | } 82 | }, 83 | { 84 | "kind": "ImageStream", 85 | "apiVersion": "v1", 86 | "metadata": { 87 | "name": "jboss-eap64-openshift" 88 | }, 89 | "spec": { 90 | "dockerImageRepository": "registry.access.redhat.com/jboss-eap-6/eap64-openshift", 91 | "tags": [ 92 | { 93 | "name": "1.1", 94 | "annotations": { 95 | "description": "JBoss EAP 6.4 S2I images.", 96 | "iconClass": "icon-jboss", 97 | "tags": "builder,eap,javaee,java,jboss,xpaas", 98 | "supports":"eap:6.4,javaee:6,java:8,xpaas:1.1", 99 | "sampleRepo": "https://github.com/jboss-developer/jboss-eap-quickstarts.git", 100 | "sampleContextDir": "kitchensink", 101 | "sampleRef": "6.4.x", 102 | "version": "1.1" 103 | } 104 | }, 105 | { 106 | "name": "1.2", 107 | "annotations": { 108 | "description": "JBoss EAP 6.4 S2I images.", 109 | "iconClass": "icon-jboss", 110 | "tags": "builder,eap,javaee,java,jboss,xpaas", 111 | "supports":"eap:6.4,javaee:6,java:8,xpaas:1.2", 112 | "sampleRepo": "https://github.com/jboss-developer/jboss-eap-quickstarts.git", 113 | "sampleContextDir": "kitchensink", 114 | "sampleRef": "6.4.x", 115 | "version": "1.2" 116 | } 117 | }, 118 | { 119 | "name": "1.3", 120 | "annotations": { 121 | "description": "JBoss EAP 6.4 S2I images.", 122 | "iconClass": "icon-jboss", 123 | "tags": "builder,eap,javaee,java,jboss,xpaas", 124 | "supports":"eap:6.4,javaee:6,java:8,xpaas:1.3", 125 | "sampleRepo": "https://github.com/jboss-developer/jboss-eap-quickstarts.git", 126 | "sampleContextDir": "kitchensink", 127 | "sampleRef": "6.4.x", 128 | "version": "1.3" 129 | } 130 | } 131 | ] 132 | } 133 | }, 134 | { 135 | "kind": "ImageStream", 136 | "apiVersion": "v1", 137 | "metadata": { 138 | "name": "jboss-eap70-openshift" 139 | }, 140 | "spec": { 141 | "dockerImageRepository": "registry.access.redhat.com/jboss-eap-7/eap70-openshift", 142 | "tags": [ 143 | { 144 | "name": "1.3", 145 | "annotations": { 146 | "description": "JBoss EAP 7.0 S2I images.", 147 | "iconClass": "icon-jboss", 148 | "tags": "builder,eap,javaee,java,jboss,xpaas", 149 | "supports":"eap:7.0,javaee:7,java:8,xpaas:1.3", 150 | "sampleRepo": "https://github.com/jboss-developer/jboss-eap-quickstarts.git", 151 | "sampleContextDir": "kitchensink", 152 | "sampleRef": "7.0.x", 153 | "version": "1.3" 154 | } 155 | } 156 | ] 157 | } 158 | }, 159 | { 160 | "kind": "ImageStream", 161 | "apiVersion": "v1", 162 | "metadata": { 163 | "name": "jboss-decisionserver62-openshift" 164 | }, 165 | "spec": { 166 | "dockerImageRepository": "registry.access.redhat.com/jboss-decisionserver-6/decisionserver62-openshift", 167 | "tags": [ 168 | { 169 | "name": "1.2", 170 | "annotations": { 171 | "description": "Decision Server 6.2 S2I images.", 172 | "iconClass": "icon-jboss", 173 | "tags": "builder,decisionserver,java,xpaas", 174 | "supports":"decisionserver:6.2,java:8,xpaas:1.2", 175 | "sampleRepo": "https://github.com/jboss-openshift/openshift-quickstarts.git", 176 | "sampleContextDir": "decisionserver/hellorules", 177 | "sampleRef": "1.2", 178 | "version": "1.2" 179 | } 180 | } 181 | ] 182 | } 183 | }, 184 | { 185 | "kind": "ImageStream", 186 | "apiVersion": "v1", 187 | "metadata": { 188 | "name": "jboss-datagrid65-openshift" 189 | }, 190 | "spec": { 191 | "dockerImageRepository": "registry.access.redhat.com/jboss-datagrid-6/datagrid65-openshift", 192 | "tags": [ 193 | { 194 | "name": "1.2", 195 | "annotations": { 196 | "description": "JBoss Data Grid 6.5 S2I images.", 197 | "iconClass": "icon-jboss", 198 | "tags": "datagrid,java,jboss,xpaas", 199 | "supports":"datagrid:6.5,java:8,xpaas:1.2", 200 | "version": "1.2" 201 | } 202 | } 203 | ] 204 | } 205 | }, 206 | { 207 | "kind": "ImageStream", 208 | "apiVersion": "v1", 209 | "metadata": { 210 | "name": "jboss-amq-62" 211 | }, 212 | "spec": { 213 | "dockerImageRepository": "registry.access.redhat.com/jboss-amq-6/amq62-openshift", 214 | "tags": [ 215 | { 216 | "name": "1.1", 217 | "annotations": { 218 | "description": "JBoss A-MQ 6.2 broker image.", 219 | "iconClass": "icon-jboss", 220 | "tags": "messaging,amq,jboss,xpaas", 221 | "supports":"amq:6.2,messaging,xpaas:1.1", 222 | "version": "1.1" 223 | } 224 | }, 225 | { 226 | "name": "1.2", 227 | "annotations": { 228 | "description": "JBoss A-MQ 6.2 broker image.", 229 | "iconClass": "icon-jboss", 230 | "tags": "messaging,amq,jboss,xpaas", 231 | "supports":"amq:6.2,messaging,xpaas:1.2", 232 | "version": "1.2" 233 | } 234 | } 235 | ] 236 | } 237 | }, 238 | { 239 | "kind": "ImageStream", 240 | "apiVersion": "v1", 241 | "metadata": { 242 | "name": "redhat-sso70-openshift", 243 | "annotations": { 244 | "description": "Red Hat SSO 7.0" 245 | } 246 | }, 247 | "spec": { 248 | "dockerImageRepository": "registry.access.redhat.com/redhat-sso-7/sso70-openshift", 249 | "tags": [ 250 | { 251 | "name": "1.3", 252 | "annotations": { 253 | "description": "Red Hat SSO 7.0", 254 | "iconClass": "icon-jboss", 255 | "tags": "sso,keycloak,redhat", 256 | "supports":"sso:7.0,xpaas:1.3", 257 | "version": "1.3" 258 | } 259 | } 260 | ] 261 | } 262 | } 263 | ] 264 | } 265 | -------------------------------------------------------------------------------- /.openshift_template/python.template: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "Template", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "name": "python-email-api", 6 | "annotations": { 7 | "description": "An example Node.js application with a MongoDB database", 8 | "tags": "quickstart,nodejs,mongodb", 9 | "iconClass": "icon-nodejs" 10 | } 11 | }, 12 | "labels": { 13 | "template": "python-email-api" 14 | }, 15 | "objects": [{ 16 | "kind": "Service", 17 | "apiVersion": "v1", 18 | "metadata": { 19 | "name": "python-email-api", 20 | "annotations": { 21 | "description": "Exposes and load balances the application pods" 22 | } 23 | }, 24 | "spec": { 25 | "ports": [{ 26 | "name": "web", 27 | "port": 8080, 28 | "targetPort": 8080 29 | }], 30 | "selector": { 31 | "name": "python-email-api" 32 | } 33 | } 34 | }, { 35 | "kind": "Route", 36 | "apiVersion": "v1", 37 | "metadata": { 38 | "name": "python-email-api" 39 | }, 40 | "spec": { 41 | "host": "${PYTHON_APPLICATION_DOMAIN}", 42 | "to": { 43 | "kind": "Service", 44 | "name": "python-email-api" 45 | } 46 | } 47 | }, { 48 | "kind": "ImageStream", 49 | "apiVersion": "v1", 50 | "metadata": { 51 | "name": "python-email-api", 52 | "annotations": { 53 | "description": "Keeps track of changes in the application image" 54 | } 55 | }, 56 | "spec": { 57 | "dockerImageRepository": "debianmaster/python-email-api" 58 | } 59 | }, { 60 | "kind": "DeploymentConfig", 61 | "apiVersion": "v1", 62 | "metadata": { 63 | "name": "python-email-api" 64 | }, 65 | "spec": { 66 | "strategy": { 67 | "type": "Rolling" 68 | }, 69 | "triggers": [{ 70 | "type": "ConfigChange", 71 | "imageChangeParams": { 72 | "automatic": true 73 | } 74 | }], 75 | "replicas": 1, 76 | "selector": { 77 | "app": "python-email-api", 78 | "deploymentconfig": "python-email-api" 79 | }, 80 | "template": { 81 | "metadata": { 82 | "name": "python-email-api", 83 | "labels": { 84 | "app": "python-email-api", 85 | "deploymentconfig": "python-email-api" 86 | } 87 | }, 88 | "spec": { 89 | "containers": [{ 90 | "name": "python-email-api", 91 | "image": "debianmaster/python-email-api@sha256:736abc826bc71286bd6d744d78c28802ab3101df25bdf93213270238c8f6090b", 92 | "ports": [{ 93 | "containerPort": 8080 94 | }] 95 | }] 96 | } 97 | } 98 | } 99 | }], 100 | "parameters": [{ 101 | "name": "MEMORY_LIMIT", 102 | "displayName": "Memory limit", 103 | "description": "Maximum amount of memory the Node.js container can use", 104 | "value": "512Mi" 105 | }, { 106 | "name": "MEMORY_MONGODB_LIMIT", 107 | "displayName": "Memory limit", 108 | "description": "Maximum amount of memory the MongoDB container can use", 109 | "value": "512Mi" 110 | }, { 111 | "name": "SOURCE_REPOSITORY_URL", 112 | "displayName": "Source repository URL", 113 | "description": "The URL of the repository with your application source code", 114 | "value": "https://github.com/debianmaster/microservices-on-openshift.git" 115 | }, { 116 | "name": "SOURCE_REPOSITORY_REF", 117 | "displayName": "Source repository reference", 118 | "description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch" 119 | }, { 120 | "name": "NODEJS_CONTEXT_DIR", 121 | "displayName": "Context directory", 122 | "description": "Set this to the relative path to your project if it is not in the root of your repository", 123 | "value": "nodejs-users-api" 124 | }, { 125 | "name": "PYTHON_CONTEXT_DIR", 126 | "displayName": "Context directory", 127 | "description": "Set this to the relative path to your project if it is not in the root of your repository", 128 | "value": "python-email-api" 129 | }, { 130 | "name": "NODEJS_APPLICATION_DOMAIN", 131 | "displayName": "Application hostname", 132 | "description": "The exposed hostname that will route to the Node.js service, if left blank a value will be defaulted.", 133 | "value": "" 134 | }, { 135 | "name": "PYTHON_APPLICATION_DOMAIN", 136 | "displayName": "Application hostname", 137 | "description": "The exposed hostname that will route to the Node.js service, if left blank a value will be defaulted.", 138 | "value": "" 139 | }, { 140 | "name": "GITHUB_WEBHOOK_SECRET", 141 | "displayName": "GitHub webhook secret", 142 | "description": "A secret string used to configure the GitHub webhook", 143 | "generate": "expression", 144 | "from": "[a-zA-Z0-9]{40}" 145 | }, { 146 | "name": "GENERIC_WEBHOOK_SECRET", 147 | "displayName": "Generic webhook secret", 148 | "description": "A secret string used to configure the Generic webhook", 149 | "generate": "expression", 150 | "from": "[a-zA-Z0-9]{40}" 151 | }, { 152 | "name": "DATABASE_SERVICE_NAME", 153 | "displayName": "Database service name", 154 | "description": "Database service name", 155 | "value": "mongodb" 156 | }, { 157 | "name": "DATABASE_USER", 158 | "displayName": "MongoDB user name", 159 | "description": "Username for MongoDB user that will be used for accessing the database", 160 | "generate": "expression", 161 | "from": "user[A-Z0-9]{3}" 162 | }, { 163 | "name": "DATABASE_PASSWORD", 164 | "displayName": "MongoDB password", 165 | "description": "Password for the MongoDB user", 166 | "generate": "expression", 167 | "from": "[a-zA-Z0-9]{16}" 168 | }, { 169 | "name": "DATABASE_NAME", 170 | "displayName": "Database name", 171 | "description": "Database name", 172 | "value": "sampledb" 173 | }, { 174 | "name": "DATABASE_ADMIN_PASSWORD", 175 | "displayName": "Database administrator password", 176 | "description": "Password for the database admin user", 177 | "generate": "expression", 178 | "from": "[a-zA-Z0-9]{16}" 179 | }] 180 | } -------------------------------------------------------------------------------- /.openshift_template/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "Template", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "name": "microservices-on-openshift", 6 | "annotations": { 7 | "description": "A microservices sample on openshift", 8 | "tags": "microservices", 9 | "iconClass": "icon-nodejs" 10 | } 11 | }, 12 | "labels": { 13 | "template": "nodejs-users-api" 14 | }, 15 | "objects": [ 16 | { 17 | "kind": "Service", 18 | "apiVersion": "v1", 19 | "metadata": { 20 | "name": "nodejs-users-api", 21 | "annotations": { 22 | "description": "Exposes and load balances the application pods" 23 | } 24 | }, 25 | "spec": { 26 | "ports": [ 27 | { 28 | "name": "web", 29 | "port": 8080, 30 | "targetPort": 8080 31 | } 32 | ], 33 | "selector": { 34 | "name": "nodejs-users-api" 35 | } 36 | } 37 | }, 38 | { 39 | "kind": "Service", 40 | "apiVersion": "v1", 41 | "metadata": { 42 | "name": "python-email-api", 43 | "annotations": { 44 | "description": "Exposes and load balances the application pods" 45 | } 46 | }, 47 | "spec": { 48 | "ports": [ 49 | { 50 | "name": "web", 51 | "port": 8080, 52 | "targetPort": 8080 53 | } 54 | ], 55 | "selector": { 56 | "name": "python-email-api" 57 | } 58 | } 59 | }, 60 | { 61 | "kind": "Service", 62 | "apiVersion": "v1", 63 | "metadata": { 64 | "name": "php-ui", 65 | "annotations": { 66 | "description": "Exposes and load balances the application pods" 67 | } 68 | }, 69 | "spec": { 70 | "ports": [ 71 | { 72 | "name": "web", 73 | "port": 8080, 74 | "targetPort": 8080 75 | } 76 | ], 77 | "selector": { 78 | "name": "php-ui" 79 | } 80 | } 81 | }, 82 | { 83 | "kind": "Route", 84 | "apiVersion": "v1", 85 | "metadata": { 86 | "name": "nodejs-users-api" 87 | }, 88 | "spec": { 89 | "host": "${NODEJS_APPLICATION_DOMAIN}", 90 | "to": { 91 | "kind": "Service", 92 | "name": "nodejs-users-api" 93 | } 94 | } 95 | }, 96 | { 97 | "kind": "Route", 98 | "apiVersion": "v1", 99 | "metadata": { 100 | "name": "python-email-api" 101 | }, 102 | "spec": { 103 | "host": "${PYTHON_APPLICATION_DOMAIN}", 104 | "to": { 105 | "kind": "Service", 106 | "name": "python-email-api" 107 | } 108 | } 109 | }, 110 | { 111 | "kind": "Route", 112 | "apiVersion": "v1", 113 | "metadata": { 114 | "name": "php-ui" 115 | }, 116 | "spec": { 117 | "host": "${PHPUI_APPLICATION_DOMAIN}", 118 | "to": { 119 | "kind": "Service", 120 | "name": "php-ui" 121 | } 122 | } 123 | }, 124 | { 125 | "kind": "ImageStream", 126 | "apiVersion": "v1", 127 | "metadata": { 128 | "name": "nodejs-users-api", 129 | "annotations": { 130 | "description": "Keeps track of changes in the application image" 131 | } 132 | } 133 | }, 134 | { 135 | "kind": "ImageStream", 136 | "apiVersion": "v1", 137 | "metadata": { 138 | "name": "php-ui", 139 | "annotations": { 140 | "description": "Keeps track of changes in the application image" 141 | } 142 | } 143 | }, 144 | { 145 | "kind": "ImageStream", 146 | "apiVersion": "v1", 147 | "metadata": { 148 | "name": "python-email-api", 149 | "annotations": { 150 | "description": "Keeps track of changes in the application image" 151 | } 152 | }, 153 | "spec": { 154 | "dockerImageRepository": "debianmaster/python-email-api" 155 | } 156 | }, 157 | { 158 | "kind": "BuildConfig", 159 | "apiVersion": "v1", 160 | "metadata": { 161 | "name": "nodejs-users-api", 162 | "annotations": { 163 | "description": "Defines how to build the application" 164 | } 165 | }, 166 | "spec": { 167 | "source": { 168 | "type": "Git", 169 | "git": { 170 | "uri": "${SOURCE_REPOSITORY_URL}", 171 | "ref": "${SOURCE_REPOSITORY_REF}" 172 | }, 173 | "contextDir": "${NODEJS_CONTEXT_DIR}" 174 | }, 175 | "strategy": { 176 | "type": "Source", 177 | "sourceStrategy": { 178 | "from": { 179 | "kind": "ImageStreamTag", 180 | "namespace": "openshift", 181 | "name": "nodejs:0.10" 182 | } 183 | } 184 | }, 185 | "output": { 186 | "to": { 187 | "kind": "ImageStreamTag", 188 | "name": "nodejs-users-api:latest" 189 | } 190 | }, 191 | "triggers": [ 192 | { 193 | "type": "ImageChange" 194 | }, 195 | { 196 | "type": "ConfigChange" 197 | }, 198 | { 199 | "type": "GitHub", 200 | "github": { 201 | "secret": "${GITHUB_WEBHOOK_SECRET}" 202 | } 203 | }, 204 | { 205 | "type": "Generic", 206 | "generic": { 207 | "secret": "${GENERIC_WEBHOOK_SECRET}" 208 | } 209 | } 210 | ] 211 | } 212 | }, 213 | { 214 | "kind": "BuildConfig", 215 | "apiVersion": "v1", 216 | "metadata": { 217 | "name": "php-ui", 218 | "annotations": { 219 | "description": "Defines how to build the application" 220 | } 221 | }, 222 | "spec": { 223 | "source": { 224 | "type": "Git", 225 | "git": { 226 | "uri": "${SOURCE_REPOSITORY_URL}", 227 | "ref": "${SOURCE_REPOSITORY_REF}" 228 | }, 229 | "contextDir": "${PHPUI_CONTEXT_DIR}" 230 | }, 231 | "strategy": { 232 | "type": "Source", 233 | "sourceStrategy": { 234 | "from": { 235 | "kind": "ImageStreamTag", 236 | "namespace": "openshift", 237 | "name": "php:5.6" 238 | } 239 | } 240 | }, 241 | "output": { 242 | "to": { 243 | "kind": "ImageStreamTag", 244 | "name": "php-ui:latest" 245 | } 246 | }, 247 | "triggers": [ 248 | { 249 | "type": "ImageChange" 250 | }, 251 | { 252 | "type": "ConfigChange" 253 | }, 254 | { 255 | "type": "GitHub", 256 | "github": { 257 | "secret": "${GITHUB_WEBHOOK_SECRET}" 258 | } 259 | }, 260 | { 261 | "type": "Generic", 262 | "generic": { 263 | "secret": "${GENERIC_WEBHOOK_SECRET}" 264 | } 265 | } 266 | ] 267 | } 268 | }, 269 | { 270 | "kind": "DeploymentConfig", 271 | "apiVersion": "v1", 272 | "metadata": { 273 | "name": "nodejs-users-api", 274 | "annotations": { 275 | "description": "Defines how to deploy the application server" 276 | } 277 | }, 278 | "spec": { 279 | "strategy": { 280 | "type": "Rolling" 281 | }, 282 | "triggers": [ 283 | { 284 | "type": "ImageChange", 285 | "imageChangeParams": { 286 | "automatic": true, 287 | "containerNames": [ 288 | "nodejs-users-api" 289 | ], 290 | "from": { 291 | "kind": "ImageStreamTag", 292 | "name": "nodejs-users-api:latest" 293 | } 294 | } 295 | }, 296 | { 297 | "type": "ConfigChange" 298 | } 299 | ], 300 | "replicas": 1, 301 | "selector": { 302 | "name": "nodejs-users-api" 303 | }, 304 | "template": { 305 | "metadata": { 306 | "name": "nodejs-users-api", 307 | "labels": { 308 | "name": "nodejs-users-api" 309 | } 310 | }, 311 | "spec": { 312 | "containers": [ 313 | { 314 | "name": "nodejs-users-api", 315 | "image": "nodejs-users-api", 316 | "ports": [ 317 | { 318 | "containerPort": 8080 319 | } 320 | ], 321 | "env": [ 322 | { 323 | "name": "DATABASE_SERVICE_NAME", 324 | "value": "${DATABASE_SERVICE_NAME}" 325 | }, 326 | { 327 | "name": "MONGODB_USER", 328 | "value": "${DATABASE_USER}" 329 | }, 330 | { 331 | "name": "MONGODB_PASSWORD", 332 | "value": "${DATABASE_PASSWORD}" 333 | }, 334 | { 335 | "name": "MONGODB_DATABASE", 336 | "value": "${DATABASE_NAME}" 337 | }, 338 | { 339 | "name": "MONGODB_ADMIN_PASSWORD", 340 | "value": "${DATABASE_ADMIN_PASSWORD}" 341 | } 342 | ], 343 | "readinessProbe": { 344 | "timeoutSeconds": 3, 345 | "initialDelaySeconds": 3, 346 | "httpGet": { 347 | "path": "/pagecount", 348 | "port": 8080 349 | } 350 | }, 351 | "livenessProbe": { 352 | "timeoutSeconds": 3, 353 | "initialDelaySeconds": 30, 354 | "httpGet": { 355 | "path": "/pagecount", 356 | "port": 8080 357 | } 358 | }, 359 | "resources": { 360 | "limits": { 361 | "memory": "${MEMORY_LIMIT}" 362 | } 363 | } 364 | } 365 | ] 366 | } 367 | } 368 | } 369 | }, 370 | { 371 | "kind": "DeploymentConfig", 372 | "apiVersion": "v1", 373 | "metadata": { 374 | "name": "php-ui", 375 | "annotations": { 376 | "description": "Defines how to deploy the application server" 377 | } 378 | }, 379 | "spec": { 380 | "strategy": { 381 | "type": "Rolling" 382 | }, 383 | "triggers": [ 384 | { 385 | "type": "ImageChange", 386 | "imageChangeParams": { 387 | "automatic": true, 388 | "containerNames": [ 389 | "nodejs-users-api" 390 | ], 391 | "from": { 392 | "kind": "ImageStreamTag", 393 | "name": "nodejs-users-api:latest" 394 | } 395 | } 396 | }, 397 | { 398 | "type": "ConfigChange" 399 | } 400 | ], 401 | "replicas": 1, 402 | "selector": { 403 | "name": "php-ui" 404 | }, 405 | "template": { 406 | "metadata": { 407 | "name": "php-ui", 408 | "labels": { 409 | "name": "php-ui" 410 | } 411 | }, 412 | "spec": { 413 | "containers": [ 414 | { 415 | "name": "php-ui", 416 | "image": "php-ui:latest", 417 | "ports": [ 418 | { 419 | "containerPort": 8080 420 | } 421 | ], 422 | "env": [ 423 | { 424 | "name": "DATABASE_SERVICE_NAME", 425 | "value": "${DATABASE_SERVICE_NAME}" 426 | }, 427 | { 428 | "name": "MONGODB_USER", 429 | "value": "${DATABASE_USER}" 430 | }, 431 | { 432 | "name": "MONGODB_PASSWORD", 433 | "value": "${DATABASE_PASSWORD}" 434 | }, 435 | { 436 | "name": "MONGODB_DATABASE", 437 | "value": "${DATABASE_NAME}" 438 | }, 439 | { 440 | "name": "MONGODB_ADMIN_PASSWORD", 441 | "value": "${DATABASE_ADMIN_PASSWORD}" 442 | } 443 | ], 444 | "readinessProbe": { 445 | "timeoutSeconds": 3, 446 | "initialDelaySeconds": 3, 447 | "httpGet": { 448 | "path": "/pagecount", 449 | "port": 8080 450 | } 451 | }, 452 | "livenessProbe": { 453 | "timeoutSeconds": 3, 454 | "initialDelaySeconds": 30, 455 | "httpGet": { 456 | "path": "/pagecount", 457 | "port": 8080 458 | } 459 | }, 460 | "resources": { 461 | "limits": { 462 | "memory": "${MEMORY_LIMIT}" 463 | } 464 | } 465 | } 466 | ] 467 | } 468 | } 469 | } 470 | }, 471 | { 472 | "kind": "DeploymentConfig", 473 | "apiVersion": "v1", 474 | "metadata": { 475 | "name": "python-email-api" 476 | }, 477 | "spec": { 478 | "strategy": { 479 | "type": "Rolling" 480 | }, 481 | "triggers": [ 482 | { 483 | "type": "ConfigChange", 484 | "imageChangeParams": { 485 | "automatic": true 486 | } 487 | } 488 | ], 489 | "replicas": 1, 490 | "selector": { 491 | "app": "python-email-api", 492 | "deploymentconfig": "python-email-api" 493 | }, 494 | "template": { 495 | "metadata": { 496 | "name": "python-email-api", 497 | "labels": { 498 | "app": "python-email-api", 499 | "deploymentconfig": "python-email-api" 500 | } 501 | }, 502 | "spec": { 503 | "containers": [ 504 | { 505 | "name": "python-email-api", 506 | "image": "debianmaster/python-email-api", 507 | "ports": [ 508 | { 509 | "containerPort": 8080 510 | } 511 | ] 512 | } 513 | ] 514 | } 515 | } 516 | } 517 | }, 518 | { 519 | "kind": "Service", 520 | "apiVersion": "v1", 521 | "metadata": { 522 | "name": "${DATABASE_SERVICE_NAME}", 523 | "annotations": { 524 | "description": "Exposes the database server" 525 | } 526 | }, 527 | "spec": { 528 | "ports": [ 529 | { 530 | "name": "mongodb", 531 | "port": 27017, 532 | "targetPort": 27017 533 | } 534 | ], 535 | "selector": { 536 | "name": "${DATABASE_SERVICE_NAME}" 537 | } 538 | } 539 | }, 540 | { 541 | "kind": "DeploymentConfig", 542 | "apiVersion": "v1", 543 | "metadata": { 544 | "name": "${DATABASE_SERVICE_NAME}", 545 | "annotations": { 546 | "description": "Defines how to deploy the database" 547 | } 548 | }, 549 | "spec": { 550 | "strategy": { 551 | "type": "Recreate" 552 | }, 553 | "triggers": [ 554 | { 555 | "type": "ImageChange", 556 | "imageChangeParams": { 557 | "automatic": false, 558 | "containerNames": [ 559 | "mongodb" 560 | ], 561 | "from": { 562 | "kind": "ImageStreamTag", 563 | "namespace": "openshift", 564 | "name": "mongodb:2.6" 565 | } 566 | } 567 | }, 568 | { 569 | "type": "ConfigChange" 570 | } 571 | ], 572 | "replicas": 0, 573 | "selector": { 574 | "name": "${DATABASE_SERVICE_NAME}" 575 | }, 576 | "template": { 577 | "metadata": { 578 | "name": "${DATABASE_SERVICE_NAME}", 579 | "labels": { 580 | "name": "${DATABASE_SERVICE_NAME}" 581 | } 582 | }, 583 | "spec": { 584 | "containers": [ 585 | { 586 | "name": "mongodb", 587 | "image": "mongodb", 588 | "ports": [ 589 | { 590 | "containerPort": 27017 591 | } 592 | ], 593 | "env": [ 594 | { 595 | "name": "MONGODB_USER", 596 | "value": "${DATABASE_USER}" 597 | }, 598 | { 599 | "name": "MONGODB_PASSWORD", 600 | "value": "${DATABASE_PASSWORD}" 601 | }, 602 | { 603 | "name": "MONGODB_DATABASE", 604 | "value": "${DATABASE_NAME}" 605 | }, 606 | { 607 | "name": "MONGODB_ADMIN_PASSWORD", 608 | "value": "${DATABASE_ADMIN_PASSWORD}" 609 | } 610 | ], 611 | "readinessProbe": { 612 | "timeoutSeconds": 1, 613 | "initialDelaySeconds": 3, 614 | "exec": { 615 | "command": [ 616 | "/bin/sh", 617 | "-i", 618 | "-c", 619 | "mongostat --host 127.0.0.1 -u admin -p ${DATABASE_ADMIN_PASSWORD} -n 1 --noheaders" 620 | ] 621 | } 622 | }, 623 | "livenessProbe": { 624 | "timeoutSeconds": 1, 625 | "initialDelaySeconds": 30, 626 | "tcpSocket": { 627 | "port": 27017 628 | } 629 | }, 630 | "resources": { 631 | "limits": { 632 | "memory": "${MEMORY_MONGODB_LIMIT}" 633 | } 634 | } 635 | } 636 | ] 637 | } 638 | } 639 | } 640 | } 641 | ], 642 | "parameters": [ 643 | { 644 | "name": "MEMORY_LIMIT", 645 | "displayName": "Memory limit", 646 | "description": "Maximum amount of memory the Node.js container can use", 647 | "value": "512Mi" 648 | }, 649 | { 650 | "name": "MEMORY_MONGODB_LIMIT", 651 | "displayName": "Memory limit", 652 | "description": "Maximum amount of memory the MongoDB container can use", 653 | "value": "512Mi" 654 | }, 655 | { 656 | "name": "SOURCE_REPOSITORY_URL", 657 | "displayName": "Source repository URL", 658 | "description": "The URL of the repository with your application source code", 659 | "value": "https://github.com/debianmaster/microservices-on-openshift.git" 660 | }, 661 | { 662 | "name": "SOURCE_REPOSITORY_REF", 663 | "displayName": "Source repository reference", 664 | "description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch" 665 | }, 666 | { 667 | "name": "NODEJS_CONTEXT_DIR", 668 | "displayName": "Users API context dir", 669 | "description": "Set this to the relative path to your project if it is not in the root of your repository", 670 | "value": "nodejs-users-api" 671 | }, 672 | { 673 | "name": "PHPUI_CONTEXT_DIR", 674 | "displayName": "UI context dir", 675 | "description": "Set this to the relative path to your project if it is not in the root of your repository", 676 | "value": "php-ui" 677 | }, 678 | { 679 | "name": "PYTHON_CONTEXT_DIR", 680 | "displayName": "Email API context dir", 681 | "description": "Set this to the relative path to your project if it is not in the root of your repository", 682 | "value": "python-email-api" 683 | }, 684 | { 685 | "name": "NODEJS_APPLICATION_DOMAIN", 686 | "displayName": "Application hostname", 687 | "description": "The exposed hostname that will route to the Node.js service, if left blank a value will be defaulted.", 688 | "value": "" 689 | }, 690 | { 691 | "name": "PYTHON_APPLICATION_DOMAIN", 692 | "displayName": "Application hostname", 693 | "description": "The exposed hostname that will route to the Node.js service, if left blank a value will be defaulted.", 694 | "value": "" 695 | }, 696 | { 697 | "name": "PHPUI_APPLICATION_DOMAIN", 698 | "displayName": "Application hostname", 699 | "description": "The exposed hostname that will route to the Node.js service, if left blank a value will be defaulted.", 700 | "value": "" 701 | }, 702 | { 703 | "name": "GITHUB_WEBHOOK_SECRET", 704 | "displayName": "GitHub webhook secret", 705 | "description": "A secret string used to configure the GitHub webhook", 706 | "generate": "expression", 707 | "from": "[a-zA-Z0-9]{40}" 708 | }, 709 | { 710 | "name": "GENERIC_WEBHOOK_SECRET", 711 | "displayName": "Generic webhook secret", 712 | "description": "A secret string used to configure the Generic webhook", 713 | "generate": "expression", 714 | "from": "[a-zA-Z0-9]{40}" 715 | }, 716 | { 717 | "name": "DATABASE_SERVICE_NAME", 718 | "displayName": "Database service name", 719 | "description": "Database service name", 720 | "value": "mongodb" 721 | }, 722 | { 723 | "name": "DATABASE_USER", 724 | "displayName": "MongoDB user name", 725 | "description": "Username for MongoDB user that will be used for accessing the database", 726 | "generate": "expression", 727 | "from": "user[A-Z0-9]{3}" 728 | }, 729 | { 730 | "name": "DATABASE_PASSWORD", 731 | "displayName": "MongoDB password", 732 | "description": "Password for the MongoDB user", 733 | "generate": "expression", 734 | "from": "[a-zA-Z0-9]{16}" 735 | }, 736 | { 737 | "name": "DATABASE_NAME", 738 | "displayName": "Database name", 739 | "description": "Database name", 740 | "value": "sampledb" 741 | }, 742 | { 743 | "name": "DATABASE_ADMIN_PASSWORD", 744 | "displayName": "Database administrator password", 745 | "description": "Password for the database admin user", 746 | "generate": "expression", 747 | "from": "[a-zA-Z0-9]{16}" 748 | } 749 | ] 750 | } -------------------------------------------------------------------------------- /.openshift_template/tomcat_templates.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "Template", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "annotations": { 6 | "iconClass": "icon-tomcat", 7 | "description": "Application template for JWS applications built using S2I.", 8 | "tags": "tomcat,tomcat7,java,jboss,xpaas", 9 | "version": "1.2.0" 10 | }, 11 | "name": "jws30-tomcat7-basic-s2i" 12 | }, 13 | "labels": { 14 | "template": "jws30-tomcat7-basic-s2i", 15 | "xpaas": "1.2.0" 16 | }, 17 | "parameters": [ 18 | { 19 | "description": "The name for the application.", 20 | "name": "APPLICATION_NAME", 21 | "value": "jws-app", 22 | "required": true 23 | }, 24 | { 25 | "description": "Custom hostname for http service route. Leave blank for default hostname, e.g.: -.", 26 | "name": "HOSTNAME_HTTP", 27 | "value": "", 28 | "required": false 29 | }, 30 | { 31 | "description": "Git source URI for application", 32 | "name": "SOURCE_REPOSITORY_URL", 33 | "value": "https://github.com/jboss-openshift/openshift-quickstarts.git", 34 | "required": true 35 | }, 36 | { 37 | "description": "Git branch/tag reference", 38 | "name": "SOURCE_REPOSITORY_REF", 39 | "value": "1.2", 40 | "required": false 41 | }, 42 | { 43 | "description": "Path within Git project to build; empty for root project directory.", 44 | "name": "CONTEXT_DIR", 45 | "value": "tomcat-websocket-chat", 46 | "required": false 47 | }, 48 | { 49 | "description": "JWS Admin User", 50 | "name": "JWS_ADMIN_USERNAME", 51 | "from": "[a-zA-Z0-9]{8}", 52 | "generate": "expression", 53 | "required": true 54 | }, 55 | { 56 | "description": "JWS Admin Password", 57 | "name": "JWS_ADMIN_PASSWORD", 58 | "from": "[a-zA-Z0-9]{8}", 59 | "generate": "expression", 60 | "required": true 61 | }, 62 | { 63 | "description": "GitHub trigger secret", 64 | "name": "GITHUB_WEBHOOK_SECRET", 65 | "from": "[a-zA-Z0-9]{8}", 66 | "generate": "expression", 67 | "required": true 68 | }, 69 | { 70 | "description": "Generic build trigger secret", 71 | "name": "GENERIC_WEBHOOK_SECRET", 72 | "from": "[a-zA-Z0-9]{8}", 73 | "generate": "expression", 74 | "required": true 75 | }, 76 | { 77 | "description": "Namespace in which the ImageStreams for Red Hat Middleware images are installed. These ImageStreams are normally installed in the openshift namespace. You should only need to modify this if you've installed the ImageStreams in a different namespace/project.", 78 | "name": "IMAGE_STREAM_NAMESPACE", 79 | "value": "openshift", 80 | "required": true 81 | } 82 | ], 83 | "objects": [ 84 | { 85 | "kind": "Service", 86 | "apiVersion": "v1", 87 | "spec": { 88 | "ports": [ 89 | { 90 | "port": 8080, 91 | "targetPort": 8080 92 | } 93 | ], 94 | "selector": { 95 | "deploymentConfig": "${APPLICATION_NAME}" 96 | } 97 | }, 98 | "metadata": { 99 | "name": "${APPLICATION_NAME}", 100 | "labels": { 101 | "application": "${APPLICATION_NAME}" 102 | }, 103 | "annotations": { 104 | "description": "The web server's http port." 105 | } 106 | } 107 | }, 108 | { 109 | "kind": "Route", 110 | "apiVersion": "v1", 111 | "id": "${APPLICATION_NAME}-http", 112 | "metadata": { 113 | "name": "${APPLICATION_NAME}", 114 | "labels": { 115 | "application": "${APPLICATION_NAME}" 116 | }, 117 | "annotations": { 118 | "description": "Route for application's http service." 119 | } 120 | }, 121 | "spec": { 122 | "host": "${HOSTNAME_HTTP}", 123 | "to": { 124 | "name": "${APPLICATION_NAME}" 125 | } 126 | } 127 | }, 128 | { 129 | "kind": "ImageStream", 130 | "apiVersion": "v1", 131 | "metadata": { 132 | "name": "${APPLICATION_NAME}", 133 | "labels": { 134 | "application": "${APPLICATION_NAME}" 135 | } 136 | } 137 | }, 138 | { 139 | "kind": "BuildConfig", 140 | "apiVersion": "v1", 141 | "metadata": { 142 | "name": "${APPLICATION_NAME}", 143 | "labels": { 144 | "application": "${APPLICATION_NAME}" 145 | } 146 | }, 147 | "spec": { 148 | "source": { 149 | "type": "Git", 150 | "git": { 151 | "uri": "${SOURCE_REPOSITORY_URL}", 152 | "ref": "${SOURCE_REPOSITORY_REF}" 153 | }, 154 | "contextDir": "${CONTEXT_DIR}" 155 | }, 156 | "strategy": { 157 | "type": "Source", 158 | "sourceStrategy": { 159 | "forcePull": true, 160 | "from": { 161 | "kind": "ImageStreamTag", 162 | "namespace": "${IMAGE_STREAM_NAMESPACE}", 163 | "name": "jboss-webserver30-tomcat7-openshift:1.2" 164 | } 165 | } 166 | }, 167 | "output": { 168 | "to": { 169 | "kind": "ImageStreamTag", 170 | "name": "${APPLICATION_NAME}:latest" 171 | } 172 | }, 173 | "triggers": [ 174 | { 175 | "type": "GitHub", 176 | "github": { 177 | "secret": "${GITHUB_WEBHOOK_SECRET}" 178 | } 179 | }, 180 | { 181 | "type": "Generic", 182 | "generic": { 183 | "secret": "${GENERIC_WEBHOOK_SECRET}" 184 | } 185 | }, 186 | { 187 | "type": "ImageChange", 188 | "imageChange": {} 189 | }, 190 | { 191 | "type": "ConfigChange" 192 | } 193 | ] 194 | } 195 | }, 196 | { 197 | "kind": "DeploymentConfig", 198 | "apiVersion": "v1", 199 | "metadata": { 200 | "name": "${APPLICATION_NAME}", 201 | "labels": { 202 | "application": "${APPLICATION_NAME}" 203 | } 204 | }, 205 | "spec": { 206 | "strategy": { 207 | "type": "Recreate" 208 | }, 209 | "triggers": [ 210 | { 211 | "type": "ImageChange", 212 | "imageChangeParams": { 213 | "automatic": true, 214 | "containerNames": [ 215 | "${APPLICATION_NAME}" 216 | ], 217 | "from": { 218 | "kind": "ImageStream", 219 | "name": "${APPLICATION_NAME}" 220 | } 221 | } 222 | }, 223 | { 224 | "type": "ConfigChange" 225 | } 226 | ], 227 | "replicas": 1, 228 | "selector": { 229 | "deploymentConfig": "${APPLICATION_NAME}" 230 | }, 231 | "template": { 232 | "metadata": { 233 | "name": "${APPLICATION_NAME}", 234 | "labels": { 235 | "deploymentConfig": "${APPLICATION_NAME}", 236 | "application": "${APPLICATION_NAME}" 237 | } 238 | }, 239 | "spec": { 240 | "terminationGracePeriodSeconds": 60, 241 | "containers": [ 242 | { 243 | "name": "${APPLICATION_NAME}", 244 | "image": "${APPLICATION_NAME}", 245 | "imagePullPolicy": "Always", 246 | "readinessProbe": { 247 | "exec": { 248 | "command": [ 249 | "/bin/bash", 250 | "-c", 251 | "curl -s -u ${JWS_ADMIN_USERNAME}:${JWS_ADMIN_PASSWORD} 'http://localhost:8080/manager/jmxproxy/?get=Catalina%3Atype%3DServer&att=stateName' |grep -iq 'stateName *= *STARTED'" 252 | ] 253 | } 254 | }, 255 | "ports": [ 256 | { 257 | "name": "jolokia", 258 | "containerPort": 8778, 259 | "protocol": "TCP" 260 | }, 261 | { 262 | "name": "http", 263 | "containerPort": 8080, 264 | "protocol": "TCP" 265 | } 266 | ], 267 | "env": [ 268 | { 269 | "name": "JWS_ADMIN_USERNAME", 270 | "value": "${JWS_ADMIN_USERNAME}" 271 | }, 272 | { 273 | "name": "JWS_ADMIN_PASSWORD", 274 | "value": "${JWS_ADMIN_PASSWORD}" 275 | } 276 | ] 277 | } 278 | ] 279 | } 280 | } 281 | } 282 | } 283 | ] 284 | } 285 | -------------------------------------------------------------------------------- /Arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debianmaster/microservices-on-openshift/34fd31d607a2ce09355030d78effdb96857ec980/Arch.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repo demonstrates simple development and deployment of polyglot microservices on OpenShift V3. The diagram below is the architecture of the application that is made up of three sample micro services. 2 | 3 | 1. UserRegistration Backend: This microservices exposes REST APIs to register users, display user list etc. The code is written in NodeJS and it persists the data into a MongoDB database 4 | 5 | 2. UserRegistration: This is frontend UI built using PHP. The job of this microservice is confined to creating web pages. 6 | 7 | 3. Email Service: This is a generic email service that receives a request and sends an email. This code is written in Python. We will also add an email log (thinking of MySQL DB). 8 | 9 | 10 | 11 | ![alt tag](https://raw.githubusercontent.com/veermuchandi/microservices-on-openshift/master/Arch.png) 12 | 13 | > This is how it looks at the end 14 | 15 | 16 | ![alt tag](https://raw.githubusercontent.com/veermuchandi/Notes/master/demogif-latest.gif) 17 | 18 | 19 | # 20 | 21 | ## 0. Initial Setup 22 | > To setup openshift on your laptop using a Vagrant image use https://www.openshift.org/vm/ 23 | > Assuming you have openshift installed on https://10.2.2.2:8443 24 | 25 | Create an OpenShift project where these microservices will be created for development purposes. As an example we are calling it msdev. 26 | 27 | 28 | ``` 29 | oc login https://10.2.2.2:8443 30 | oc new-project msdev 31 | ``` 32 | 33 | **Note:** If you want to quickly deploy these microservices you can use the install scripts. [Read here](installscripts/readme.md) 34 | 35 | If you wish to change the code, feel free to fork the code and use your git links instead. 36 | 37 | 38 | Let us create some environment variable that makes it easy to deal with some of the parameters we use in the subsequent commands 39 | ```sh 40 | export OSE_DOMAIN=< 41 | export OSE_PROJECT=< 42 | ``` 43 | Ex:-- 44 | `$ export OSE_DOMAIN=apps.10.2.2.2.xip.io` 45 | `$ export OSE_PROJECT=msdev` 46 | 47 | 48 | ## 1. Create the Email Micro Service 49 | > Python application 50 | The below command creates a new application for email service. This code is written in Python and emails are archived in mysql. This service receives the email request and sends out the email. 51 | 52 | ###### Create mysql backend 53 | 54 | ```sh 55 | $ oc new-app -e MYSQL_USER='app_user' \ 56 | MYSQL_PASSWORD='password' \ 57 | MYSQL_DATABASE=microservices \ 58 | registry.access.redhat.com/rhscl/mysql-56-rhel7 --name='mysql' -l microservice=emailsvc 59 | 60 | $ oc patch dc/mysql --patch '{"spec":{"strategy":{"rollingParams":{"post":{"failurePolicy": "ignore","execNewPod":{"containerName":"mysql","command":["/bin/sh","-c","hostname&&sleep 10&&echo $QUERY | /opt/rh/rh-mysql56/root/usr/bin/mysql -h $MYSQL_SERVICE_HOST -u $MYSQL_USER -D $MYSQL_DATABASE -p$MYSQL_PASSWORD -P 3306"], "env": [{"name": "QUERY", "value":"CREATE TABLE IF NOT EXISTS emails \u0028from_add varchar\u002840\u0029,to_add varchar\u002840\u0029, subject varchar\u002840\u0029, body varchar\u0028200\u0029, created_at date\u0029;"}]}}}}}}' 61 | 62 | $ oc rollout latest mysql 63 | 64 | ``` 65 | > oc patch command above will create the table as a post deployment script instead of getting into the pod and running the following commands manually to create tables. The commands below are just FYI. 66 | 67 | 68 | ```sh 69 | $ sleep 10 # wait till the mysql is pod is created 70 | $ oc rsh $(oc get pods | grep mysql | grep Running | awk '{print $1}') # rsh will ssh into the mysql pod 71 | $ mysql -u $MYSQL_USER -p$MYSQL_PASSWORD -h $HOSTNAME $MYSQL_DATABASE ##inside the pod 72 | ``` 73 | 74 | ```sql 75 | create table emails (from_add varchar(40), to_add varchar(40), subject varchar(40), body varchar(200), created_at date); 76 | ``` 77 | ```sh 78 | $ exit # to exit from mysql prompt 79 | $ exit # to exit from pod 80 | ``` 81 | 82 | ###### Create email service 83 | 84 | ```sh 85 | oc new-app --context-dir='python-email-api' \ 86 | -e EMAIL_APPLICATION_DOMAIN=http://emailsvc:8080\ 87 | MYSQL_USER='app_user'\ 88 | MYSQL_PASSWORD='password'\ 89 | MYSQL_DATABASE='microservices'\ 90 | MYSQL_SERVICE_HOST='MYSQL'\ 91 | https://github.com/veermuchandi/microservices-on-openshift.git \ 92 | --name=emailsvc --image-stream='python:2.7' -l microservice=emailsvc 93 | ``` 94 | 95 | Although we can expose this service using a URL, if we want this email service to be used by other applications over http using the command ``oc expose svc/emailsvc``, we are not doing it here as we intend to use this as an internal service. You will see in the next section that the User Registration service will use the internal service name ```emailsvc``` to send emails. 96 | 97 | ## 2. Creating User Registration Backend Micro Service (nodejs application) 98 | This service contains two components. It has a database that saves the user data for which we are using MongoDB. It has business logic layer that exposes REST APIs to register a user, get userslist etc. This part of the application is written in NodeJS. We can deploy this microservice using one of the following two approaches. 99 | 100 | Approach 101 | 1. Create a MongoDB database and expose it as an internal service 102 | 2. Create a User Registration Service that talks to the database deployed in the previous step. We are going to name this as "userregsvc". 103 | 104 | ###### Create a MongoDB database 105 | ```sh 106 | $ oc new-app -e MONGODB_USER=mongouser MONGODB_PASSWORD=password \ 107 | MONGODB_DATABASE=userdb MONGODB_ADMIN_PASSWORD=password \ 108 | registry.access.redhat.com/rhscl/mongodb-26-rhel7 \ 109 | --name mongodb -l microservice=userregsvc 110 | $ oc deploy mongodb --latest 111 | ``` 112 | 113 | ###### Create the User Registration Service and expose the service so that we can use a URL to make calls to the REST APIs exposed by this service 114 | ```sh 115 | oc new-app -e EMAIL_APPLICATION_DOMAIN=http://emailsvc:8080 \ 116 | MONGODB_DATABASE=userdb MONGODB_PASSWORD=password \ 117 | MONGODB_USER=mongouser DATABASE_SERVICE_NAME=mongodb \ 118 | --context-dir='nodejs-users-api' \ 119 | https://github.com/veermuchandi/microservices-on-openshift.git \ 120 | --name='userregsvc' -l microservice=userregsvc 121 | 122 | oc expose svc/userregsvc 123 | ``` 124 | Note that we are using internal emailsvc as the EMAIL_APPLICATION_DOMAIN 125 | 126 | 127 | ## 3. Create Twitter feeds API microservice 128 | > (Java application) 129 | This microservice is a java application which takes twitter username as input and outputs recent tweets of the user. 130 | 131 | ```sh 132 | oc import-image --from=registry.access.redhat.com/jboss-webserver-3/webserver30-tomcat8-openshift tomcat8 --confirm 133 | 134 | oc new-app \ 135 | https://github.com/veermuchandi/microservices-on-openshift.git \ 136 | --context-dir='java-twitter-feed-api' \ 137 | --image-stream='tomcat8' \ 138 | --name='twitter-api' -l microservice=twittersvc 139 | 140 | oc expose svc/twitter-api 141 | ``` 142 | 143 | 144 | ## 4. Create the frontend user registration application as a separate microservice 145 | > (php application) 146 | This microservice produces html+javascript to run in a browser and makes ajax calls to the backend User Registration service using REST APIs. 147 | Note that we are setting an environment variable for userregsvc to access the backend using REST APIs. 148 | 149 | ```sh 150 | $ oc new-app -e USER_REG_SVC="http://userregsvc-$OSE_PROJECT.$OSE_DOMAIN" \ 151 | -e TWITTER_FEED_SVC="http://twitter-api-$OSE_PROJECT.$OSE_DOMAIN" \ 152 | --context-dir='php-ui' \ 153 | https://github.com/veermuchandi/microservices-on-openshift.git \ 154 | --name='userreg' \ 155 | -l microservice=userreg 156 | 157 | $ oc expose svc/userreg 158 | ``` 159 | The service exposed in the above step is our application front end. You can find the URL by running ```oc get route``` 160 | 161 | ## 5. Verification and Testing 162 | 163 | > Visit http://userreg-msdev.apps.10.2.2.2.xip.io/ to see the php frontend. 164 | 165 | 166 | 167 | ## 6. Scaling applications 168 | > Suppose you have a huge traffic and you want to scale front end 169 | 170 | ```sh 171 | oc scale dc/userreg --replicas=4 172 | ``` 173 | -------------------------------------------------------------------------------- /installscripts/1.setVariable.sh: -------------------------------------------------------------------------------- 1 | export OSE_DOMAIN=apps.devday.ocpcloud.com 2 | export OSE_CLIENT_PROJECT=msservices 3 | export OSE_SERVICES_PROJECT=msservices 4 | export OSE_INFRA_PROJECT=msservices 5 | export FROM_GMAIL=<> 6 | export FROM_GMAIL_PASSWORD=<> 7 | //For these params refer https://dev.twitter.com/oauth/overview/application-owner-access-tokens 8 | export TWITTER_CONSUMER_KEY=<> 9 | export TWITTER_CONSUMER_SECRET=<> 10 | export TWITTER_OAUTH_ACCESS_TOKEN=<> 11 | export TWITTER_OAUTH_ACCESS_TOKEN_SECRET=<> 12 | 13 | -------------------------------------------------------------------------------- /installscripts/2.deployEmailSvc-PythonMySQL.sh: -------------------------------------------------------------------------------- 1 | oc project $OSE_INFRA_PROJECT 2 | oc new-app -e MYSQL_USER='app_user' \ 3 | MYSQL_PASSWORD='password' \ 4 | MYSQL_DATABASE=microservices \ 5 | registry.access.redhat.com/rhscl/mysql-56-rhel7 --name='mysql' -l microservice=emailsvc 6 | 7 | sleep 10 8 | 9 | oc deploy mysql --cancel 10 | 11 | oc patch dc/mysql --patch '{"spec":{"strategy":{"rollingParams":{"post":{"failurePolicy": "ignore","execNewPod":{"containerName":"mysql","command":["/bin/sh","-c","hostname&&sleep 10&&echo $QUERY | /opt/rh/rh-mysql56/root/usr/bin/mysql -h $MYSQL_SERVICE_HOST -u $MYSQL_USER -D $MYSQL_DATABASE -p$MYSQL_PASSWORD -P 3306"], "env": [{"name": "QUERY", "value":"CREATE TABLE IF NOT EXISTS emails \u0028from_add varchar\u002840\u0029,to_add varchar\u002840\u0029, subject varchar\u002840\u0029, body varchar\u0028200\u0029, created_at date\u0029;"}]}}}}}}' 12 | 13 | oc rollout latest mysql 14 | 15 | oc new-app --context-dir='python-email-api' \ 16 | -e EMAIL_APPLICATION_DOMAIN=http://emailsvc:8080 \ 17 | MYSQL_USER='app_user' \ 18 | MYSQL_PASSWORD='password' \ 19 | MYSQL_DATABASE='microservices' \ 20 | MYSQL_SERVICE_HOST='MYSQL' \ 21 | https://github.com/veermuchandi/microservices-on-openshift.git \ 22 | --name=emailsvc --image-stream='python:2.7' -l microservice=emailsvc 23 | 24 | oc create configmap email-props --from-literal=GMAIL_USERNAME=$FROM_GMAIL --from-literal=GMAIL_PASSWORD=$FROM_GMAIL_PASSWORD 25 | oc env dc/emailsvc --from=configmap/email-props 26 | 27 | -------------------------------------------------------------------------------- /installscripts/3.deployTwitter-Tomcat.sh: -------------------------------------------------------------------------------- 1 | oc project $OSE_SERVICES_PROJECT 2 | oc import-image --from=registry.access.redhat.com/jboss-webserver-3/webserver30-tomcat8-openshift tomcat8 --confirm 3 | 4 | oc new-app \ 5 | https://github.com/veermuchandi/microservices-on-openshift.git \ 6 | --context-dir='java-twitter-feed-api' \ 7 | --image-stream='tomcat8' \ 8 | --name='twitter-api' -l microservice=twittersvc 9 | 10 | oc create configmap twitter-props \ 11 | --from-literal=TWITTER_CONSUMER_KEY=$TWITTER_CONSUMER_KEY \ 12 | --from-literal=TWITTER_CONSUMER_SERVICE=$TWITTER_CONSUMER_SECRET \ 13 | --from-literal=TWITTER_OAUTH_ACCESS_TOKEN=$TWITTER_OAUTH_ACCESS_TOKEN \ 14 | --from-literal=TWITTER_OAUTH_ACCESS_TOKEN_SECRET=$TWITTER_OAUTH_ACCESS_TOKEN_SECRET 15 | 16 | oc env dc/twitter-api --from=configmap/twitter-props 17 | 18 | oc expose svc/twitter-api 19 | -------------------------------------------------------------------------------- /installscripts/4.deployUserRegBackend-NodejsMongo.sh: -------------------------------------------------------------------------------- 1 | oc project $OSE_SERVICES_PROJECT 2 | 3 | export EMAIL_SERVICE_URL="http://emailsvc."$OSE_INFRA_PROJECT":8080" 4 | 5 | oc new-app -e MONGODB_USER=mongouser MONGODB_PASSWORD=password \ 6 | MONGODB_DATABASE=userdb MONGODB_ADMIN_PASSWORD=password \ 7 | registry.access.redhat.com/rhscl/mongodb-26-rhel7 \ 8 | --name mongodb -l microservice=userregsvc 9 | 10 | oc deploy mongodb --latest 11 | 12 | oc new-app -e EMAIL_APPLICATION_DOMAIN=$EMAIL_SERVICE_URL \ 13 | MONGODB_DATABASE=userdb MONGODB_PASSWORD=password \ 14 | MONGODB_USER=mongouser DATABASE_SERVICE_NAME=mongodb \ 15 | --context-dir='nodejs-users-api' \ 16 | https://github.com/debianmaster/microservices-on-openshift.git \ 17 | --name='userregsvc' -l microservice=userregsvc 18 | 19 | oc expose svc/userregsvc 20 | -------------------------------------------------------------------------------- /installscripts/5.deployFrontend-PHP.sh: -------------------------------------------------------------------------------- 1 | oc project $OSE_CLIENT_PROJECT 2 | oc new-app -e USER_REG_SVC="http://userregsvc-$OSE_SERVICES_PROJECT.$OSE_DOMAIN" \ 3 | -e TWITTER_FEED_SVC="http://twitter-api-$OSE_SERVICES_PROJECT.$OSE_DOMAIN" \ 4 | --context-dir='php-ui' \ 5 | https://github.com/veermuchandi/microservices-on-openshift.git \ 6 | --name='userreg' \ 7 | -l microservice=userreg 8 | oc expose svc/userreg 9 | -------------------------------------------------------------------------------- /installscripts/readme.md: -------------------------------------------------------------------------------- 1 | # Quick Install Scripts 2 | 3 | If you want to quickly deploy these microservices independently without using templates, you can use the following scripts. 4 | 5 | Once you clone the repository, navigate to `installscripts` folder. Run the scripts in order. 6 | 7 | [1.setVariable.sh](1.setVariable.sh) This script sets all the environment variables needed by your services. Edit this script first. 8 | 9 | * Create a project to deploy microservices (`oc new-project mstest`) and use the same projectName (example `mstest`) as the value for three variables `OSE_CLIENT_PROJECT`, `OSE_SERVICES_PROJECT` and `OSE_INFRA_PROJECT`. For more complex deployments where you want to separate this application into distinct projects these variables may gave separate values. 10 | * `OSE_DOMAIN` is the domain name or the wildcard DNS for your openshift setup. 11 | * `FROM_GMAIL` and `FROM_GMAIL_PASSWORD` are the values for the gmail account to use by the email service. Email service requires a gmail account to use to send emails from. So create an email account and add the values for these variables. 12 | * `TWITTER_CONSUMER_KEY`, `TWITTER_CONSUMER_SECRET`, `TWITTER_OAUTH_ACCESS_TOKEN`, `TWITTER_OAUTH_ACCESS_TOKEN_SECRET` are the credentials required by the Twitter service to pull the tweets. Refer the documentation here [https://dev.twitter.com/oauth/overview/application-owner-access-tokens](https://dev.twitter.com/oauth/overview/application-owner-access-tokens) 13 | 14 | Once the values are assigned to environment variables, run this script as follows to set the values to the environment variables. 15 | ``` 16 | source 1.setVariable.sh 17 | ``` 18 | 19 | [2.deployEmailSvc-PythonMySQL.sh](2.deployEmailSvc-PythonMySQL.sh) 20 | This script deploys email service written in python that uses MySQL database to store the emails. The gmail credentials required by this service are added as a configmap and assigned to the environment variables used by the python code. Run this code as follows 21 | 22 | ``` 23 | source 2.deployEmailSvc-PythonMySQL.sh 24 | ``` 25 | 26 | [3.deployTwitter-Tomcat.sh](3.deployTwitter-Tomcat.sh) 27 | This script deploys the Twitter service written in Java. This service requires connection to Twitter. Twitter credentials are added as a configmap and are configured as environment variables that get the values from configmap. Run the script as follows 28 | 29 | ``` 30 | source 3.deployTwitter-Tomcat.sh 31 | ``` 32 | 33 | 34 | [4.deployUserRegBackend-NodejsMongo.sh](4.deployUserRegBackend-NodejsMongo.sh) 35 | This script deploys the UserRegistration backed that is written in NodeJS. The data is saved to a MongoDB. 36 | 37 | ``` 38 | source 4.deployUserRegBackend-NodejsMongo.sh 39 | ``` 40 | 41 | [5.deployFrontend-PHP.sh](5.deployFrontend-PHP.sh) 42 | This script deploys front-end microservice written in PHP. The resultant application should make REST calls to UserRegistration backend, and Twitter services. 43 | 44 | ``` 45 | source 5.deployFrontend-PHP.sh 46 | ``` 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /installscripts/x.cleanup: -------------------------------------------------------------------------------- 1 | oc delete all --all -n $OSE_CLIENT_PROJECT 2 | oc delete all --all -n $OSE_SERVICES_PROJECT 3 | oc delete all --all -n $OSE_INFRA_PROJECT 4 | oc delete configmap --all -n $OSE_CLIENT_PROJECT 5 | oc delete configmap --all -n $OSE_SERVICES_PROJECT 6 | oc delete configmap --all -n $OSE_INFRA_PROJECT 7 | -------------------------------------------------------------------------------- /java-twitter-feed-api/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | com.example 7 | simple-service-webapp 8 | war 9 | 1.0-SNAPSHOT 10 | simple-service-webapp 11 | 12 | 13 | simple-service-webapp 14 | 15 | 16 | org.apache.maven.plugins 17 | maven-compiler-plugin 18 | 2.5.1 19 | true 20 | 21 | 1.7 22 | 1.7 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | org.glassfish.jersey 32 | jersey-bom 33 | ${jersey.version} 34 | pom 35 | import 36 | 37 | 38 | 39 | 40 | 41 | 42 | org.glassfish.jersey.containers 43 | jersey-container-servlet-core 44 | 45 | 46 | 47 | com.googlecode.json-simple 48 | json-simple 49 | 1.1 50 | 51 | 52 | org.twitter4j 53 | twitter4j-core 54 | [4.0,) 55 | 56 | 57 | org.glassfish.jersey.media 58 | jersey-media-moxy 59 | 60 | 61 | com.fasterxml.jackson.jaxrs 62 | jackson-jaxrs-json-provider 63 | 2.2.3 64 | 65 | 66 | junit 67 | junit 68 | 4.9 69 | test 70 | 71 | 72 | 73 | 2.22.2 74 | UTF-8 75 | 76 | 77 | -------------------------------------------------------------------------------- /java-twitter-feed-api/src/main/java/com/example/MyResource.java: -------------------------------------------------------------------------------- 1 | 2 | package com.example; 3 | 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import javax.ws.rs.GET; 9 | import javax.ws.rs.Path; 10 | import javax.ws.rs.Produces; 11 | import javax.ws.rs.QueryParam; 12 | import javax.ws.rs.core.MediaType; 13 | import javax.ws.rs.core.Response; 14 | 15 | import twitter4j.Query; 16 | import twitter4j.QueryResult; 17 | import twitter4j.Twitter; 18 | import twitter4j.TwitterException; 19 | import twitter4j.TwitterFactory; 20 | import twitter4j.conf.ConfigurationBuilder; 21 | 22 | /** 23 | * Root resource (exposed at "myresource" path) 24 | */ 25 | @Path("tweets") 26 | public class MyResource { 27 | 28 | 29 | @GET 30 | @Produces(MediaType.APPLICATION_JSON) 31 | public Response getIt(@QueryParam("name") String name) { 32 | 33 | User u = new User(); 34 | List tweetsFromUser = new ArrayList(); 35 | 36 | try { 37 | 38 | ConfigurationBuilder cb = new ConfigurationBuilder(); 39 | cb.setDebugEnabled(true) 40 | .setOAuthConsumerKey(System.getenv("TWITTER_CONSUMER_KEY")) 41 | .setOAuthConsumerSecret( 42 | System.getenv("TWITTER_CONSUMER_SERVICE")) 43 | .setOAuthAccessToken( 44 | System.getenv("TWITTER_OAUTH_ACCESS_TOKEN")) 45 | .setOAuthAccessTokenSecret( 46 | System.getenv("TWITTER_OAUTH_ACCESS_TOKEN_SECRET")); 47 | TwitterFactory tf = new TwitterFactory(cb.build()); 48 | Twitter twitter = tf.getInstance(); 49 | 50 | Query query = new Query(name); 51 | QueryResult result; 52 | do { 53 | result = twitter.search(query); 54 | List tweets = result.getTweets(); 55 | for (twitter4j.Status tweet : tweets) { 56 | System.out.println("@" + tweet.getUser().getScreenName() + " - " + tweet.getText()); 57 | tweetsFromUser.add(tweet.getText()); 58 | } 59 | } while ((query = result.nextQuery()) != null); 60 | 61 | } catch (TwitterException te) { 62 | te.printStackTrace(); 63 | tweetsFromUser.add("Exception occurred..!!!"); 64 | } 65 | 66 | u.setTweets(tweetsFromUser); 67 | return Response.ok().entity(u).header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT").allow("OPTIONS").build(); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /java-twitter-feed-api/src/main/java/com/example/User.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import java.util.List; 4 | 5 | import javax.xml.bind.annotation.XmlAccessType; 6 | import javax.xml.bind.annotation.XmlAccessorType; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | @XmlRootElement 10 | @XmlAccessorType(XmlAccessType.FIELD) 11 | public class User { 12 | 13 | private List tweets; 14 | 15 | public List getTweets() { 16 | return tweets; 17 | } 18 | 19 | public void setTweets(List tweets) { 20 | this.tweets = tweets; 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /java-twitter-feed-api/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Jersey Web Application 7 | org.glassfish.jersey.servlet.ServletContainer 8 | 9 | jersey.config.server.provider.packages 10 | com.example 11 | 12 | 1 13 | 14 | 15 | Jersey Web Application 16 | /api/* 17 | 18 | 19 | -------------------------------------------------------------------------------- /java-twitter-feed-api/src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Jersey RESTful Web Application!

4 |

Jersey resource 5 |

Visit Project Jersey website 6 | for more information on Jersey! 7 | 8 | 9 | -------------------------------------------------------------------------------- /nodejs-mongodb-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "Template", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "name": "nodejs-mongodb-template", 6 | "selfLink": "/oapi/v1/namespaces/openshift/templates/nodejs-mongodb-example", 7 | "uid": "1dae6cc1-b481-11e5-8b8e-fa163e38132c", 8 | "resourceVersion": "1209695", 9 | "creationTimestamp": "2016-01-06T14:23:54Z", 10 | "annotations": { 11 | "description": "An example Node.js application with a MongoDB database", 12 | "iconClass": "icon-nodejs", 13 | "tags": "instant-app,nodejs,mongodb" 14 | } 15 | }, 16 | "objects": [ 17 | { 18 | "kind": "Service", 19 | "apiVersion": "v1", 20 | "metadata": { 21 | "name": "${APPLICATION_NAME}", 22 | "annotations": { 23 | "description": "Exposes and load balances the application pods" 24 | } 25 | }, 26 | "spec": { 27 | "ports": [ 28 | { 29 | "name": "web", 30 | "port": 8080, 31 | "targetPort": 8080 32 | } 33 | ], 34 | "selector": { 35 | "name": "${APPLICATION_NAME}" 36 | } 37 | } 38 | }, 39 | { 40 | "kind": "Route", 41 | "apiVersion": "v1", 42 | "metadata": { 43 | "name": "${APPLICATION_NAME}" 44 | }, 45 | "spec": { 46 | "host": "${APPLICATION_DOMAIN}", 47 | "to": { 48 | "kind": "Service", 49 | "name": "${APPLICATION_NAME}" 50 | } 51 | } 52 | }, 53 | { 54 | "kind": "ImageStream", 55 | "apiVersion": "v1", 56 | "metadata": { 57 | "name": "${APPLICATION_NAME}", 58 | "annotations": { 59 | "description": "Keeps track of changes in the application image" 60 | } 61 | } 62 | }, 63 | { 64 | "kind": "BuildConfig", 65 | "apiVersion": "v1", 66 | "metadata": { 67 | "name": "${APPLICATION_NAME}", 68 | "annotations": { 69 | "description": "Defines how to build the application" 70 | } 71 | }, 72 | "spec": { 73 | "source": { 74 | "type": "Git", 75 | "git": { 76 | "uri": "${SOURCE_REPOSITORY_URL}", 77 | "ref": "${SOURCE_REPOSITORY_REF}" 78 | }, 79 | "contextDir": "${CONTEXT_DIR}" 80 | }, 81 | "strategy": { 82 | "type": "Source", 83 | "sourceStrategy": { 84 | "from": { 85 | "kind": "ImageStreamTag", 86 | "namespace": "openshift", 87 | "name": "nodejs:0.10" 88 | } 89 | } 90 | }, 91 | "output": { 92 | "to": { 93 | "kind": "ImageStreamTag", 94 | "name": "${APPLICATION_NAME}:latest" 95 | } 96 | }, 97 | "triggers": [ 98 | { 99 | "type": "ImageChange" 100 | }, 101 | { 102 | "type": "ConfigChange" 103 | }, 104 | { 105 | "type": "GitHub", 106 | "github": { 107 | "secret": "${GITHUB_WEBHOOK_SECRET}" 108 | } 109 | }, 110 | { 111 | "type": "Generic", 112 | "generic": { 113 | "secret": "${GENERIC_WEBHOOK_SECRET}" 114 | } 115 | } 116 | ] 117 | } 118 | }, 119 | { 120 | "kind": "DeploymentConfig", 121 | "apiVersion": "v1", 122 | "metadata": { 123 | "name": "${APPLICATION_NAME}", 124 | "annotations": { 125 | "description": "Defines how to deploy the application server" 126 | } 127 | }, 128 | "spec": { 129 | "strategy": { 130 | "type": "Rolling" 131 | }, 132 | "triggers": [ 133 | { 134 | "type": "ImageChange", 135 | "imageChangeParams": { 136 | "automatic": true, 137 | "containerNames": [ 138 | "${APPLICATION_NAME}" 139 | ], 140 | "from": { 141 | "kind": "ImageStreamTag", 142 | "name": "${APPLICATION_NAME}:latest" 143 | } 144 | } 145 | }, 146 | { 147 | "type": "ConfigChange" 148 | } 149 | ], 150 | "replicas": 1, 151 | "selector": { 152 | "name": "${APPLICATION_NAME}" 153 | }, 154 | "template": { 155 | "metadata": { 156 | "name": "${APPLICATION_NAME}", 157 | "labels": { 158 | "name": "${APPLICATION_NAME}" 159 | } 160 | }, 161 | "spec": { 162 | "containers": [ 163 | { 164 | "name": "${APPLICATION_NAME}", 165 | "image": "${APPLICATION_NAME}", 166 | "ports": [ 167 | { 168 | "containerPort": 8080 169 | } 170 | ], 171 | "env": [ 172 | { 173 | "name": "DATABASE_SERVICE_NAME", 174 | "value": "${DATABASE_SERVICE_NAME}" 175 | }, 176 | { 177 | "name": "MONGODB_USER", 178 | "value": "${DATABASE_USER}" 179 | }, 180 | { 181 | "name": "MONGODB_PASSWORD", 182 | "value": "${DATABASE_PASSWORD}" 183 | }, 184 | { 185 | "name": "MONGODB_DATABASE", 186 | "value": "${DATABASE_NAME}" 187 | }, 188 | { 189 | "name": "MONGODB_ADMIN_PASSWORD", 190 | "value": "${DATABASE_ADMIN_PASSWORD}" 191 | }, 192 | { 193 | "name": "EMAIL_APPLICATION_DOMAIN", 194 | "value": "${EMAIL_APPLICATION_DOMAIN}" 195 | } 196 | ] 197 | } 198 | ] 199 | } 200 | } 201 | } 202 | }, 203 | { 204 | "kind": "Service", 205 | "apiVersion": "v1", 206 | "metadata": { 207 | "name": "${DATABASE_SERVICE_NAME}", 208 | "annotations": { 209 | "description": "Exposes the database server" 210 | } 211 | }, 212 | "spec": { 213 | "ports": [ 214 | { 215 | "name": "mongodb", 216 | "port": 27017, 217 | "targetPort": 27017 218 | } 219 | ], 220 | "selector": { 221 | "name": "${DATABASE_SERVICE_NAME}" 222 | } 223 | } 224 | }, 225 | { 226 | "kind": "DeploymentConfig", 227 | "apiVersion": "v1", 228 | "metadata": { 229 | "name": "${DATABASE_SERVICE_NAME}", 230 | "annotations": { 231 | "description": "Defines how to deploy the database" 232 | } 233 | }, 234 | "spec": { 235 | "strategy": { 236 | "type": "Recreate" 237 | }, 238 | "triggers": [ 239 | { 240 | "type": "ImageChange", 241 | "imageChangeParams": { 242 | "automatic": false, 243 | "containerNames": [ 244 | "mongodb" 245 | ], 246 | "from": { 247 | "kind": "ImageStreamTag", 248 | "namespace": "openshift", 249 | "name": "mongodb:2.6" 250 | } 251 | } 252 | }, 253 | { 254 | "type": "ConfigChange" 255 | } 256 | ], 257 | "replicas": 1, 258 | "selector": { 259 | "name": "${DATABASE_SERVICE_NAME}" 260 | }, 261 | "template": { 262 | "metadata": { 263 | "name": "${DATABASE_SERVICE_NAME}", 264 | "labels": { 265 | "name": "${DATABASE_SERVICE_NAME}" 266 | } 267 | }, 268 | "spec": { 269 | "containers": [ 270 | { 271 | "name": "mongodb", 272 | "image": "mongodb", 273 | "ports": [ 274 | { 275 | "containerPort": 27017 276 | } 277 | ], 278 | "env": [ 279 | { 280 | "name": "MONGODB_USER", 281 | "value": "${DATABASE_USER}" 282 | }, 283 | { 284 | "name": "MONGODB_PASSWORD", 285 | "value": "${DATABASE_PASSWORD}" 286 | }, 287 | { 288 | "name": "MONGODB_DATABASE", 289 | "value": "${DATABASE_NAME}" 290 | }, 291 | { 292 | "name": "MONGODB_ADMIN_PASSWORD", 293 | "value": "${DATABASE_ADMIN_PASSWORD}" 294 | } 295 | ] 296 | } 297 | ] 298 | } 299 | } 300 | } 301 | } 302 | ], 303 | "parameters": [ 304 | { 305 | "name": "APPLICATION_NAME", 306 | "description": "Application Name", 307 | "value": "nodejs-mongodb-example" 308 | }, 309 | { 310 | "name": "SOURCE_REPOSITORY_URL", 311 | "description": "The URL of the repository with your application source code", 312 | "value": "https://github.com/openshift/nodejs-ex.git" 313 | }, 314 | { 315 | "name": "SOURCE_REPOSITORY_REF", 316 | "description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch" 317 | }, 318 | { 319 | "name": "CONTEXT_DIR", 320 | "description": "Set this to the relative path to your project if it is not in the root of your repository" 321 | }, 322 | { 323 | "name": "APPLICATION_DOMAIN", 324 | "description": "The exposed hostname that will route to the Node.js service, if left blank a value will be defaulted." 325 | }, 326 | { 327 | "name": "GITHUB_WEBHOOK_SECRET", 328 | "description": "A secret string used to configure the GitHub webhook", 329 | "generate": "expression", 330 | "from": "[a-zA-Z0-9]{40}" 331 | }, 332 | { 333 | "name": "GENERIC_WEBHOOK_SECRET", 334 | "description": "A secret string used to configure the Generic webhook", 335 | "generate": "expression", 336 | "from": "[a-zA-Z0-9]{40}" 337 | }, 338 | { 339 | "name": "DATABASE_SERVICE_NAME", 340 | "description": "Database service name", 341 | "value": "mongodb" 342 | }, 343 | { 344 | "name": "DATABASE_USER", 345 | "description": "Username for MongoDB user that will be used for accessing the database", 346 | "generate": "expression", 347 | "from": "user[A-Z0-9]{3}" 348 | }, 349 | { 350 | "name": "DATABASE_PASSWORD", 351 | "description": "Password for the MongoDB user", 352 | "generate": "expression", 353 | "from": "[a-zA-Z0-9]{16}" 354 | }, 355 | { 356 | "name": "DATABASE_NAME", 357 | "description": "Database name", 358 | "value": "sampledb" 359 | }, 360 | { 361 | "name": "DATABASE_ADMIN_PASSWORD", 362 | "description": "Password for the database admin user", 363 | "generate": "expression", 364 | "from": "[a-zA-Z0-9]{16}" 365 | }, 366 | { 367 | "name": "EMAIL_APPLICATION_DOMAIN", 368 | "description": "Email Service or email url", 369 | "value": "http://emailsvc:8080" 370 | } 371 | ], 372 | "labels": { 373 | "template": "nodejs-mongodb-template" 374 | } 375 | } 376 | -------------------------------------------------------------------------------- /nodejs-users-api/app/models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require('mongoose'); 2 | var Schema = mongoose.Schema; 3 | 4 | // set up a mongoose model 5 | module.exports = mongoose.model('User', new Schema({ 6 | username: String, 7 | email: String, 8 | password: String, 9 | cpassword: String, 10 | twitterId: String, 11 | admin: Boolean 12 | })); 13 | -------------------------------------------------------------------------------- /nodejs-users-api/config.js: -------------------------------------------------------------------------------- 1 | var mongoServiceName = process.env.DATABASE_SERVICE_NAME.toUpperCase(); 2 | var mongoHost = process.env[mongoServiceName + "_SERVICE_HOST"]; 3 | var mongoPort = process.env[mongoServiceName + "_SERVICE_PORT"]; 4 | console.log("mongohost:port ="+mongoHost+":"+mongoPort); 5 | module.exports = { 6 | 'secret': 'saregama', 7 | //'database':'mongodb://localhost/demo' 8 | //'database': 'mongodb://'+process.env.MONGODB_USER+':'+process.env.MONGODB_PASSWORD+'@'+process.env.MONGODB_SERVICE_HOST+':27017/'+process.env.MONGODB_DATABASE 9 | 'database': 'mongodb://'+process.env.MONGODB_USER+':'+process.env.MONGODB_PASSWORD+'@'+mongoHost+':'+mongoPort+'/'+process.env.MONGODB_DATABASE 10 | }; 11 | -------------------------------------------------------------------------------- /nodejs-users-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-users-api", 3 | "main": "server.js", 4 | "dependencies": { 5 | "body-parser": "^1.15.0", 6 | "cors": "^2.7.1", 7 | "express": "^4.13.4", 8 | "jsonwebtoken": "^5.7.0", 9 | "mongoose": "^4.4.5", 10 | "morgan": "^1.7.0", 11 | "request-json": "^0.5.5" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /nodejs-users-api/server.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | var express = require('express'); 6 | var app = express(); 7 | var bodyParser = require('body-parser'); 8 | var morgan = require('morgan'); 9 | var mongoose = require('mongoose'); 10 | 11 | var jwt = require('jsonwebtoken'); 12 | var config = require('./config'); 13 | var User = require('./app/models/user'); 14 | var cors = require('cors'); 15 | 16 | request = require('request-json'); 17 | 18 | var client = request.createClient(process.env.EMAIL_APPLICATION_DOMAIN); 19 | 20 | var port = process.env.PORT || 8080; 21 | mongoose.connect(config.database); 22 | app.set('superSecret', config.secret); 23 | app.use(bodyParser.urlencoded({ extended: false })); 24 | app.use(bodyParser.json()); 25 | 26 | 27 | app.use(morgan('dev')); 28 | 29 | app.use(cors()); 30 | 31 | 32 | 33 | app.get('/setup', function(req, res) { 34 | 35 | 36 | var nick = new User({ 37 | username: 'demo', 38 | password: 'demo', 39 | admin: true 40 | }); 41 | nick.save(function(err) { 42 | if (err) throw err; 43 | console.log('User saved successfully'); 44 | res.json({ success: true }); 45 | }); 46 | }); 47 | 48 | 49 | app.get('/', function(req, res) { 50 | res.send('API Works!'); 51 | }); 52 | 53 | var apiRoutes = express.Router(); 54 | 55 | 56 | apiRoutes.post('/authenticate', function(req, res) { 57 | 58 | // find the user 59 | User.findOne({ 60 | username: req.body.username, 61 | password: req.body.password 62 | }, function(err, user) { 63 | 64 | if (err) throw err; 65 | 66 | if (!user) { 67 | res.json({ success: false, message: 'Authentication failed. User not found.' }); 68 | } else if (user) { 69 | 70 | // check if password matches 71 | if (user.password != req.body.password) { 72 | res.json({ success: false, message: 'Authentication failed. Wrong password.' }); 73 | } else { 74 | 75 | // if user is found and password is right 76 | // create a token 77 | var token = jwt.sign(user, app.get('superSecret'), { 78 | expiresIn: 86400 // expires in 24 hours 79 | }); 80 | 81 | res.json({ 82 | success: true, 83 | message: 'Enjoy your token!', 84 | token: token 85 | }); 86 | } 87 | 88 | } 89 | 90 | }); 91 | }); 92 | 93 | 94 | apiRoutes.use(function(req, res, next) { 95 | 96 | 97 | var token = req.body.token || req.param('token') || req.headers['x-access-token']; 98 | 99 | 100 | if (token) { 101 | 102 | 103 | jwt.verify(token, app.get('superSecret'), function(err, decoded) { 104 | if (err) { 105 | return res.json({ success: false, message: 'Failed to authenticate token.' }); 106 | } else { 107 | 108 | req.decoded = decoded; 109 | next(); 110 | } 111 | }); 112 | 113 | } else { 114 | 115 | 116 | return res.status(403).send({ 117 | success: false, 118 | message: 'No token provided.' 119 | }); 120 | 121 | } 122 | 123 | }); 124 | 125 | apiRoutes.get('/', function(req, res) { 126 | res.json({ message: 'All Good!' }); 127 | }); 128 | 129 | app.post('/users', function(req, res) { 130 | var u = req.body; 131 | console.log('userobj',u,'email=',process.env.EMAIL_APPLICATION_DOMAIN); 132 | u.admin=false; 133 | var usr = new User(u); 134 | console.log(usr); 135 | usr.save(function(err,data) { 136 | if (err) throw err; 137 | data = { 138 | msg: "Signup complete!", 139 | subject: "Registration", 140 | to: req.body.email 141 | } 142 | console.log('data',data); 143 | client.post('/email/', data, function(err, response, body) { 144 | console.log('email sent!'); 145 | }); 146 | }); 147 | res.json({ success: true }); 148 | }); 149 | 150 | apiRoutes.get('/users', function(req, res) { 151 | User.find({},{username:1,email:1,twitterId:1}, function(err, users) { 152 | res.json(users); 153 | }); 154 | }); 155 | 156 | apiRoutes.get('/check', function(req, res) { 157 | res.json(req.decoded); 158 | }); 159 | 160 | app.use('/api', apiRoutes); 161 | 162 | 163 | app.listen(port); 164 | console.log('Magic happens at http://localhost:' + port); 165 | console.log(process.ENV); 166 | -------------------------------------------------------------------------------- /nodejs-users-api/test.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var sphp = require('sphp'); 3 | 4 | var app = express(); 5 | var server = app.listen(8080); 6 | 7 | app.use(sphp.express('./')); 8 | app.use(express.static('./')); 9 | -------------------------------------------------------------------------------- /php-ui/friends.php: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
username
email
{{ friend.username }}
{{ friend.email }}
10 |
11 | -------------------------------------------------------------------------------- /php-ui/hack.php: -------------------------------------------------------------------------------- 1 | "; 11 | $rs = $connection->query($query); 12 | while ($row = mysqli_fetch_assoc($rs)) { 13 | echo "From Address: ".$row['from_add'] . "To Address: " . $row['to_add'] . "Subject: " . $row['subject'] ."When: ".$row['created_at'] . "
"; 14 | } 15 | echo "End of the list
"; 16 | mysqli_close($connection); 17 | ?> 18 | -------------------------------------------------------------------------------- /php-ui/head.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Login and Register Demo V2 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /php-ui/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 |
8 |
9 |
10 | 61 |
62 |
63 |
64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /php-ui/login.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | 7 |
8 |
9 | 10 | 11 |
12 |
13 |
14 |
15 | 16 |
17 |
18 |
19 | 20 | Auth Token: 21 |
22 | 23 |
24 |
25 | 26 |
27 |
28 |
-------------------------------------------------------------------------------- /php-ui/profile.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /php-ui/register.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | 7 |
8 |
9 | 10 |
11 |
12 | 13 |
14 |
15 | 16 |
17 |
18 |
19 |
20 | 21 |
22 |
23 |
24 |
-------------------------------------------------------------------------------- /php-ui/script.js: -------------------------------------------------------------------------------- 1 | /* Dummy comments */ 2 | var app = angular.module('myApp', []); 3 | app.controller('appController', function($scope,$http) { 4 | $scope.currentPage='register'; 5 | $scope.friends=[]; 6 | $scope.form={ 7 | username:'foobar', 8 | password:'foobar', 9 | cpassword:'foobar', 10 | email:'foobar@gmail.com', 11 | fname:'foo', 12 | lname:'bar' 13 | }; 14 | $scope.loginform={ 15 | username:'foobar', 16 | password:'foobar' 17 | }; 18 | $scope.userTarget=document.getElementById('hdnUserRegSvc').value; 19 | $scope.twitterTarget=document.getElementById('hdnTwitterSvc').value; 20 | $scope.$watch('currentPage',function(old,newval) { 21 | $scope.token=''; 22 | }); 23 | $scope.login = function (){ 24 | $http.post($scope.userTarget+"/api/authenticate",$scope.loginform).success(function(data, status) { 25 | if(data['success']==true){ 26 | alert('Login successful, click link to get friends list.'); 27 | $scope.token=data.token; 28 | } 29 | else{ 30 | alert('username/password incorrect'); 31 | } 32 | }); 33 | }; 34 | $scope.getFriendsList=function(){ 35 | $http.get($scope.userTarget+"/api/users?token="+$scope.token).success(function(data, status) { 36 | console.log(data); 37 | $scope.friends=data; 38 | $scope.currentPage='friends'; 39 | }); 40 | }; 41 | $scope.getTweets=function(user){ 42 | $http.get($scope.twitterTarget+"/simple-service-webapp/api/tweets?name="+user).success(function(data, status) { 43 | console.log(data); 44 | $scope.tweets=data.tweets; 45 | $scope.currentPage='tweets'; 46 | }); 47 | } 48 | $scope.register = function (){ 49 | $http.post($scope.userTarget+"/users", $scope.form).success(function(data, status) { 50 | if(data['success']==true){ 51 | alert('Registration successful, please login'); 52 | $scope.currentPage='login'; 53 | } 54 | else{ 55 | alert('Error while registering, please retry') 56 | } 57 | }); 58 | }; 59 | }); 60 | -------------------------------------------------------------------------------- /php-ui/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 90px; 3 | } 4 | 5 | .panel-login { 6 | border-color: #ccc; 7 | -webkit-box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.2); 8 | -moz-box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.2); 9 | box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.2); 10 | } 11 | 12 | .panel-login>.panel-heading { 13 | color: #00415d; 14 | background-color: #fff; 15 | border-color: #fff; 16 | text-align: center; 17 | } 18 | 19 | .panel-login>.panel-heading a { 20 | text-decoration: none; 21 | color: #666; 22 | font-weight: bold; 23 | font-size: 15px; 24 | -webkit-transition: all 0.1s linear; 25 | -moz-transition: all 0.1s linear; 26 | transition: all 0.1s linear; 27 | } 28 | 29 | .panel-login>.panel-heading a.active { 30 | color: #029f5b; 31 | font-size: 18px; 32 | } 33 | 34 | .panel-login>.panel-heading hr { 35 | margin-top: 10px; 36 | margin-bottom: 0px; 37 | clear: both; 38 | border: 0; 39 | height: 1px; 40 | background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0)); 41 | background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0)); 42 | background-image: -ms-linear-gradient(left, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0)); 43 | background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0)); 44 | } 45 | 46 | .panel-login input[type="text"], 47 | .panel-login input[type="email"], 48 | .panel-login input[type="password"] { 49 | height: 45px; 50 | border: 1px solid #ddd; 51 | font-size: 16px; 52 | -webkit-transition: all 0.1s linear; 53 | -moz-transition: all 0.1s linear; 54 | transition: all 0.1s linear; 55 | } 56 | 57 | .panel-login input:hover, 58 | .panel-login input:focus { 59 | outline: none; 60 | -webkit-box-shadow: none; 61 | -moz-box-shadow: none; 62 | box-shadow: none; 63 | border-color: #ccc; 64 | } 65 | 66 | .btn-login { 67 | background-color: #59B2E0; 68 | outline: none; 69 | color: #fff; 70 | font-size: 14px; 71 | height: auto; 72 | font-weight: normal; 73 | padding: 14px 0; 74 | text-transform: uppercase; 75 | border-color: #59B2E6; 76 | } 77 | 78 | .btn-login:hover, 79 | .btn-login:focus { 80 | color: #fff; 81 | background-color: #53A3CD; 82 | border-color: #53A3CD; 83 | } 84 | 85 | .forgot-password { 86 | text-decoration: underline; 87 | color: #888; 88 | } 89 | 90 | .forgot-password:hover, 91 | .forgot-password:focus { 92 | text-decoration: underline; 93 | color: #666; 94 | } 95 | 96 | .btn-register { 97 | background-color: #1CB94E; 98 | outline: none; 99 | color: #fff; 100 | font-size: 14px; 101 | height: auto; 102 | font-weight: normal; 103 | padding: 14px 0; 104 | text-transform: uppercase; 105 | border-color: #1CB94A; 106 | } 107 | 108 | .btn-register:hover, 109 | .btn-register:focus { 110 | color: #fff; 111 | background-color: #1CA347; 112 | border-color: #1CA347; 113 | } -------------------------------------------------------------------------------- /php-ui/tweets.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 |
{{tweet | json }}
7 |
8 | -------------------------------------------------------------------------------- /python-email-api/.sti/environment: -------------------------------------------------------------------------------- 1 | PYTHONPATH2=/usr/local/lib/python2.7/site-packages 2 | -------------------------------------------------------------------------------- /python-email-api/requirements.txt: -------------------------------------------------------------------------------- 1 | email==4.0.2 2 | falcon==0.3.0 3 | gunicorn==19.4.5 4 | PyMySQL==0.7.2 5 | -------------------------------------------------------------------------------- /python-email-api/sample.py: -------------------------------------------------------------------------------- 1 | 2 | import falcon 3 | import json 4 | import smtplib 5 | import codecs 6 | import pymysql.cursors 7 | import os 8 | from datetime import datetime 9 | from datetime import timedelta 10 | 11 | 12 | 13 | class EmailResource(object): 14 | def on_get(self, req, resp): 15 | """Handles GET requests""" 16 | resp.status = falcon.HTTP_200 17 | resp.body = 'Email API 2' 18 | def on_post(self, req, resp): 19 | """Handles POST requests""" 20 | try: 21 | raw_json = req.stream.read().decode('utf-8') 22 | except Exception as ex: 23 | raise falcon.HTTPError(falcon.HTTP_400, 24 | 'Error', 25 | ex.message) 26 | 27 | try: 28 | email_req = json.loads(raw_json) 29 | except ValueError: 30 | raise falcon.HTTPError(falcon.HTTP_400, 31 | 'Malformed JSON', 32 | 'Could not decode the request body. The ' 33 | 'JSON was incorrect.') 34 | 35 | resp.status = falcon.HTTP_202 36 | server = smtplib.SMTP('smtp.gmail.com', 587) 37 | server.starttls() 38 | server.login(os.getenv('GMAIL_USERNAME', 'node2test@gmail.com'), os.getenv('GMAIL_PASSWORD', 'Refresh@2015')) 39 | msg = email_req['msg'] 40 | server.sendmail(os.getenv('GMAIL_USERNAME', 'node2test@gmail.com'), email_req['to'], msg) 41 | server.quit() 42 | config = { 43 | 'user': os.getenv('MYSQL_USER', 'root'), 44 | 'password': os.getenv('MYSQL_PASSWORD', ''), 45 | 'host': os.getenv('MYSQL_SERVICE_HOST', 'localhost'), 46 | 'db': os.getenv('MYSQL_DATABASE', 'microservices'), 47 | 'cursorclass': pymysql.cursors.DictCursor, 48 | } 49 | connection = pymysql.connect(**config) 50 | try: 51 | with connection.cursor() as cursor: 52 | add_email = ("INSERT INTO emails " 53 | "(from_add, to_add, subject, body, created_at) " 54 | "VALUES (%s, %s, %s, %s, %s)") 55 | 56 | data_email = (os.getenv('GMAIL_USERNAME', 'node2test@gmail.com'), email_req['to'], 'New registration',msg, datetime.now()) 57 | cursor.execute(add_email, data_email) 58 | connection.commit() 59 | #create table emails (from_add varchar(40), to_add varchar(40), subject varchar(40), body varchar(200), created_at date); 60 | finally: 61 | connection.close() 62 | resp.body = json.dumps(email_req) 63 | 64 | api = falcon.API() 65 | api.add_route('/email', EmailResource()) 66 | -------------------------------------------------------------------------------- /python-email-api/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup ( 4 | name = "sample:api", 5 | version = "0.1", 6 | description = "Example application to be deployed.", 7 | packages = find_packages(), 8 | install_requires = ["gunicorn"], 9 | ) 10 | --------------------------------------------------------------------------------