def has_bcs_service(self, access_token, project_id, request_namespace): """判断是否开启容器服务 开启后就不能关闭,所以缓存很久,默认30天 """ cache_key = f"BK_DEVOPS_BCS:HAS_BCS_SERVICE:{project_id}" project = region.get(cache_key, expiration_time=3600 * 24 * 30) if not project or not isinstance(project, FancyDict): result = paas_cc.get_project(access_token, project_id) project = result.get("data") or {} # coes: container orchestration engines project['coes'] = project['kind'] try: from backend.container_service.projects.utils import get_project_kind # k8s类型包含kind为1(bcs k8s)或其它属于k8s的编排引擎 project['kind'] = get_project_kind(project['kind']) except ImportError: pass project = FancyDict(project) if request_namespace in SKIP_REQUEST_NAMESPACE: # 如果是SKIP_REQUEST_NAMESPACE,有更新接口,不判断kind if project.get("cc_app_id") != 0: region.set(cache_key, project) elif project.get("cc_app_id") != 0: region.set(cache_key, project) else: # 其他抛出没有开启容器服务 raise error_codes.NoBCSService() return project
def compose_request(access_token, username): """组装request,以便于使用auth api时使用""" return FancyDict({ 'user': FancyDict({ 'username': username, 'token': FancyDict({'access_token': access_token}) }), })
def _refine_project(self, project: FancyDict): project.coes = project.kind project.project_code = project.english_name try: from backend.container_service.projects.utils import get_project_kind # k8s类型包含kind为1(bcs k8s)或其它属于k8s的编排引擎 project.kind = get_project_kind(project.kind) except ImportError: pass
def authenticate_token(self, request, user: JWTUser): """生成有效的request.user.token.access_token""" access_token = request.META.get(constants.ACCESS_TOKEN_KEY_NAME, "") # 通过头部传入access_token if access_token: self._validate_access_token(request, access_token) user.token = FancyDict(access_token=access_token) else: # 如果客户端未传入有效access_token, 平台注入系统access_token user.token = FancyDict(access_token=get_access_token().get("access_token")) return (user, None)
def get_project_info(self, request, project_id): """获取项目信息 """ resp = paas_cc.get_project(request.user.token.access_token, project_id) if resp.get('code') != ErrorCode.NoError: raise error_codes.APIError.f(resp.get('message')) request.project = FancyDict(resp.get('data', {}))
def initial(self, request, *args, **kwargs): request.user.token = FancyDict(access_token=get_client_access_token().get("access_token")) if self.project_field_name in kwargs: return super().initial(request, *args, **kwargs) for field_name in self.available_project_field_names: self.refine_project_field(request.user.token.access_token, field_name, kwargs) return super().initial(request, *args, **kwargs)
def has_permission(self, request, view): has_perm = super().has_permission(request, view) if not has_perm: return False access_token = request.META.get(ACCESS_TOKEN_KEY_NAME, "") request.user.token = FancyDict(user_access_token=access_token) access_token = get_access_token().get("access_token") request.user.token.access_token = access_token return True
def _get_enabled_project(self, access_token, project_id_or_code: str) -> Optional[FancyDict]: from backend.tests.testing_utils.mocks.paas_cc import StubPaaSCCClient project_data = StubPaaSCCClient().get_project(project_id_or_code) project = FancyDict(**project_data) if project.cc_app_id != 0: return project return None
def get(self, project_id): domain_settings = { "SITE_STATIC_URL": settings.SITE_STATIC_URL, "DEVOPS_BCS_API_URL": remove_url_domain(settings.DEVOPS_BCS_API_URL), } data = { "settings": FancyDict(domain_settings), "project_id": project_id } self.render("templates/mgr.html", **data)
def authenticate_credentials(self, userid, password): if userid != "bk_iam": raise AuthenticationFailed("username is not bk_iam") iam = IAM(settings.APP_ID, settings.APP_TOKEN, settings.BK_IAM_HOST, settings.BK_PAAS_INNER_HOST) ok, msg, token = iam.get_token(settings.APP_ID) if not ok: raise AuthenticationFailed(f"get system token fail: {msg}") if password != token: raise AuthenticationFailed("password in basic_auth not equals to system token") return (FancyDict(username=userid, password=password), None)
def has_bcs_service(self, access_token, project_id, request_namespace): """判断是否开启容器服务 开启后就不能关闭,所以缓存很久,默认30天 """ cache_key = f'BK_DEVOPS_BCS:HAS_BCS_SERVICE:{project_id}' project = region.get(cache_key, expiration_time=3600 * 24 * 30) if not project or not isinstance(project, FancyDict): result = paas_cc.get_project(access_token, project_id) project = result.get('data') or {} project = FancyDict(project) if request_namespace in SKIP_REQUEST_NAMESPACE: # 如果是SKIP_REQUEST_NAMESPACE,有更新接口,不判断kind if project.get('cc_app_id') != 0 and project.get( 'kind') in ClusterType: region.set(cache_key, project) elif project.get('kind') in ClusterType: # 如果已经开启容器服务,判断是否cc_app_id再缓存 if project.get('cc_app_id') != 0: region.set(cache_key, project) else: # 其他抛出没有开启容器服务 raise error_codes.NoBCSService() return project
def fake_node_data(self): self.data = FancyDict( metadata=FancyDict(labels=FancyDict()), spec=FancyDict(taints=[]), status=FancyDict( addresses=[ FancyDict(address=fake_inner_ip, type="InternalIP") ], conditions=[FancyDict(status="True", type="Ready")], ), )
def get_request_user(self, request, access_token, project_id): if settings.DEBUG: app_code, username = DEFAULT_APP_CODE, DEFAULT_USER else: app_code, username = parse_jwt_info(self.jwt_info(request)) request.user = APIUser request.user.token.access_token = access_token request.user.username = DEFAULT_USER if settings.DEBUG else username request.user.app_code = app_code result = get_project(access_token, project_id) project = result.get("data") or {} project = FancyDict(project) request.project = project
def init_handler(self, request, cc_app_id, project_id): self.project_kind, self.app_code, self.project_info = check_user_project( self.data["access_token"], project_id, cc_app_id, self.jwt_info(request), is_orgin_project=True) request.user = APIUser request.user.token.access_token = self.data["access_token"] request.user.username = self.app_code request.user.project_kind = self.project_kind # 添加project信息,方便同时处理提供给apigw和前台页面使用 request.project = FancyDict(self.project_info) if request.project["kind"] != 2: raise error_codes.CheckFailed.f("现阶段只允许操作Mesos类型")
def _get_enabled_project(self, access_token, project_id_or_code: str) -> Optional[FancyDict]: cache_key = f"BK_DEVOPS_BCS:ENABLED_BCS_PROJECT:{project_id_or_code}" project = region.get(cache_key, expiration_time=EXPIRATION_TIME) if project and isinstance(project, FancyDict): return project paas_cc = PaaSCCClient(auth=ComponentAuth(access_token)) project_data = paas_cc.get_project(project_id_or_code) project = FancyDict(**project_data) self._refine_project(project) # 用户绑定了项目, 并且选择了编排类型 if project.cc_app_id != 0 and project.kind in ClusterType: region.set(cache_key, project) return project return None
def _get_enabled_project(self, access_token, project_id_or_code: str) -> Optional[FancyDict]: cache_key = bcs_project_cache_key.format( project_id_or_code=project_id_or_code) project = region.get(cache_key, expiration_time=EXPIRATION_TIME) if project and isinstance(project, FancyDict): return project paas_cc = PaaSCCClient(auth=ComponentAuth(access_token)) project_data = paas_cc.get_project(project_id_or_code) project = FancyDict(**project_data) self._refine_project(project) # 项目绑定了业务,即开启容器服务 if project.cc_app_id != 0: region.set(cache_key, project) return project return None
def has_permission(self, request, view): has_perm = super().has_permission(request, view) if not has_perm: return False access_token = request.META.get(ACCESS_TOKEN_KEY_NAME, "") if access_token: try: from backend.components.paas_auth import get_user_by_access_token except ImportError: pass else: user = get_user_by_access_token(access_token) if user.get("user_id") != request.user.username: return False request.user.token = FancyDict(access_token=access_token) return True return False
def authenticate_credentials(self, userid: str, password: str, request=None): if userid != "bk_iam": raise AuthenticationFailed("username is not bk_iam") iam = IAM( settings.APP_CODE, settings.SECRET_KEY, settings.BK_IAM_HOST, settings.BK_PAAS_INNER_HOST, settings.BK_IAM_APIGATEWAY_URL, ) ok, msg, token = iam.get_token(settings.BK_IAM_SYSTEM_ID) if not ok: raise AuthenticationFailed(f"get system token fail: {msg}") if password != token: raise AuthenticationFailed( "password in basic_auth not equals to system token") return (FancyDict(username=userid, password=password), None)
def authenticate(self, request): auth = rest_framework.authentication.get_authorization_header( request).split() if not auth or auth[0].lower() != self.keyword.lower().encode(): return None if len(auth) == 1: msg = _('Invalid token header. No credentials provided.') raise rest_framework.exceptions.AuthenticationFailed(msg) elif len(auth) > 2: msg = _( 'Invalid token header. Token string should not contain spaces.' ) raise rest_framework.exceptions.AuthenticationFailed(msg) try: token = auth[1].decode() except UnicodeError: msg = _( 'Invalid token header. Token string should not contain invalid characters.' ) raise rest_framework.exceptions.AuthenticationFailed(msg) model = self.get_model() try: token = model.objects.get(key=token) except model.DoesNotExist: msg = _('Invalid token header. Token string not reisted.') raise rest_framework.exceptions.AuthenticationFailed(msg) user = FancyDict( token=token, is_authenticated=True, username=token.username, ) return user, token
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ from unittest.mock import patch import pytest from backend.helm.app import repo from backend.tests.bcs_mocks.fake_bk_repo import FakeBkRepoMod from backend.utils import FancyDict pytestmark = pytest.mark.django_db FAKE_USER = FancyDict(username="******", token=FancyDict(access_token="access_token")) FAKE_PROJECT = FancyDict( project_id="project_id", project_code="project_code", project_name="project_name", english_name="project_code", description="this is a test", ) @patch("backend.helm.app.repo.bk_repo.BkRepoClient", new=FakeBkRepoMod) def test_get_or_create_private_repo(bk_user): detail = repo.get_or_create_private_repo(bk_user, FAKE_PROJECT) assert detail.name == FAKE_PROJECT.project_code assert detail.project_id == FAKE_PROJECT.project_id assert repo.Repository.objects.filter(
from backend.tests.testing_utils.base import generate_random_string from backend.utils import FancyDict @dataclass class NodePods: items: List[FancyDict] FAKE_POD_NAME = generate_random_string(8) FAKE_HOST_IP = generate_random_string(8) FAKE_NAMESPACE = generate_random_string(8) FAKE_PODS = NodePods( items=[ FancyDict( data=FancyDict(status=FancyDict(hostIP=FAKE_HOST_IP)), metadata={"name": FAKE_POD_NAME, "namespace": FAKE_NAMESPACE}, ) ] ) class TestPodsRescheduler: @patch("backend.resources.workloads.pod.scheduler.Pod.list", return_value=FAKE_PODS) def test_list_pods(self, ctx_cluster): # 通过节点 IP,可以过滤到 pods 的场景 pods = PodsRescheduler(ctx_cluster).list_pods_by_nodes([FAKE_HOST_IP]) assert len(pods) == 1 # 校验字段 assert pods[0]["name"] == FAKE_POD_NAME assert pods[0]["namespace"] == FAKE_NAMESPACE
def app(self): return FancyDict(self.payload.get('app') or {})
def request_user(): return FancyDict({ "username": "******", "token": FancyDict({"access_token": "test_access_token"}) })
def project(self): return FancyDict(self.payload.get('project') or {})
def test_k8s_resource_status(replicas, available, expect): resource = FancyDict() status = get_k8s_resource_status("deployment", resource, replicas, available) assert status == expect
def user(self): return FancyDict(self.payload.get('user') or {})
def test_k8s_job_status(replicas, available, completions, expect): resource = FancyDict(data=FancyDict(spec=FancyDict( completions=completions))) status = get_k8s_resource_status("job", resource, replicas, available) assert status == expect
def initial(self, request, *args, **kwargs): request.user.token = FancyDict( access_token=get_client_access_token().get("access_token")) super().initial(request, *args, **kwargs)
FAKE_PREFIX_PATH = "api/cluster_manager/proxy/" FAKE_RESPONSE = { "code": 0, "data": { "foo": "bar" }, "result": True, "message": "" } FAKE_SERVER_HOST = "http://127.0.0.2" FAKE_PROXY_CONFIG = ProxyConfig( host=FAKE_SERVER_HOST, request=FancyDict( method="GET", query_params={"test": "tet"}, path=f"{FAKE_PREFIX_PATH}/test", data={}, ), prefix_path=FAKE_PREFIX_PATH, ) class TestProxyClient: def test_get_source_url(self, requests_mock): client = ProxyClient(FAKE_PROXY_CONFIG) assert client.source_url == f"{FAKE_SERVER_HOST}/test" def test_get_proxy(self, requests_mock): requests_mock.get(ANY, json=FAKE_RESPONSE) client = ProxyClient(FAKE_PROXY_CONFIG) resp_json = client.proxy()