Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remote-run api implementation #4022

Merged
merged 7 commits into from
Mar 24, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
remote-run api implementation
piax93 committed Mar 17, 2025

Verified

This commit was signed with the committer’s verified signature.
piax93 Matteo Piano
commit b9c36064890c9137d847edf0384f7795340b63ea
20 changes: 20 additions & 0 deletions paasta_tools/api/api.py
Original file line number Diff line number Diff line change
@@ -189,6 +189,26 @@ def make_app(global_config=None):
"/v1/service_autoscaler/pause",
request_method="GET",
)
config.add_route(
"remote_run.start",
"/v1/remote_run/{service}/{instance}/start",
request_method="POST",
)
config.add_route(
"remote_run.stop",
"/v1/remote_run/{service}/{instance}/stop",
request_method="POST",
)
config.add_route(
"remote_run.poll",
"/v1/remote_run/{service}/{instance}/poll",
request_method="GET",
)
config.add_route(
"remote_run.token",
"/v1/remote_run/{service}/{instance}/token",
request_method="GET",
)
config.add_route("version", "/v1/version")
config.add_route("deploy_queue.list", "/v1/deploy_queue")
config.scan()
107 changes: 107 additions & 0 deletions paasta_tools/api/views/remote_run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Copyright 2015-2016 Yelp Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.
import traceback

from pyramid.view import view_config

from paasta_tools.api import settings
from paasta_tools.api.views.exception import ApiFailure
from paasta_tools.kubernetes.remote_run import remote_run_ready
from paasta_tools.kubernetes.remote_run import remote_run_start
from paasta_tools.kubernetes.remote_run import remote_run_stop
from paasta_tools.kubernetes.remote_run import remote_run_token
from paasta_tools.utils import load_system_paasta_config


DEFAULT_MAX_DURATION = 60 * 60 # 1 hour
DEFAULT_MAX_DURATION_LIMIT = 8 * 60 * 60 # 8 hours


@view_config(route_name="remote_run.start", request_method="POST", renderer="json")
def view_remote_run_start(request):
system_config = load_system_paasta_config()
service = request.swagger_data["service"]
instance = request.swagger_data["instance"]
user = request.swagger_data["json_body"]["user"]
interactive = request.swagger_data["json_body"].get("interactive", True)
recreate = request.swagger_data["json_body"].get("recreate", False)
max_duration = min(
request.swagger_data["json_body"].get("max_duration", DEFAULT_MAX_DURATION),
system_config.get_remote_run_duration_limit(DEFAULT_MAX_DURATION_LIMIT),
)
try:
return remote_run_start(
service=service,
instance=instance,
cluster=settings.cluster,
user=user,
interactive=interactive,
recreate=recreate,
max_duration=max_duration,
)
except Exception:
error_message = traceback.format_exc()
raise ApiFailure(error_message, 500)


@view_config(route_name="remote_run.poll", request_method="GET", renderer="json")
def view_remote_run_poll(request):
service = request.swagger_data["service"]
instance = request.swagger_data["instance"]
job_name = request.swagger_data["job_name"]
try:
return remote_run_ready(
service=service,
instance=instance,
cluster=settings.cluster,
job_name=job_name,
)
except Exception:
error_message = traceback.format_exc()
raise ApiFailure(error_message, 500)


@view_config(route_name="remote_run.stop", request_method="POST", renderer="json")
def view_remote_run_stop(request):
service = request.swagger_data["service"]
instance = request.swagger_data["instance"]
user = request.swagger_data["json_body"]["user"]
try:
return remote_run_stop(
service=service,
instance=instance,
cluster=settings.cluster,
user=user,
)
except Exception:
error_message = traceback.format_exc()
raise ApiFailure(error_message, 500)


@view_config(route_name="remote_run.token", request_method="GET", renderer="json")
def view_remote_run_token(request):
service = request.swagger_data["service"]
instance = request.swagger_data["instance"]
user = request.swagger_data["user"]
try:
token = remote_run_token(
service=service,
instance=instance,
cluster=settings.cluster,
user=user,
)
return {"token": token}
except Exception:
error_message = traceback.format_exc()
raise ApiFailure(error_message, 500)
34 changes: 34 additions & 0 deletions paasta_tools/eks_tools.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
from typing import Optional
from typing import Union

import service_configuration_lib

from paasta_tools.kubernetes_tools import KubernetesDeploymentConfig
from paasta_tools.kubernetes_tools import KubernetesDeploymentConfigDict
from paasta_tools.kubernetes_tools import load_kubernetes_service_config_no_cache
from paasta_tools.utils import BranchDictV2
from paasta_tools.utils import deep_merge_dictionaries
from paasta_tools.utils import DEFAULT_SOA_DIR
from paasta_tools.utils import load_service_instance_config
from paasta_tools.utils import load_v2_deployments_json
from paasta_tools.utils import time_cache
from paasta_tools.utils import validate_service_instance


class EksDeploymentConfig(KubernetesDeploymentConfig):
@@ -117,3 +120,34 @@ def load_eks_service_config(
load_deployments=load_deployments,
soa_dir=soa_dir,
)


@time_cache(ttl=5)
def agnostic_load_service_config(
service: str,
instance: str,
cluster: str,
load_deployments: bool = True,
soa_dir: str = DEFAULT_SOA_DIR,
) -> Union[KubernetesDeploymentConfig, EksDeploymentConfig]:
"""Load deployment configuration for service, regardless of it being defined
to run on EKS or self-hosted Kubernetes.

:param str service: service name
:param str instance: service instance
:param str cluster: paasta cluster
:param bool load_deployments: whether the corresponding deployments.json for this service
should also be loaded
:param str soa_dir: The SOA configuration directory to read from
:return: EKS or Kubernetes deployment configuration
"""
instance_type = validate_service_instance(service, instance, cluster, soa_dir)
return (
load_eks_service_config_no_cache(
service, instance, cluster, load_deployments, soa_dir
)
if instance_type == "eks"
else load_kubernetes_service_config_no_cache(
service, instance, cluster, load_deployments, DEFAULT_SOA_DIR
)
)
Loading