Skip to content

Commit

Permalink
Merge pull request #186 from DSD-DBS/staging
Browse files Browse the repository at this point in the history
Staging
  • Loading branch information
MoritzWeber0 authored Aug 16, 2022
2 parents dd7b9e3 + b8d314f commit 73073c4
Show file tree
Hide file tree
Showing 19 changed files with 363 additions and 63 deletions.
5 changes: 1 addition & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ rollout: backend frontend
undeploy:
helm uninstall --kube-context k3d-$(CLUSTER_NAME) --namespace $(NAMESPACE) $(RELEASE)
kubectl --context k3d-$(CLUSTER_NAME) delete --all deployments -n $(SESSION_NAMESPACE)
rm -f .provision-guacamole

create-cluster:
type k3d || { echo "K3D is not installed, install k3d and run 'make create-cluster' again"; exit 1; }
Expand All @@ -132,7 +131,6 @@ create-cluster:

delete-cluster:
k3d cluster list $(CLUSTER_NAME) 2>&- && k3d cluster delete $(CLUSTER_NAME)
rm -f .provision-guacamole

wait:
@echo "-----------------------------------------------------------"
Expand All @@ -146,8 +144,7 @@ wait:
kubectl wait --for=condition=Ready pods --timeout=5m --context k3d-$(CLUSTER_NAME) -n $(NAMESPACE) -l id=$(RELEASE)-deployment-guacamole-guacamole
kubectl exec --context k3d-$(CLUSTER_NAME) --namespace $(NAMESPACE) $$(kubectl get pod --namespace $(NAMESPACE) -l id=$(RELEASE)-deployment-guacamole-guacamole --no-headers | cut -f1 -d' ') -- /opt/guacamole/bin/initdb.sh --postgres | \
kubectl exec -ti --context k3d-$(CLUSTER_NAME) --namespace $(NAMESPACE) $$(kubectl get pod --namespace $(NAMESPACE) -l id=$(RELEASE)-deployment-guacamole-postgres --no-headers | cut -f1 -d' ') -- psql -U guacamole guacamole && \
echo "Guacamole database initialized sucessfully."; \
touch .provision-guacamole
echo "Guacamole database initialized sucessfully.";

# Execute with `make -j3 dev`
dev: dev-oauth-mock dev-frontend dev-backend
Expand Down
37 changes: 37 additions & 0 deletions backend/t4cclient/extensions/modelsources/git/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright DB Netz AG and the capella-collab-manager contributors
# SPDX-License-Identifier: Apache-2.0

import collections.abc as cabc
import logging
import subprocess

from fastapi import HTTPException

log = logging.getLogger(__name__)


def ls_remote(url: str, env: cabc.Mapping[str, str]) -> list[str]:
try:
proc = subprocess.run(
["git", "ls-remote", url], capture_output=True, check=True, env=env
)
except subprocess.CalledProcessError as e:
log.debug(
{
"msg": "Exit code 128 during cloning of the repository " + url,
"stdout": e.stdout,
"stderr": e.stderr,
"exitcode": e.returncode,
}
)
if e.returncode == 128:
raise HTTPException(
status_code=500,
detail={
"err_code": "no_git_model_credentials",
"reason": "There was an error accessing the model. Please ask your project lead for more information. In most cases, the credentials need to be updated.",
},
)
else:
raise e
return proc.stdout.decode().strip().splitlines()
49 changes: 47 additions & 2 deletions backend/t4cclient/extensions/modelsources/git/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,30 @@
# SPDX-License-Identifier: Apache-2.0

import base64
import logging
import os
import typing as t

from fastapi import APIRouter, Depends
from fastapi import APIRouter, Depends, HTTPException
from requests import Session

from .core import ls_remote
from t4cclient.core.authentication.database import verify_repository_role
from t4cclient.core.authentication.database.git_models import verify_gitmodel_permission
from t4cclient.core.authentication.jwt_bearer import JWTBearer
from t4cclient.core.database import get_db
from t4cclient.core.oauth.responses import AUTHENTICATION_RESPONSES
from t4cclient.extensions.modelsources import git
from t4cclient.extensions.modelsources.git.crud import get_primary_model_of_repository
from t4cclient.extensions.modelsources.git.models import (
GetRepositoryGitModel,
PatchRepositoryGitModel,
PostGitModel,
RepositoryGitInnerModel,
RepositoryGitModel,
)

