paasta-tools 1.28.3__py3-none-any.whl → 1.30.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- paasta_tools/__init__.py +1 -1
- paasta_tools/api/api_docs/swagger.json +4 -1
- paasta_tools/api/views/remote_run.py +2 -0
- paasta_tools/cli/cmds/remote_run.py +145 -11
- paasta_tools/kubernetes/remote_run.py +49 -23
- paasta_tools/paastaapi/__init__.py +1 -1
- paasta_tools/paastaapi/api/autoscaler_api.py +1 -1
- paasta_tools/paastaapi/api/default_api.py +1 -1
- paasta_tools/paastaapi/api/remote_run_api.py +1 -1
- paasta_tools/paastaapi/api/resources_api.py +1 -1
- paasta_tools/paastaapi/api/service_api.py +1 -1
- paasta_tools/paastaapi/api_client.py +1 -1
- paasta_tools/paastaapi/configuration.py +2 -2
- paasta_tools/paastaapi/exceptions.py +1 -1
- paasta_tools/paastaapi/model/adhoc_launch_history.py +1 -1
- paasta_tools/paastaapi/model/autoscaler_count_msg.py +1 -1
- paasta_tools/paastaapi/model/autoscaling_override.py +1 -1
- paasta_tools/paastaapi/model/deploy_queue.py +1 -1
- paasta_tools/paastaapi/model/deploy_queue_service_instance.py +1 -1
- paasta_tools/paastaapi/model/envoy_backend.py +1 -1
- paasta_tools/paastaapi/model/envoy_location.py +1 -1
- paasta_tools/paastaapi/model/envoy_status.py +1 -1
- paasta_tools/paastaapi/model/flink_cluster_overview.py +1 -1
- paasta_tools/paastaapi/model/flink_config.py +1 -1
- paasta_tools/paastaapi/model/flink_job.py +1 -1
- paasta_tools/paastaapi/model/flink_job_details.py +1 -1
- paasta_tools/paastaapi/model/flink_jobs.py +1 -1
- paasta_tools/paastaapi/model/float_and_error.py +1 -1
- paasta_tools/paastaapi/model/hpa_metric.py +1 -1
- paasta_tools/paastaapi/model/inline_object.py +1 -1
- paasta_tools/paastaapi/model/inline_response200.py +1 -1
- paasta_tools/paastaapi/model/inline_response2001.py +1 -1
- paasta_tools/paastaapi/model/inline_response202.py +1 -1
- paasta_tools/paastaapi/model/inline_response403.py +1 -1
- paasta_tools/paastaapi/model/instance_bounce_status.py +1 -1
- paasta_tools/paastaapi/model/instance_mesh_status.py +1 -1
- paasta_tools/paastaapi/model/instance_status.py +1 -1
- paasta_tools/paastaapi/model/instance_status_adhoc.py +1 -1
- paasta_tools/paastaapi/model/instance_status_cassandracluster.py +1 -1
- paasta_tools/paastaapi/model/instance_status_flink.py +1 -1
- paasta_tools/paastaapi/model/instance_status_kafkacluster.py +1 -1
- paasta_tools/paastaapi/model/instance_status_kubernetes.py +1 -1
- paasta_tools/paastaapi/model/instance_status_kubernetes_autoscaling_status.py +1 -1
- paasta_tools/paastaapi/model/instance_status_kubernetes_v2.py +1 -1
- paasta_tools/paastaapi/model/instance_status_tron.py +1 -1
- paasta_tools/paastaapi/model/instance_tasks.py +1 -1
- paasta_tools/paastaapi/model/integer_and_error.py +1 -1
- paasta_tools/paastaapi/model/kubernetes_container.py +1 -1
- paasta_tools/paastaapi/model/kubernetes_container_v2.py +1 -1
- paasta_tools/paastaapi/model/kubernetes_healthcheck.py +1 -1
- paasta_tools/paastaapi/model/kubernetes_pod.py +1 -1
- paasta_tools/paastaapi/model/kubernetes_pod_event.py +1 -1
- paasta_tools/paastaapi/model/kubernetes_pod_v2.py +1 -1
- paasta_tools/paastaapi/model/kubernetes_replica_set.py +1 -1
- paasta_tools/paastaapi/model/kubernetes_version.py +1 -1
- paasta_tools/paastaapi/model/remote_run_outcome.py +1 -1
- paasta_tools/paastaapi/model/remote_run_start.py +4 -1
- paasta_tools/paastaapi/model/remote_run_stop.py +1 -1
- paasta_tools/paastaapi/model/remote_run_token.py +1 -1
- paasta_tools/paastaapi/model/resource.py +1 -1
- paasta_tools/paastaapi/model/resource_item.py +1 -1
- paasta_tools/paastaapi/model/resource_value.py +1 -1
- paasta_tools/paastaapi/model/smartstack_backend.py +1 -1
- paasta_tools/paastaapi/model/smartstack_location.py +1 -1
- paasta_tools/paastaapi/model/smartstack_status.py +1 -1
- paasta_tools/paastaapi/model/task_tail_lines.py +1 -1
- paasta_tools/paastaapi/model_utils.py +1 -1
- paasta_tools/paastaapi/rest.py +1 -1
- {paasta_tools-1.28.3.dist-info → paasta_tools-1.30.0.dist-info}/METADATA +1 -1
- {paasta_tools-1.28.3.dist-info → paasta_tools-1.30.0.dist-info}/RECORD +126 -126
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/apply_external_resources.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/bounce_log_latency_parser.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/check_autoscaler_max_instances.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/check_cassandracluster_services_replication.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/check_flink_services_health.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/check_kubernetes_api.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/check_kubernetes_services_replication.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/check_manual_oapi_changes.sh +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/check_oom_events.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/check_orphans.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/check_spark_jobs.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/cleanup_kubernetes_cr.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/cleanup_kubernetes_crd.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/cleanup_kubernetes_jobs.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/create_dynamodb_table.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/create_paasta_playground.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/delete_kubernetes_deployments.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/emit_allocated_cpu_metrics.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/generate_all_deployments +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/generate_authenticating_services.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/generate_deployments_for_service.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/generate_services_file.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/generate_services_yaml.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/get_running_task_allocation.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/habitat_fixer.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/ide_helper.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/is_pod_healthy_in_proxy.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/is_pod_healthy_in_smartstack.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/kill_bad_containers.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/kubernetes_remove_evicted_pods.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/mass-deploy-tag.sh +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/mock_patch_checker.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/paasta_cleanup_remote_run_resources.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/paasta_cleanup_stale_nodes.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/paasta_deploy_tron_jobs +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/paasta_execute_docker_command.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/paasta_secrets_sync.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/paasta_tabcomplete.sh +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/paasta_update_soa_memcpu.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/render_template.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/rightsizer_soaconfigs_update.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/service_shard_remove.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/service_shard_update.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/setup_istio_mesh.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/setup_kubernetes_cr.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/setup_kubernetes_crd.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/setup_kubernetes_internal_crd.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/setup_kubernetes_job.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/setup_prometheus_adapter_config.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/shared_ip_check.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/synapse_srv_namespaces_fact.py +0 -0
- {paasta_tools-1.28.3.data → paasta_tools-1.30.0.data}/scripts/timeouts_metrics_prom.py +0 -0
- {paasta_tools-1.28.3.dist-info → paasta_tools-1.30.0.dist-info}/WHEEL +0 -0
- {paasta_tools-1.28.3.dist-info → paasta_tools-1.30.0.dist-info}/entry_points.txt +0 -0
- {paasta_tools-1.28.3.dist-info → paasta_tools-1.30.0.dist-info}/licenses/LICENSE +0 -0
- {paasta_tools-1.28.3.dist-info → paasta_tools-1.30.0.dist-info}/top_level.txt +0 -0
paasta_tools/__init__.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"swagger": "2.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Paasta API",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.3.0"
|
|
6
6
|
},
|
|
7
7
|
"basePath": "/v1",
|
|
8
8
|
"schemes": [
|
|
@@ -2324,6 +2324,9 @@
|
|
|
2324
2324
|
},
|
|
2325
2325
|
"toolbox": {
|
|
2326
2326
|
"type": "boolean"
|
|
2327
|
+
},
|
|
2328
|
+
"command": {
|
|
2329
|
+
"type": "string"
|
|
2327
2330
|
}
|
|
2328
2331
|
},
|
|
2329
2332
|
"required": [
|
|
@@ -35,6 +35,7 @@ def view_remote_run_start(request):
|
|
|
35
35
|
interactive = request.swagger_data["json_body"].get("interactive", True)
|
|
36
36
|
recreate = request.swagger_data["json_body"].get("recreate", False)
|
|
37
37
|
is_toolbox = request.swagger_data["json_body"].get("toolbox", False)
|
|
38
|
+
command = request.swagger_data["json_body"].get("command", None)
|
|
38
39
|
max_duration = min(
|
|
39
40
|
request.swagger_data["json_body"].get("max_duration", DEFAULT_MAX_DURATION),
|
|
40
41
|
get_max_job_duration_limit(),
|
|
@@ -49,6 +50,7 @@ def view_remote_run_start(request):
|
|
|
49
50
|
recreate=recreate,
|
|
50
51
|
max_duration=max_duration,
|
|
51
52
|
is_toolbox=is_toolbox,
|
|
53
|
+
command=command,
|
|
52
54
|
)
|
|
53
55
|
except Exception:
|
|
54
56
|
error_message = traceback.format_exc()
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
import argparse
|
|
16
16
|
import json
|
|
17
|
+
import os
|
|
17
18
|
import shutil
|
|
18
19
|
import subprocess
|
|
19
20
|
import sys
|
|
@@ -24,6 +25,8 @@ from paasta_tools.cli.utils import get_paasta_oapi_api_clustername
|
|
|
24
25
|
from paasta_tools.cli.utils import get_paasta_oapi_client_with_auth
|
|
25
26
|
from paasta_tools.cli.utils import lazy_choices_completer
|
|
26
27
|
from paasta_tools.cli.utils import run_interactive_cli
|
|
28
|
+
from paasta_tools.kubernetes.remote_run import format_remote_run_job_name
|
|
29
|
+
from paasta_tools.kubernetes.remote_run import load_eks_or_adhoc_deployment_config
|
|
27
30
|
from paasta_tools.kubernetes.remote_run import TOOLBOX_MOCK_SERVICE
|
|
28
31
|
from paasta_tools.paastaapi.exceptions import ApiException
|
|
29
32
|
from paasta_tools.paastaapi.model.remote_run_start import RemoteRunStart
|
|
@@ -39,8 +42,14 @@ from paasta_tools.utils import SystemPaastaConfig
|
|
|
39
42
|
KUBECTL_EXEC_CMD_TEMPLATE = (
|
|
40
43
|
"{kubectl_wrapper} --token {token} exec -it -n {namespace} {pod} -- /bin/bash"
|
|
41
44
|
)
|
|
42
|
-
|
|
43
|
-
"{kubectl_wrapper} --token {token} -n {namespace} cp {
|
|
45
|
+
KUBECTL_CP_TO_CMD_TEMPLATE = (
|
|
46
|
+
"{kubectl_wrapper} --token {token} -n {namespace} cp {source} {pod}:{dest}"
|
|
47
|
+
)
|
|
48
|
+
KUBECTL_CP_FROM_CMD_TEMPLATE = (
|
|
49
|
+
"{kubectl_wrapper} --token {token} -n {namespace} cp {pod}:{source} {dest}"
|
|
50
|
+
)
|
|
51
|
+
KUBECTL_LOGS_CMD_TEMPLATE = (
|
|
52
|
+
"{kubectl_wrapper} --token {token} logs -n {namespace} -f {pod}"
|
|
44
53
|
)
|
|
45
54
|
|
|
46
55
|
|
|
@@ -59,6 +68,13 @@ def _list_services_and_toolboxes() -> List[str]:
|
|
|
59
68
|
)
|
|
60
69
|
|
|
61
70
|
|
|
71
|
+
def _get_kubectl_wrapper(cluster: str) -> str:
|
|
72
|
+
kubectl_wrapper = f"kubectl-eks-{cluster}"
|
|
73
|
+
if not shutil.which(kubectl_wrapper):
|
|
74
|
+
kubectl_wrapper = f"kubectl-{cluster}"
|
|
75
|
+
return kubectl_wrapper
|
|
76
|
+
|
|
77
|
+
|
|
62
78
|
def parse_error(body: str) -> str:
|
|
63
79
|
try:
|
|
64
80
|
body_object = json.loads(body)
|
|
@@ -71,6 +87,81 @@ def parse_error(body: str) -> str:
|
|
|
71
87
|
)
|
|
72
88
|
|
|
73
89
|
|
|
90
|
+
def paasta_remote_run_copy(
|
|
91
|
+
args: argparse.Namespace,
|
|
92
|
+
system_paasta_config: SystemPaastaConfig,
|
|
93
|
+
) -> int:
|
|
94
|
+
client = get_paasta_oapi_client_with_auth(
|
|
95
|
+
cluster=get_paasta_oapi_api_clustername(cluster=args.cluster, is_eks=True),
|
|
96
|
+
system_paasta_config=system_paasta_config,
|
|
97
|
+
)
|
|
98
|
+
if not client:
|
|
99
|
+
print("Cannot get a paasta-api client")
|
|
100
|
+
return 1
|
|
101
|
+
|
|
102
|
+
# Create the config and extract the job name
|
|
103
|
+
user = get_username()
|
|
104
|
+
deployment_config = load_eks_or_adhoc_deployment_config(
|
|
105
|
+
args.service, args.instance, args.cluster, args.is_toolbox, user
|
|
106
|
+
)
|
|
107
|
+
deployment_name = deployment_config.get_sanitised_deployment_name()
|
|
108
|
+
job_name = format_remote_run_job_name(deployment_name, user)
|
|
109
|
+
|
|
110
|
+
poll_response = client.remote_run.remote_run_poll(
|
|
111
|
+
service=args.service,
|
|
112
|
+
instance=args.instance,
|
|
113
|
+
job_name=job_name,
|
|
114
|
+
user=user,
|
|
115
|
+
toolbox=args.toolbox,
|
|
116
|
+
)
|
|
117
|
+
if poll_response.status != 200:
|
|
118
|
+
print(
|
|
119
|
+
f"Unable to find running remote-run pod: have you started one with `paasta remote-run start`?"
|
|
120
|
+
)
|
|
121
|
+
return 1
|
|
122
|
+
|
|
123
|
+
if args.to_pod:
|
|
124
|
+
# Create the toolbox copy command
|
|
125
|
+
exec_command = f"scp -A {args.copy_file_source} {poll_response.pod_address}:{args.copy_file_dest}"
|
|
126
|
+
# Pick the correct template and force /tmp/ for non-toolbox
|
|
127
|
+
kubectl_cp_template = KUBECTL_CP_TO_CMD_TEMPLATE
|
|
128
|
+
if not args.copy_file_dest.startswith("/tmp") and not args.toolbox:
|
|
129
|
+
args.copy_file_dest = os.path.join("/tmp/", args.copy_file_dest)
|
|
130
|
+
else:
|
|
131
|
+
exec_command = f"scp -A {poll_response.pod_address}:{args.copy_file_source} {args.copy_file_dest}"
|
|
132
|
+
kubectl_cp_template = KUBECTL_CP_FROM_CMD_TEMPLATE
|
|
133
|
+
|
|
134
|
+
# Kubectl cp doesnt like directories as a destination
|
|
135
|
+
if os.path.isdir(args.copy_file_dest):
|
|
136
|
+
args.copy_file_dest = os.path.join(
|
|
137
|
+
args.copy_file_dest, os.path.basename(args.copy_file_source)
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
if args.toolbox:
|
|
141
|
+
cp_command = exec_command.split(" ")
|
|
142
|
+
else:
|
|
143
|
+
token_response = client.remote_run.remote_run_token(
|
|
144
|
+
args.service, args.instance, user
|
|
145
|
+
)
|
|
146
|
+
kubectl_wrapper = _get_kubectl_wrapper(args.cluster)
|
|
147
|
+
cp_command = kubectl_cp_template.format(
|
|
148
|
+
kubectl_wrapper=kubectl_wrapper,
|
|
149
|
+
namespace=poll_response.namespace,
|
|
150
|
+
pod=poll_response.pod_name,
|
|
151
|
+
source=args.copy_file_source,
|
|
152
|
+
dest=args.copy_file_dest,
|
|
153
|
+
token=token_response.token,
|
|
154
|
+
).split(" ")
|
|
155
|
+
call = subprocess.run(cp_command, capture_output=True)
|
|
156
|
+
if call.returncode != 0:
|
|
157
|
+
print("Error copying file from remote-run pod: ", file=sys.stderr)
|
|
158
|
+
print(call.stderr.decode("utf-8"), file=sys.stderr)
|
|
159
|
+
return 1
|
|
160
|
+
print(f"{args.copy_file_source} successfully copied to {args.copy_file_dest}")
|
|
161
|
+
|
|
162
|
+
return 0
|
|
163
|
+
|
|
164
|
+
|
|
74
165
|
def paasta_remote_run_start(
|
|
75
166
|
args: argparse.Namespace,
|
|
76
167
|
system_paasta_config: SystemPaastaConfig,
|
|
@@ -84,7 +175,6 @@ def paasta_remote_run_start(
|
|
|
84
175
|
if not client:
|
|
85
176
|
print("Cannot get a paasta-api client")
|
|
86
177
|
return 1
|
|
87
|
-
|
|
88
178
|
user = get_username()
|
|
89
179
|
try:
|
|
90
180
|
start_response = client.remote_run.remote_run_start(
|
|
@@ -96,6 +186,7 @@ def paasta_remote_run_start(
|
|
|
96
186
|
recreate=args.recreate,
|
|
97
187
|
max_duration=args.max_duration,
|
|
98
188
|
toolbox=args.toolbox,
|
|
189
|
+
command=args.cmd or "",
|
|
99
190
|
),
|
|
100
191
|
)
|
|
101
192
|
except ApiException as e:
|
|
@@ -132,7 +223,7 @@ def paasta_remote_run_start(
|
|
|
132
223
|
print(f"{status_prefix}Timed out while waiting for job to start")
|
|
133
224
|
return 1
|
|
134
225
|
|
|
135
|
-
if not args.interactive
|
|
226
|
+
if not (args.interactive or args.toolbox or args.follow):
|
|
136
227
|
print("Successfully started remote-run job")
|
|
137
228
|
return 0
|
|
138
229
|
|
|
@@ -148,10 +239,10 @@ def paasta_remote_run_start(
|
|
|
148
239
|
token_response = client.remote_run.remote_run_token(
|
|
149
240
|
args.service, args.instance, user
|
|
150
241
|
)
|
|
151
|
-
kubectl_wrapper =
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
242
|
+
kubectl_wrapper = _get_kubectl_wrapper(args.cluster)
|
|
243
|
+
exec_command = (
|
|
244
|
+
KUBECTL_LOGS_CMD_TEMPLATE if args.follow else KUBECTL_EXEC_CMD_TEMPLATE
|
|
245
|
+
).format(
|
|
155
246
|
kubectl_wrapper=kubectl_wrapper,
|
|
156
247
|
namespace=poll_response.namespace,
|
|
157
248
|
pod=poll_response.pod_name,
|
|
@@ -160,11 +251,12 @@ def paasta_remote_run_start(
|
|
|
160
251
|
|
|
161
252
|
if args.copy_file:
|
|
162
253
|
for filename in args.copy_file:
|
|
163
|
-
cp_command =
|
|
254
|
+
cp_command = KUBECTL_CP_TO_CMD_TEMPLATE.format(
|
|
164
255
|
kubectl_wrapper=kubectl_wrapper,
|
|
165
256
|
namespace=poll_response.namespace,
|
|
166
257
|
pod=poll_response.pod_name,
|
|
167
|
-
|
|
258
|
+
source=filename,
|
|
259
|
+
dest=os.path.join("/tmp", filename),
|
|
168
260
|
token=token_response.token,
|
|
169
261
|
).split(" ")
|
|
170
262
|
call = subprocess.run(cp_command, capture_output=True)
|
|
@@ -249,7 +341,8 @@ def add_subparser(subparsers: argparse._SubParsersAction) -> None:
|
|
|
249
341
|
description="Starts or connects to a remote-run-job",
|
|
250
342
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
251
343
|
)
|
|
252
|
-
start_parser.
|
|
344
|
+
cmd_or_interactive = start_parser.add_mutually_exclusive_group()
|
|
345
|
+
cmd_or_interactive.add_argument(
|
|
253
346
|
"-I",
|
|
254
347
|
"--interactive",
|
|
255
348
|
help=(
|
|
@@ -259,6 +352,15 @@ def add_subparser(subparsers: argparse._SubParsersAction) -> None:
|
|
|
259
352
|
action="store_true",
|
|
260
353
|
default=False,
|
|
261
354
|
)
|
|
355
|
+
cmd_or_interactive.add_argument(
|
|
356
|
+
"-C",
|
|
357
|
+
"--cmd",
|
|
358
|
+
help=(
|
|
359
|
+
"Run container with particular command, rather than the one specified in soa-configs"
|
|
360
|
+
),
|
|
361
|
+
required=False,
|
|
362
|
+
default=None,
|
|
363
|
+
)
|
|
262
364
|
start_parser.add_argument(
|
|
263
365
|
"-m",
|
|
264
366
|
"--max-duration",
|
|
@@ -269,6 +371,13 @@ def add_subparser(subparsers: argparse._SubParsersAction) -> None:
|
|
|
269
371
|
type=int,
|
|
270
372
|
default=1800,
|
|
271
373
|
)
|
|
374
|
+
start_parser.add_argument(
|
|
375
|
+
"-f",
|
|
376
|
+
"--follow",
|
|
377
|
+
help="Attach to and follow container output",
|
|
378
|
+
action="store_true",
|
|
379
|
+
default=False,
|
|
380
|
+
)
|
|
272
381
|
start_parser.add_argument(
|
|
273
382
|
"-r",
|
|
274
383
|
"--recreate",
|
|
@@ -295,8 +404,31 @@ def add_subparser(subparsers: argparse._SubParsersAction) -> None:
|
|
|
295
404
|
description="Stop your remote-run job if it exists",
|
|
296
405
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
297
406
|
)
|
|
407
|
+
copy_parser = subparsers.add_parser(
|
|
408
|
+
"copy",
|
|
409
|
+
help="Copy a file from a running remote-run job",
|
|
410
|
+
description="Copy a file from a running remote-run job",
|
|
411
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
412
|
+
)
|
|
413
|
+
copy_parser.add_argument(
|
|
414
|
+
"copy_file_source",
|
|
415
|
+
help="Location of the file within the pod",
|
|
416
|
+
type=str,
|
|
417
|
+
)
|
|
418
|
+
copy_parser.add_argument(
|
|
419
|
+
"copy_file_dest",
|
|
420
|
+
help="Location on the local host to copy the file to",
|
|
421
|
+
type=str,
|
|
422
|
+
)
|
|
423
|
+
copy_parser.add_argument(
|
|
424
|
+
"--to-pod",
|
|
425
|
+
help="Copy a file to the pod instead of from the pod",
|
|
426
|
+
action="store_true",
|
|
427
|
+
default=False,
|
|
428
|
+
)
|
|
298
429
|
add_common_args_to_parser(start_parser)
|
|
299
430
|
add_common_args_to_parser(stop_parser)
|
|
431
|
+
add_common_args_to_parser(copy_parser)
|
|
300
432
|
remote_run_parser.set_defaults(command=paasta_remote_run)
|
|
301
433
|
|
|
302
434
|
|
|
@@ -306,4 +438,6 @@ def paasta_remote_run(args: argparse.Namespace) -> int:
|
|
|
306
438
|
return paasta_remote_run_start(args, system_paasta_config)
|
|
307
439
|
elif args.remote_run_command == "stop":
|
|
308
440
|
return paasta_remote_run_stop(args, system_paasta_config)
|
|
441
|
+
elif args.remote_run_command == "copy":
|
|
442
|
+
return paasta_remote_run_copy(args, system_paasta_config)
|
|
309
443
|
raise ValueError(f"Unsupported subcommand: {args.remote_run_command}")
|
|
@@ -44,7 +44,7 @@ from paasta_tools.kubernetes_tools import KubeClient
|
|
|
44
44
|
from paasta_tools.kubernetes_tools import limit_size_with_hash
|
|
45
45
|
from paasta_tools.kubernetes_tools import paasta_prefixed
|
|
46
46
|
from paasta_tools.utils import load_system_paasta_config
|
|
47
|
-
|
|
47
|
+
from paasta_tools.utils import NoConfigurationForServiceError
|
|
48
48
|
|
|
49
49
|
logger = logging.getLogger(__name__)
|
|
50
50
|
REMOTE_RUN_JOB_LABEL = "remote-run"
|
|
@@ -66,8 +66,8 @@ class RemoteRunOutcome(TypedDict, total=False):
|
|
|
66
66
|
namespace: str
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
def
|
|
70
|
-
|
|
69
|
+
def format_remote_run_job_name(
|
|
70
|
+
job_name: str,
|
|
71
71
|
user: str,
|
|
72
72
|
) -> str:
|
|
73
73
|
"""Format name for remote run job
|
|
@@ -76,7 +76,35 @@ def _format_remote_run_job_name(
|
|
|
76
76
|
:param str user: the user requesting the remote-run
|
|
77
77
|
:return: job name
|
|
78
78
|
"""
|
|
79
|
-
return limit_size_with_hash(f"remote-run-{user}-{
|
|
79
|
+
return limit_size_with_hash(f"remote-run-{user}-{job_name}")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def load_eks_or_adhoc_deployment_config(
|
|
83
|
+
service: str,
|
|
84
|
+
instance: str,
|
|
85
|
+
cluster: str,
|
|
86
|
+
is_toolbox: bool = False,
|
|
87
|
+
user: Optional[str] = None,
|
|
88
|
+
) -> EksDeploymentConfig:
|
|
89
|
+
assert user or not is_toolbox, "User required for toolbox deployment"
|
|
90
|
+
try:
|
|
91
|
+
deployment_config = (
|
|
92
|
+
generate_toolbox_deployment(service, cluster, user)
|
|
93
|
+
if is_toolbox
|
|
94
|
+
else load_eks_service_config(service, instance, cluster)
|
|
95
|
+
)
|
|
96
|
+
except NoConfigurationForServiceError:
|
|
97
|
+
# Perhaps they are trying to use an adhoc instance
|
|
98
|
+
deployment_config = load_adhoc_job_config(service, instance, cluster)
|
|
99
|
+
deployment_config = EksDeploymentConfig(
|
|
100
|
+
service,
|
|
101
|
+
cluster,
|
|
102
|
+
instance,
|
|
103
|
+
config_dict=deployment_config.config_dict,
|
|
104
|
+
branch_dict=deployment_config.branch_dict,
|
|
105
|
+
)
|
|
106
|
+
deployment_config.config_filename_prefix = "adhoc"
|
|
107
|
+
return deployment_config
|
|
80
108
|
|
|
81
109
|
|
|
82
110
|
def remote_run_start(
|
|
@@ -88,6 +116,7 @@ def remote_run_start(
|
|
|
88
116
|
recreate: bool,
|
|
89
117
|
max_duration: int,
|
|
90
118
|
is_toolbox: bool,
|
|
119
|
+
command: Optional[str] = None,
|
|
91
120
|
) -> RemoteRunOutcome:
|
|
92
121
|
"""Trigger remote-run job
|
|
93
122
|
|
|
@@ -99,19 +128,20 @@ def remote_run_start(
|
|
|
99
128
|
:param bool recreate: whether to recreate remote-run job if existing
|
|
100
129
|
:param int max_duration: maximum allowed duration for the remote-ruh job
|
|
101
130
|
:param bool is_toolbox: requested job is for a toolbox container
|
|
131
|
+
:param str command: command override to execute in the job container
|
|
102
132
|
:return: outcome of the operation, and resulting Kubernetes pod information
|
|
103
133
|
"""
|
|
104
134
|
kube_client = KubeClient()
|
|
105
135
|
|
|
106
136
|
# Load the service deployment settings
|
|
107
|
-
deployment_config = (
|
|
108
|
-
|
|
109
|
-
if is_toolbox
|
|
110
|
-
else load_eks_service_config(service, instance, cluster)
|
|
137
|
+
deployment_config = load_eks_or_adhoc_deployment_config(
|
|
138
|
+
service, instance, cluster, is_toolbox, user
|
|
111
139
|
)
|
|
112
140
|
|
|
113
|
-
# Set
|
|
114
|
-
if
|
|
141
|
+
# Set override command, or sleep for interactive mode
|
|
142
|
+
if command and not is_toolbox:
|
|
143
|
+
deployment_config.config_dict["cmd"] = command
|
|
144
|
+
elif interactive and not is_toolbox:
|
|
115
145
|
deployment_config.config_dict["cmd"] = f"sleep {max_duration}"
|
|
116
146
|
|
|
117
147
|
# Create the app with a new name
|
|
@@ -120,7 +150,7 @@ def remote_run_start(
|
|
|
120
150
|
deadline_seconds=max_duration,
|
|
121
151
|
keep_routable_ip=is_toolbox,
|
|
122
152
|
)
|
|
123
|
-
job_name =
|
|
153
|
+
job_name = format_remote_run_job_name(formatted_job.metadata.name, user)
|
|
124
154
|
formatted_job.metadata.name = job_name
|
|
125
155
|
app_wrapper = get_application_wrapper(formatted_job)
|
|
126
156
|
app_wrapper.soa_config = deployment_config
|
|
@@ -178,10 +208,8 @@ def remote_run_ready(
|
|
|
178
208
|
kube_client = KubeClient()
|
|
179
209
|
|
|
180
210
|
# Load the service deployment settings
|
|
181
|
-
deployment_config = (
|
|
182
|
-
|
|
183
|
-
if is_toolbox
|
|
184
|
-
else load_eks_service_config(service, instance, cluster)
|
|
211
|
+
deployment_config = load_eks_or_adhoc_deployment_config(
|
|
212
|
+
service, instance, cluster, is_toolbox, user
|
|
185
213
|
)
|
|
186
214
|
namespace = deployment_config.get_namespace()
|
|
187
215
|
|
|
@@ -225,17 +253,15 @@ def remote_run_stop(
|
|
|
225
253
|
kube_client = KubeClient()
|
|
226
254
|
|
|
227
255
|
# Load the service deployment settings
|
|
228
|
-
deployment_config = (
|
|
229
|
-
|
|
230
|
-
if is_toolbox
|
|
231
|
-
else load_eks_service_config(service, instance, cluster)
|
|
256
|
+
deployment_config = load_eks_or_adhoc_deployment_config(
|
|
257
|
+
service, instance, cluster, is_toolbox, user
|
|
232
258
|
)
|
|
233
259
|
|
|
234
260
|
# Rebuild the job metadata
|
|
235
261
|
formatted_job = deployment_config.format_kubernetes_job(
|
|
236
262
|
job_label=REMOTE_RUN_JOB_LABEL
|
|
237
263
|
)
|
|
238
|
-
job_name =
|
|
264
|
+
job_name = format_remote_run_job_name(formatted_job.metadata.name, user)
|
|
239
265
|
formatted_job.metadata.name = job_name
|
|
240
266
|
|
|
241
267
|
# Stop the job
|
|
@@ -263,14 +289,14 @@ def remote_run_token(
|
|
|
263
289
|
kube_client = KubeClient()
|
|
264
290
|
|
|
265
291
|
# Load the service deployment settings
|
|
266
|
-
deployment_config =
|
|
292
|
+
deployment_config = load_eks_or_adhoc_deployment_config(service, instance, cluster)
|
|
267
293
|
namespace = deployment_config.get_namespace()
|
|
268
294
|
|
|
269
295
|
# Rebuild the job metadata
|
|
270
296
|
formatted_job = deployment_config.format_kubernetes_job(
|
|
271
297
|
job_label=REMOTE_RUN_JOB_LABEL
|
|
272
298
|
)
|
|
273
|
-
job_name =
|
|
299
|
+
job_name = format_remote_run_job_name(formatted_job.metadata.name, user)
|
|
274
300
|
|
|
275
301
|
# Find pod and create exec token for it
|
|
276
302
|
pod = find_job_pod(kube_client, namespace, job_name)
|
|
@@ -449,7 +475,7 @@ def create_pod_scoped_role(
|
|
|
449
475
|
role_name = f"remote-run-role-{pod_name_hash}"
|
|
450
476
|
policy = V1PolicyRule(
|
|
451
477
|
verbs=["create", "get"],
|
|
452
|
-
resources=["pods", "pods/exec"],
|
|
478
|
+
resources=["pods", "pods/exec", "pods/log"],
|
|
453
479
|
resource_names=[pod_name],
|
|
454
480
|
api_groups=[""],
|
|
455
481
|
)
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
9
9
|
|
|
10
|
-
The version of the OpenAPI document: 1.
|
|
10
|
+
The version of the OpenAPI document: 1.3.0
|
|
11
11
|
Generated by: https://openapi-generator.tech
|
|
12
12
|
"""
|
|
13
13
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
6
6
|
|
|
7
|
-
The version of the OpenAPI document: 1.
|
|
7
|
+
The version of the OpenAPI document: 1.3.0
|
|
8
8
|
Generated by: https://openapi-generator.tech
|
|
9
9
|
"""
|
|
10
10
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -370,7 +370,7 @@ class Configuration(object):
|
|
|
370
370
|
return "Python SDK Debug Report:\n"\
|
|
371
371
|
"OS: {env}\n"\
|
|
372
372
|
"Python Version: {pyversion}\n"\
|
|
373
|
-
"Version of the API: 1.
|
|
373
|
+
"Version of the API: 1.3.0\n"\
|
|
374
374
|
"SDK Package Version: 1.0.0".\
|
|
375
375
|
format(env=sys.platform, pyversion=sys.version)
|
|
376
376
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
7
|
|
|
8
|
-
The version of the OpenAPI document: 1.
|
|
8
|
+
The version of the OpenAPI document: 1.3.0
|
|
9
9
|
Generated by: https://openapi-generator.tech
|
|
10
10
|
"""
|
|
11
11
|
|