diff --git a/ci-templates/build.yml b/ci-templates/build.yml index 79ab2b823b21de625797217f814222b4f1d3f3d6..64c988eb82981ad180d3e766ad49740d80bfe0e5 100644 --- a/ci-templates/build.yml +++ b/ci-templates/build.yml @@ -26,7 +26,7 @@ .angular_build: extends: .default stage: build - image: trion/ng-cli:13.3.7 + image: trion/ng-cli:14.2.9 script: - | if [ ! -f "./src/assets/config/theming.scss" ]; then @@ -36,7 +36,7 @@ cp ./src/assets/config/config.prod.default.json ./src/assets/config/config.prod.json fi - npm install - - ng build --configuration production --deleteOutputPath=false + - ng build --configuration production artifacts: paths: - dist/ diff --git a/ci-templates/build_unprotected.yml b/ci-templates/build_unprotected.yml index bf2678b8b766c2301b1ba1e7905cd2f46f02f3f9..55e0fdf74af304d2f1458ec01a1e509bcb94d1ba 100644 --- a/ci-templates/build_unprotected.yml +++ b/ci-templates/build_unprotected.yml @@ -20,7 +20,7 @@ .angular_build: extends: .default stage: build - image: trion/ng-cli:13.3.7 + image: trion/ng-cli:14.2.9 script: - | if [ ! -f "./src/assets/config/theming.scss" ]; then @@ -30,7 +30,7 @@ cp ./src/assets/config/config.prod.default.json ./src/assets/config/config.prod.json fi - npm install - - ng build --configuration production --deleteOutputPath=false + - ng build --configuration production artifacts: paths: - dist/ diff --git a/compose/deploy.sh b/compose/deploy.sh index d8ac5383db45435b482eb5355c904f8a5565059c..ba0cd282151b68e921f09d6633b074a0bf756051 100644 --- a/compose/deploy.sh +++ b/compose/deploy.sh @@ -43,6 +43,8 @@ updaterepo org.etsi.osl.osom updaterepo org.etsi.osl.oas updaterepo org.etsi.osl.tmf.api updaterepo org.etsi.osl.cridge +updaterepo org.etsi.osl.metrico +updaterepo org.etsi.osl.mcp.server updaterepo org.etsi.osl.tmf.web updaterepo org.etsi.osl.portal.web @@ -61,5 +63,5 @@ fi echo "Installing npm packages..." -docker run -u 0 --rm -v "$PWD":/app trion/ng-cli:13.3.7 npm install -docker run -u 0 --rm -v "$PWD":/app trion/ng-cli:13.3.7 ng build --configuration production --deleteOutputPath=false +docker run -u $(id -u) --rm -v "$PWD":/app trion/ng-cli:14.2.9 npm install +docker run -u $(id -u) --rm -v "$PWD":/app trion/ng-cli:14.2.9 ng build --configuration production diff --git a/compose/docker-compose.yaml.configure b/compose/docker-compose.yaml.configure index ce1ebc0e978326442686c2a93bd11a61b33605ed..5026f35d2509cd4ca9da16e6a5b647aa5177d58d 100644 --- a/compose/docker-compose.yaml.configure +++ b/compose/docker-compose.yaml.configure @@ -1,4 +1,3 @@ -version: '3.4' services: artemis: @@ -10,6 +9,11 @@ services: - 8161:8161 - 61616:61616 - 61613:61613 + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "3" volumes: - /var/log/activemq:/var/log/activemq networks: @@ -23,6 +27,11 @@ services: ports: - 80:80 - 443:443 + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "3" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - ./nginx/certificates:/etc/nginx/certificates @@ -44,6 +53,11 @@ services: MYSQL_ROOT_HOST: "%" ports: - "13306:3306" + logging: + driver: "json-file" + options: + max-size: "200m" + max-file: "2" volumes: - ~/mysql/data:/var/lib/mysql - ./mysql-init:/docker-entrypoint-initdb.d @@ -51,32 +65,37 @@ services: - back keycloak: - container_name: keycloak - image: quay.io/keycloak/keycloak:16.1.1 - restart: always - profiles: ["dev", "prod"] - environment: - DB_VENDOR: MYSQL - DB_ADDR: amysql - DB_DATABASE: keycloak - DB_USER: keycloak - DB_PASSWORD: password - KEYCLOAK_USER: admin - KEYCLOAK_PASSWORD: Pa55w0rd - JDBC_PARAMS: "useSSL=false" - JAVA_OPTS: "-server -Xms512m -Xmx2048m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -XX:+UseAdaptiveSizePolicy -XX:MaxMetaspaceSize=1024m -Djava.net.preferIPv4Stack=true -Djboss.as.management.blocking.timeout=3600" - KEYCLOAK_IMPORT: /tmp/realm-export.json - PROXY_ADDRESS_FORWARDING: "true" - volumes: - - ./keycloak-init:/tmp - ports: - - 8080:8080 - - 8443:8443 - depends_on: - - mysql-portal - networks: - - front - - back + container_name: keycloak + image: quay.io/keycloak/keycloak:16.1.1 + restart: always + profiles: ["dev", "prod"] + environment: + DB_VENDOR: MYSQL + DB_ADDR: amysql + DB_DATABASE: keycloak + DB_USER: keycloak + DB_PASSWORD: password + KEYCLOAK_USER: admin + KEYCLOAK_PASSWORD: Pa55w0rd + JDBC_PARAMS: "useSSL=false" + JAVA_OPTS: "-server -Xms512m -Xmx2048m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -XX:+UseAdaptiveSizePolicy -XX:MaxMetaspaceSize=1024m -Djava.net.preferIPv4Stack=true -Djboss.as.management.blocking.timeout=3600" + KEYCLOAK_IMPORT: /tmp/realm-export.json + PROXY_ADDRESS_FORWARDING: "true" + volumes: + - ./keycloak-init:/tmp + logging: + driver: "json-file" + options: + max-size: "200m" + max-file: "5" + ports: + - 8080:8080 + - 8443:8443 + depends_on: + - mysql-portal + networks: + - front + - back osportalapi: @@ -114,7 +133,7 @@ services: logging: driver: "json-file" options: - max-size: "1g" + max-size: "750m" max-file: "3" volumes: - ./repo:/root @@ -145,7 +164,7 @@ services: logging: driver: "json-file" options: - max-size: "1g" + max-size: "800m" max-file: "3" ports: - 13011:13011 @@ -170,6 +189,11 @@ services: "bugzillakey":"", "main_operations_product":"" }' + logging: + driver: "json-file" + options: + max-size: "200m" + max-file: "3" ports: - 13010:13010 networks: @@ -244,6 +268,11 @@ services: "logging.level.org.springframework" : "INFO", "logging.level.org.etsi.osl.osom" : "INFO" }' + logging: + driver: "json-file" + options: + max-size: "1g" + max-file: "3" ports: - 13100:13100 networks: @@ -340,8 +369,8 @@ services: "spring.activemq.brokerUrl": "tcp://anartemis:61616?jms.watchTopicAdvisories=false", "spring.activemq.user": "artemis", "spring.activemq.password": "artemis", - "logging.level.org.springframework" : "DEBUG", - "logging.level.org.etsi.osl.metrico" : "DEBUG" + "logging.level.org.springframework" : "INFO", + "logging.level.org.etsi.osl.metrico" : "INFO" }' logging: driver: "json-file" @@ -355,6 +384,43 @@ services: - osscapi - mysql-portal + oslmcp: + container_name: openslice-mcp + restart: always + profiles: ["prod"] + build: + context: ../../org.etsi.osl.mcp.server/ + dockerfile: Dockerfile + image: labs.etsi.org:5050/osl/code/org.etsi.osl.mcp.server:latest + environment: + SPRING_APPLICATION_JSON: '{ + "spring.datasource.url": "jdbc:mysql://amysql/osdb?createDatabaseIfNotExist=true", + "spring.datasource.username":"root", + "spring.datasource.password":"letmein", + "spring-addons.issuers[0].uri": "http://keycloak:8080/auth/realms/openslice", + "spring-addons.issuers[0].username-json-path":"$.preferred_username", + "spring-addons.issuers[0].claims[0].jsonPath":"$.realm_access.roles", + "spring-addons.issuers[0].claims[1].jsonPath":"$.resource_access.*.roles", + "spring.security.oauth2.resourceserver.jwt.issuer-uri": "http://keycloak:8080/auth/realms/openslice", + "springdoc.oAuthFlow.authorizationUrl": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/auth", + "springdoc.oAuthFlow.tokenUrl": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/token", + "springdoc.oauth.client-id" : "osapiWebClientId", + "springdoc.oauth.clientsecret" : "secret", + "spring.activemq.brokerUrl": "tcp://anartemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "logging.level.org.springframework" : "INFO" + }' + ports: + - 13015:13015 + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "2" + networks: + - front + - back portainer: container_name: portainer @@ -363,6 +429,11 @@ services: profiles: ["dev", "prod"] networks: - front + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "3" ports: - 9000:9000 volumes: @@ -385,6 +456,11 @@ services: "centrallogurl":"http://elk_ip:elk_port/index_name/_doc", "logging.level.org.springframework" : "INFO" }' + logging: + driver: "json-file" + options: + max-size: "800m" + max-file: "3" ports: - 13013:13013 networks: @@ -399,6 +475,11 @@ services: - blockdiag environment: - KROKI_BLOCKDIAG_HOST=blockdiag + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "3" ports: - "8000:8000" networks: diff --git a/kubernetes/helm/openslice/Chart.yaml b/kubernetes/helm/openslice/Chart.yaml index 8a0612ac2f0ea3b8c892ff22bfd446fba9221d44..506eb599e0f01c98092568510fa2fa7eaff9c5a3 100644 --- a/kubernetes/helm/openslice/Chart.yaml +++ b/kubernetes/helm/openslice/Chart.yaml @@ -15,9 +15,9 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 2.0.0 +version: 2.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 2024Q4 +appVersion: 2025Q2 diff --git a/kubernetes/helm/openslice/templates/kroki-ingress.yaml b/kubernetes/helm/openslice/templates/kroki-ingress.yaml index 5127bdb12296565a01db48edf23d8da25c270674..c1467645d8ef1159f30a4db93d165a20e737a367 100644 --- a/kubernetes/helm/openslice/templates/kroki-ingress.yaml +++ b/kubernetes/helm/openslice/templates/kroki-ingress.yaml @@ -10,7 +10,7 @@ metadata: nginx.ingress.kubernetes.io/rewrite-target: "/$1" name: {{ include "openslice.fullname" . }}-kroki-ingress spec: - ingressClassName: nginx + ingressClassName: {{ .Values.ingress.ingressClassName | quote }} rules: - http: paths: diff --git a/kubernetes/helm/openslice/templates/mcp-server-ingress.yaml.yaml b/kubernetes/helm/openslice/templates/mcp-server-ingress.yaml.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0c515e6a3a99a2611615397d092384d737e51745 --- /dev/null +++ b/kubernetes/helm/openslice/templates/mcp-server-ingress.yaml.yaml @@ -0,0 +1,23 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + annotations: + nginx.ingress.kubernetes.io/rewrite-target: "/$1" + name: {{ include "openslice.fullname" . }}-mcpserver-ingress +spec: + ingressClassName: {{ .Values.ingress.ingressClassName | quote }} + rules: + - http: + paths: + - pathType: ImplementationSpecific + path: "/mcpserver/(.*)" + backend: + service: + name: {{ include "openslice.fullname" . }}-mcpserver + port: + number: 13015 diff --git a/kubernetes/helm/openslice/templates/mcp-server.yaml b/kubernetes/helm/openslice/templates/mcp-server.yaml new file mode 100644 index 0000000000000000000000000000000000000000..942f9a9a170321dff7bfe69224f30655f25c15e3 --- /dev/null +++ b/kubernetes/helm/openslice/templates/mcp-server.yaml @@ -0,0 +1,76 @@ +{{- if .Values.mcpserver.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mcpserver + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-mcpserver +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mcpserver + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mcpserver + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + containers: + - name: {{ include "openslice.fullname" . }}-mcpserver + image: "{{ .Values.image.mcpserver.repository }}:{{ .Values.image.mcpserver.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.mcpserver.pullPolicy | default "Always" }} + env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.datasource.url": "jdbc:mysql://{{ include "openslice.fullname" . }}-mysql/osdb?createDatabaseIfNotExist=true", + "spring.datasource.username": "{{ .Values.oscreds.mysql.username }}", + "spring.datasource.password": "{{ .Values.oscreds.mysql.password }}", + "spring-addons.issuers[0].uri": "{{ .Values.rooturl }}/auth/realms/openslice", + "spring-addons.issuers[0].username-json-path":"$.preferred_username", + "spring-addons.issuers[0].claims[0].jsonPath":"$.realm_access.roles", + "spring-addons.issuers[0].claims[1].jsonPath":"$.resource_access.*.roles", + "spring.security.oauth2.resourceserver.jwt.issuer-uri": "{{ .Values.rooturl }}/auth/realms/openslice", + "springdoc.oAuthFlow.authorizationUrl": "{{ .Values.rooturl }}/auth/realms/openslice/protocol/openid-connect/auth", + "springdoc.oAuthFlow.tokenUrl": "{{ .Values.rooturl }}/auth/realms/openslice/protocol/openid-connect/token", + "springdoc.oauth.client-id": "osapiWebClientId", + "springdoc.oauth.clientsecret": "{{ .Values.mcpserver.springdoc.clientSecret }}", + "spring.activemq.brokerUrl": "tcp://{{ include "openslice.fullname" . }}-artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "{{ .Values.oscreds.activemq.user }}", + "spring.activemq.password": "{{ .Values.oscreds.activemq.password }}", + "logging.level.org.springframework": "{{ .Values.mcpserver.spring.logLevel | default "INFO" }}" + } + ports: + - containerPort: 13015 + resources: + {{- toYaml .Values.resources | nindent 12 }} + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mcpserver + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-mcpserver +spec: + ports: + - name: "13015" + port: 13015 + targetPort: 13015 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mcpserver + {{- include "openslice.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/kubernetes/helm/openslice/templates/openslice-ingress.yaml b/kubernetes/helm/openslice/templates/openslice-ingress.yaml index a5f731485acad1a42297e77910cf176a152cc576..365ffc7a6caeeec3d9bc76c7740e7e0090d25989 100644 --- a/kubernetes/helm/openslice/templates/openslice-ingress.yaml +++ b/kubernetes/helm/openslice/templates/openslice-ingress.yaml @@ -10,7 +10,7 @@ metadata: {{- toYaml .Values.ingress.annotations | nindent 4 }} name: {{ include "openslice.fullname" . }}-openslice-ingress spec: - ingressClassName: nginx + ingressClassName: {{ .Values.ingress.ingressClassName | quote }} rules: - http: paths: diff --git a/kubernetes/helm/openslice/values.yaml b/kubernetes/helm/openslice/values.yaml index ba45552be15c1de84c7e87548b52b0985b7b0d9a..cc86020d7d3eb3c0d9084c177ab5dc911e7e16c7 100644 --- a/kubernetes/helm/openslice/values.yaml +++ b/kubernetes/helm/openslice/values.yaml @@ -85,6 +85,11 @@ image: pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. tag: "latest" + mcpserver: + repository: labs.etsi.org:5050/osl/code/org.etsi.osl.mcp.server + # Overrides the image tag whose default is the chart appVersion. + tag: latest + pullPolicy: Always bugzillaurl: example.com:443/bugzilla bugzillakey: VH2Vw0iI5aYgALFFzVDWqhACwt6Hu3bXla9kSC1Z @@ -118,9 +123,9 @@ mysql: metrico: enabled: true - logLevel: DEBUG + logLevel: INFO spring: - loglevel: DEBUG + loglevel: INFO cridge: enabled: true @@ -154,6 +159,13 @@ osscapi: spring: loglevel: INFO +mcpserver: + enabled: true + springdoc: + clientSecret: secret + spring: + logLevel: INFO + # Storage class to be used for provisioning. Default is manual # storageClass: ~ @@ -190,6 +202,7 @@ service: port: 80 ingress: + ingressClassName: nginx paths: - path: "/tmf-api" service: "osscapi" diff --git a/pom.xml b/pom.xml index bfa0fc3e38a54253ce40a2a03ce7f78502c673d6..476803810245d5eadcb013bcd877bfcddc6e92e1 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.etsi.osl org.etsi.osl.main - 2024Q4 + 2025Q2 pom org.etsi.osl.main @@ -33,24 +33,25 @@ 1.7.0 - 1.0.1 - 1.0.1 - 1.0.1 - 1.1.0 - 2024Q4 - 1.0.1 - 1.1.0 - 1.0.1 - 1.1.0 - 1.0.1 - 1.1.0 - 1.0.1 - 1.0.1 - 1.0.1 - 1.0.1 - 1.1.0 - 1.1.0 - 0.9 + 1.0.2 + 1.0.2 + 1.0.2 + 1.2.0 + 2025Q2 + 1.0.2 + 1.1.1 + 1.1.0 + 1.2.0 + 1.0.2 + 1.2.0 + 1.1.0 + 1.0.2 + 1.0.2 + 1.0.2 + 1.2.0 + 1.2.0 + 1.0.0 + 1.0.0