diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..55180a1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM nginx:1.17.1-alpine +COPY nginx.conf /etc/nginx/nginx.conf +COPY /dist /usr/share/nginx/html +RUN apk --no-cache add curl diff --git a/Dockerfile.apache b/Dockerfile.apache new file mode 100644 index 0000000..817f509 --- /dev/null +++ b/Dockerfile.apache @@ -0,0 +1,3 @@ +FROM httpd:2.4 +COPY /dist /usr/local/apache2/htdocs/ +COPY httpd.conf /usr/local/apache2/conf/httpd.conf \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b57af10 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# first-angular-app +Sample application to demo a Angular container app \ No newline at end of file diff --git a/first-angular-deployment.yaml b/first-angular-deployment.yaml new file mode 100644 index 0000000..e9bbeeb --- /dev/null +++ b/first-angular-deployment.yaml @@ -0,0 +1,21 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: firstangular-deployment + labels: + app: firstangular-app +spec: + replicas: 1 + selector: + matchLabels: + app: firstangular-app + template: + metadata: + labels: + app: firstangular-app + spec: + containers: + - name: firstappangular-container + image: pcsathish1/first-angular-app:3.0 + ports: + - containerPort: 80 diff --git a/first-angular-svc.yaml b/first-angular-svc.yaml new file mode 100644 index 0000000..2451678 --- /dev/null +++ b/first-angular-svc.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: firstangular-service + labels: + app: firstangular-app +spec: + type: LoadBalancer + selector: + app: firstangular-app + ports: + - protocol: TCP + port: 80 + targetPort: 80 diff --git a/httpd.conf b/httpd.conf new file mode 100644 index 0000000..734c4c5 --- /dev/null +++ b/httpd.conf @@ -0,0 +1,64 @@ +# Apache httpd v2.4 minimal configuration +# This can be reduced further if you remove the accees log and mod_log_config +ServerRoot "/usr/local/apache2" + +# Minimum modules needed +LoadModule mpm_event_module modules/mod_mpm_event.so +LoadModule log_config_module modules/mod_log_config.so +LoadModule mime_module modules/mod_mime.so +LoadModule dir_module modules/mod_dir.so +LoadModule authz_core_module modules/mod_authz_core.so +LoadModule unixd_module modules/mod_unixd.so +LoadModule proxy_module modules/mod_proxy.so +LoadModule proxy_http_module modules/mod_proxy_http.so + +TypesConfig conf/mime.types + +PidFile logs/httpd.pid + +# Comment this out if running httpd as a non root user +User nobody + +# Port to Listen on +Listen *:80 + +# In a basic setup httpd can only serve files from its document root +DocumentRoot "/usr/local/apache2/htdocs/" + + + + + ProxyPreserveHost On + + # Servers to proxy the connection, or; + # List of application servers: + # Usage: + # ProxyPass / http://[IP Addr.]:[port]/ + # ProxyPassReverse / http://[IP Addr.]:[port]/ + # Example: + ProxyPass /api http://localhost:8080/locations/ + ProxyPassReverse /api http://localhost:8080/locations/ + + ServerName localhost + + +# Default file to serve +DirectoryIndex index.html + +# Errors go to their own log +ErrorLog logs/error_log + +# Access log +LogFormat "%h %l %u %t \"%r\" %>s %b" common +CustomLog logs/access_log common + +# Never change this block + + AllowOverride None + Require all denied + + +# Allow documents to be served from the DocumentRoot + + Require all granted + \ No newline at end of file diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..dd212cb --- /dev/null +++ b/nginx.conf @@ -0,0 +1,24 @@ +events{} +http { + include /etc/nginx/mime.types; + # The identifier Backend is internal to nginx, and used to name this specific upstream + upstream Backend { + # springboot-service is the internal DNS name used by the backend Service inside Kubernetes + server springboot-service:8080; + #server 192.168.1.7:8080; + # server 127.0.0.1:8080 max_fails=1 fail_timeout=1s; + # server 127.0.0.1:8080 max_fails=1 fail_timeout=1s; + } + server { + listen 80; + server_name localhost; + root /usr/share/nginx/html; + index index.html; + location / { + try_files $uri $uri/ /index.html; + } + location /api/locations { + proxy_pass http://Backend/locations; + } + } +} \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 677712d..301a9a9 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,17 +1,10 @@ import { Component } from '@angular/core'; -import { HomeComponent } from './home/home.component'; -import { RouterLink, RouterOutlet } from '@angular/router'; @Component({ selector: 'app-root', - standalone: true, - imports: [ - HomeComponent, - RouterLink, - RouterOutlet, - ], template: `
+
@@ -20,6 +13,7 @@ import { RouterLink, RouterOutlet } from '@angular/router';
+
`, styleUrls: ['./app.component.css'], diff --git a/src/app/app.module.ts b/src/app/app.module.ts new file mode 100644 index 0000000..d0b2511 --- /dev/null +++ b/src/app/app.module.ts @@ -0,0 +1,31 @@ +import { NgModule } from "@angular/core"; +import { HomeComponent } from "./home/home.component"; +import { RouterLink, RouterOutlet } from "@angular/router"; +import { AppComponent } from "./app.component"; +import { LogTestComponent } from "./shared/log-test/log-test.component"; +import { BrowserModule } from "@angular/platform-browser"; +import { AppRoutingModule } from "./app.routing.module"; +import { HousingLocationComponent } from "./housing-location/housing-location.component"; +import { LogService } from "./shared/log.service"; + + + +@NgModule({ + imports: [ + BrowserModule, + AppRoutingModule, + ], + declarations: [ + AppComponent, HomeComponent, HousingLocationComponent, LogTestComponent + ], + providers: [LogService], + bootstrap: [ AppComponent ] +}) +export class AppModule { } + + +/* +Copyright Google LLC. All Rights Reserved. +Use of this source code is governed by an MIT-style license that +can be found in the LICENSE file at https://angular.io/license +*/ \ No newline at end of file diff --git a/src/app/app.routing.module.ts b/src/app/app.routing.module.ts new file mode 100644 index 0000000..d6f0e3d --- /dev/null +++ b/src/app/app.routing.module.ts @@ -0,0 +1,31 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { HomeComponent } from './home/home.component'; +import { DetailsComponent } from './details/details.component'; + +const routeConfig: Routes = [ + { + path: '', + component: HomeComponent, + title: 'Home page' + }, + { + path: 'details/:id', + component: DetailsComponent, + title: 'Home details' + } + ]; + + +@NgModule({ + imports: [ RouterModule.forRoot(routeConfig) ], + exports: [ RouterModule ] +}) +export class AppRoutingModule {} + + +/* +Copyright Google LLC. All Rights Reserved. +Use of this source code is governed by an MIT-style license that +can be found in the LICENSE file at https://angular.io/license +*/ \ No newline at end of file diff --git a/src/app/details/details.component.ts b/src/app/details/details.component.ts index 41c013f..9e271d3 100644 --- a/src/app/details/details.component.ts +++ b/src/app/details/details.component.ts @@ -60,6 +60,7 @@ export class DetailsComponent { constructor() { const housingLocationId = parseInt(this.route.snapshot.params['id'], 10); + console.log ("houseing location id"+housingLocationId); this.housingService.getHousingLocationById(housingLocationId).then(housingLocation => { this.housingLocation = housingLocation; }); diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index 208ce80..55084ee 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -6,11 +6,6 @@ import { HousingService } from '../housing.service'; @Component({ selector: 'app-home', - standalone: true, - imports: [ - CommonModule, - HousingLocationComponent - ], template: `
diff --git a/src/app/housing-location/housing-location.component.ts b/src/app/housing-location/housing-location.component.ts index 0834923..1f014af 100644 --- a/src/app/housing-location/housing-location.component.ts +++ b/src/app/housing-location/housing-location.component.ts @@ -5,11 +5,6 @@ import { RouterModule } from '@angular/router'; @Component({ selector: 'app-housing-location', - standalone: true, - imports: [ - CommonModule, - RouterModule - ], template: `
Exterior photo of {{housingLocation.name}} @@ -17,6 +12,7 @@ import { RouterModule } from '@angular/router';

{{ housingLocation.city}}, {{housingLocation.state }}

Learn More
+ `, styleUrls: ['./housing-location.component.css'], }) diff --git a/src/app/housing.service.ts b/src/app/housing.service.ts index 9ed2554..214e852 100644 --- a/src/app/housing.service.ts +++ b/src/app/housing.service.ts @@ -1,24 +1,30 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HousingLocation } from './housinglocation'; +import { LogService } from './shared/log.service'; @Injectable({ providedIn: 'root' }) export class HousingService { - url = 'http://localhost:8080/location'; + url = 'api/locations'; + //url = 'http://localhost:8080/locations'; + + logger: LogService = inject(LogService); async getAllHousingLocations(): Promise { + this.logger.log("URL to get data", this.url); const data = await fetch(this.url); return await data.json() ?? []; } async getHousingLocationById(id: number): Promise { + this.logger.debug("URL to get by data by id", `${this.url}/${id}`); const data = await fetch(`${this.url}/${id}`); return await data.json() ?? {}; } submitApplication(firstName: string, lastName: string, email: string) { - console.log(firstName, lastName, email); + this.logger.log(firstName, lastName, email); } } diff --git a/src/app/shared/log-test/log-test.component.html b/src/app/shared/log-test/log-test.component.html new file mode 100644 index 0000000..3a8f126 --- /dev/null +++ b/src/app/shared/log-test/log-test.component.html @@ -0,0 +1 @@ + diff --git a/src/app/shared/log-test/log-test.component.ts b/src/app/shared/log-test/log-test.component.ts new file mode 100644 index 0000000..1b9ed22 --- /dev/null +++ b/src/app/shared/log-test/log-test.component.ts @@ -0,0 +1,15 @@ +import { Component } from "@angular/core"; +import { LogService } from '../log.service'; + +@Component({ + selector: "log-test", + templateUrl: "./log-test.component.html" +}) +export class LogTestComponent { + constructor(private logger: LogService) { + } + + testLog(): void { + this.logger.log("Test the `log()` Method"); + } +} diff --git a/src/app/shared/log.service.ts b/src/app/shared/log.service.ts new file mode 100644 index 0000000..500b7e1 --- /dev/null +++ b/src/app/shared/log.service.ts @@ -0,0 +1,106 @@ +import { Injectable } from '@angular/core'; + + +export enum LogLevel { + All = 0, + Debug = 1, + Info = 2, + Warn = 3, + Error = 4, + Fatal = 5, + Off = 6 +} + +@Injectable() +export class LogService { + level: LogLevel = LogLevel.All; + logWithDate: boolean = true; + + debug(msg: string, ...optionalParams: any[]) { + this.writeToLog(msg, LogLevel.Debug, optionalParams); + } + + info(msg: string, ...optionalParams: any[]) { + this.writeToLog(msg, LogLevel.Info, optionalParams); + } + + warn(msg: string, ...optionalParams: any[]) { + this.writeToLog(msg, LogLevel.Warn, optionalParams); + } + + error(msg: string, ...optionalParams: any[]) { + this.writeToLog(msg, LogLevel.Error, optionalParams); + } + + fatal(msg: string, ...optionalParams: any[]) { + this.writeToLog(msg, LogLevel.Fatal, optionalParams); + } + + log(msg: string, ...optionalParams: any[]) { + this.writeToLog(msg, LogLevel.All, optionalParams); + } + + private writeToLog(msg: string, level: LogLevel, params: any[]) { + if (this.shouldLog(level)) { + let entry: LogEntry = new LogEntry(); + entry.message = msg; + entry.level = level; + entry.extraInfo = params; + entry.logWithDate = this.logWithDate; + console.log(entry.buildLogString()); + } + } + + + private shouldLog(level: LogLevel): boolean { + let ret: boolean = false; + if ((level >= this.level && level !== LogLevel.Off) || this.level === LogLevel.All) { + ret = true; + } + return ret; + } + + +} + +export class LogEntry { + // Public Properties + entryDate: Date = new Date(); + message: string = ""; + level: LogLevel = LogLevel.Debug; + extraInfo: any[] = []; + logWithDate: boolean = true; + + buildLogString(): string { + let ret: string = ""; + + if (this.logWithDate) { + ret = new Date() + " - "; + } + + ret += "Type: " + LogLevel[this.level]; + ret += " - Message: " + this.message; + if (this.extraInfo.length) { + ret += " - Extra Info: " + this.formatParams(this.extraInfo); + } + + return ret; + } + + private formatParams(params: any[]): string { + let ret: string = params.join(","); + + // Is there at least one object in the array? + if (params.some(p => typeof p == "object")) { + ret = ""; + + // Build comma-delimited string + for (let item of params) { + ret += JSON.stringify(item) + ","; + } + } + + return ret; + } +} + diff --git a/src/main.ts b/src/main.ts index fe1364a..aad341e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,17 +1,14 @@ -/* -* Protractor support is deprecated in Angular. -* Protractor is used in this example for compatibility with Angular documentation tools. -*/ -import { bootstrapApplication,provideProtractorTestingSupport } from '@angular/platform-browser'; -import { AppComponent } from './app/app.component'; -import { provideRouter } from '@angular/router'; -import routeConfig from './app/routes'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.error(err)); -bootstrapApplication(AppComponent, - { - providers: [ - provideProtractorTestingSupport(), - provideRouter(routeConfig) - ] - } -).catch(err => console.error(err)); + + +/* +Copyright Google LLC. All Rights Reserved. +Use of this source code is governed by an MIT-style license that +can be found in the LICENSE file at https://angular.io/license +*/ \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index fd60dd3..516e51f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ { "compileOnSave": false, "compilerOptions": { + "strictPropertyInitialization": false, "baseUrl": "./", "outDir": "./dist/out-tsc", "forceConsistentCasingInFileNames": true,