router = APIRouter()
log = logging.getLogger(__name__)


@router.get(
Expand Down Expand Up @@ -105,3 +109,44 @@ def patch_model(
model=RepositoryGitInnerModel(**db_model.__dict__),
)
return None


@router.get(
"/primary/revisions", tags=["Repositories"], responses=AUTHENTICATION_RESPONSES
)
def get_revisions(
project: str, db: Session = Depends(get_db), token=Depends(JWTBearer())
):
remote_refs: dict[str, list[str]] = {"branches": [], "tags": []}

git_model = get_primary_model_of_repository(db, project)
if not git_model:
raise HTTPException(
status_code=500,
detail={
"err_code": "no_git_model",
"reason": "No git model is assigned to your project. Please ask a project lead to assign a git model.",
},
)

url = git_model.path
log.debug("Fetch revisions of git-model '%s' with url '%s'", git_model.name, url)

git_env = os.environ.copy()
git_env["GIT_USERNAME"] = git_model.username or ""
git_env["GIT_PASSWORD"] = git_model.password or ""
for ref in ls_remote(url, git_env):
(_, ref) = ref.split("\t")
if "^" in ref:
continue
if ref.startswith("refs/heads/"):
remote_refs["branches"].append(ref[len("refs/heads/") :])
elif ref.startswith("refs/tags/"):
remote_refs["tags"].append(ref[len("refs/tags/") :])

remote_refs["default"] = git_model.revision

log.debug("Determined branches: %s", remote_refs["branches"])
log.debug("Determined tags: %s", remote_refs["tags"])
log.debug("Determined default branch: %s", remote_refs["default"])
return remote_refs
4 changes: 3 additions & 1 deletion backend/t4cclient/routes/repositories/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Copyright DB Netz AG and the capella-collab-manager contributors
# SPDX-License-Identifier: Apache-2.0

import collections.abc as cabc
import importlib
import logging
import typing as t
from importlib import metadata

from fastapi import APIRouter, Depends
from fastapi import APIRouter, Depends, HTTPException
from requests import Session

import t4cclient.core.services.repositories as repository_service
Expand All @@ -21,6 +22,7 @@
from t4cclient.core.database import get_db, repositories
from t4cclient.core.database import users as database_users
from t4cclient.core.oauth.responses import AUTHENTICATION_RESPONSES
from t4cclient.extensions.modelsources.git.crud import get_primary_model_of_repository
from t4cclient.extensions.modelsources.t4c import connection
from t4cclient.schemas.repositories import (
GetRepositoryUserResponse,
Expand Down
2 changes: 2 additions & 0 deletions backend/t4cclient/sessions/operators/k8s.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def start_readonly_session(
entrypoint: str,
git_username: str,
git_password: str,
git_depth: int,
) -> t.Dict[str, t.Any]:
id = self._generate_id()

Expand All @@ -140,6 +141,7 @@ def start_readonly_session(
"GIT_URL": git_url,
"GIT_REVISION": git_revision,
"GIT_ENTRYPOINT": entrypoint,
"GIT_DEPTH": git_depth,
"RMT_PASSWORD": password,
},
)
Expand Down
27 changes: 23 additions & 4 deletions backend/t4cclient/sessions/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from t4cclient.sessions.operators import OPERATOR
from t4cclient.sessions.schema import (
AdvancedSessionResponse,
DepthType,
GetSessionsResponse,
GetSessionUsageResponse,
GuacamoleAuthentication,
Expand Down Expand Up @@ -68,7 +69,7 @@ def get_current_sessions(db: Session = Depends(get_db), token=Depends(JWTBearer(
]
]
)
)
),
)


Expand All @@ -78,7 +79,6 @@ def get_current_sessions(db: Session = Depends(get_db), token=Depends(JWTBearer(
def request_session(
body: PostSessionRequest, db: Session = Depends(get_db), token=Depends(JWTBearer())
):

rdp_password = generate_password(length=64)

owner = get_username(token)
Expand Down Expand Up @@ -139,13 +139,28 @@ def request_session(
"reason": "The Model has no connected Git Model. Please contact a project manager or admininistrator",
},
)

revision = body.branch or git_model.revision
if body.depth == DepthType.LatestCommit:
depth = 1
elif body.depth == DepthType.CompleteHistory:
depth = 0
else:
raise HTTPException(
status_code=400,
detail={
"err_code": "wrong_depth_format",
"reason": f"Depth type {depth} is not allowed.",
},
)
session = OPERATOR.start_readonly_session(
password=rdp_password,
git_url=git_model.path,
git_revision=git_model.revision,
git_revision=revision,
entrypoint=git_model.entrypoint,
git_username=git_model.username,
git_password=git_model.password,
git_depth=depth,
)

guacamole_identifier = guacamole.create_connection(
Expand All @@ -159,13 +174,17 @@ def request_session(
guacamole_token, guacamole_username, guacamole_identifier
)

body_dict = body.dict()
del body_dict["branch"]
del body_dict["depth"]

database_model = DatabaseSession(
guacamole_username=guacamole_username,
guacamole_password=guacamole_password,
rdp_password=rdp_password,
guacamole_connection_id=guacamole_identifier,
owner_name=owner,
**body.dict(),
**body_dict,
**session,
)
response = database.create_session(db=db, session=database_model).__dict__
Expand Down
7 changes: 7 additions & 0 deletions backend/t4cclient/sessions/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ class WorkspaceType(enum.Enum):
READONLY = "readonly"


class DepthType(enum.Enum):
LatestCommit = "LatestCommit"
CompleteHistory = "CompleteHistory"


class GetSessionsResponse(BaseModel):
id: str
type: WorkspaceType
Expand Down Expand Up @@ -58,6 +63,8 @@ class Config:

class PostSessionRequest(BaseModel):
type: WorkspaceType
branch: str
depth: DepthType
repository: t.Optional[str]

class Config:
Expand Down
2 changes: 1 addition & 1 deletion capella-dockerimages
21 changes: 13 additions & 8 deletions docs/user/docs/sessions/request.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
Please follow these steps to request a session:

1. Navigate to the `Workspaces` tab inside the webapplication.
2. Please select your preferred worspace type.
1. Navigate to the `Workspaces` tab inside the web application.
1. Please select your preferred worspace type.

!!! Question "Which type should I use?"
Please have a look at [Session Types](types.md)

3. Click the `Request session` button.
4. You should see the state of your request. It can take up to 2 minutes, until we can assign the required resources. In most of the cases this takes under 30 seconds.
5. You should now see a success message. Please click on `Connect to Session`.
6. The session should appear in a new tab and Capella starts automatically.
7. Please follow the instructions (depends on the workflow of your project)
1. In case of read-only sessions, you have to select a project. Then, two more fields appear where you can choose the revision (i.e. branch or tag) and either the latest commit or complete commit history of the primary model of this project. Instead of choosing a single branch, it is possible to click the checkbox to mark that all branches should be downloaded.

!!! note ""
Choosing all revisions and only the latest commit clones only the latest commits for all branches.

1. Click the `Request session` button.
1. You should see the state of your request. It can take up to 2 minutes, until the required resources can be assigned. In most of the cases this takes under 30 seconds.
1. You should now see a success message. Please click on `Connect to Session`.
1. The session should appear in a new tab and Capella starts automatically.
1. Please follow the instructions (depends on the workflow of your project)
1. [Git](flows/git.md)
2. [TeamForCapella](flows/t4c.md)
1. [TeamForCapella](flows/t4c.md)
13 changes: 8 additions & 5 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"@angular/cli": "~14.1.1",
"@angular/compiler-cli": "~14.1.1",
"@types/jasmine": "~4.0.3",
"@types/node": "^18.6.3",
"@types/node": "^18.6.5",
"jasmine-core": "~4.3.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.1.1",
Expand Down
15 changes: 7 additions & 8 deletions frontend/src/app/auth/http-interceptor/auth.interceptor.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
// Copyright DB Netz AG and the capella-collab-manager contributors
// SPDX-License-Identifier: Apache-2.0

import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpHeaders,
HttpRequest,
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { LocalStorageService } from '../local-storage/local-storage.service';
import { catchError, first, map, tap, switchMap } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { Observable, throwError } from 'rxjs';
import { catchError, first, map, switchMap } from 'rxjs/operators';
import {
AuthService,
RefreshTokenResponse,
} from 'src/app/services/auth/auth.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { LocalStorageService } from '../local-storage/local-storage.service';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
Expand Down
Loading

0 comments on commit 73073c4

Please sign in to comment.