Skip to content

Commit

Permalink
ADD: get framework information.
Browse files Browse the repository at this point in the history
ADD: inspect task to get low level information of a task.

ADD: framework plugin.

ADD: framework filter for tasks.

CHANGE: task query limit to unlimited.

remove newline and rewrite docstring
  • Loading branch information
andreaspeters committed Sep 2, 2021
1 parent 8a344da commit 0a894b0
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 23 deletions.
1 change: 1 addition & 0 deletions docs/frameworks.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ layout: documentation

* [Aurora](http://aurora.apache.org) is a service scheduler that runs on top of Mesos, enabling you to run long-running services that take advantage of Mesos' scalability, fault-tolerance, and resource isolation.
* [Marathon](https://github.com/mesosphere/marathon) is a private PaaS built on Mesos. It automatically handles hardware or software failures and ensures that an app is "always on".
* [M3s](https://github.com/AVENTER-UG/go-mesos-framework-k3s) is a framework to run Kubernetes under mesos.
* [Singularity](https://github.com/HubSpot/Singularity) is a scheduler (HTTP API and web interface) for running Mesos tasks: long running processes, one-off tasks, and scheduled jobs.
* [SSSP](https://github.com/mesosphere/sssp) is a simple web application that provides a white-label "Megaupload" for storing and sharing files in S3.

Expand Down
2 changes: 2 additions & 0 deletions src/python/cli_new/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ if (ENABLE_NEW_CLI)
lib/cli/plugins/agent/main.py
lib/cli/plugins/config/__init__.py
lib/cli/plugins/config/main.py
lib/cli/plugins/framework/__init__.py
lib/cli/plugins/framework/main.py
lib/cli/plugins/task/__init__.py
lib/cli/plugins/task/main.py)

Expand Down
3 changes: 2 additions & 1 deletion src/python/cli_new/bin/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
PLUGINS = [
os.path.join(PROJECT_DIR, "lib", "mesos", "plugins", "agent"),
os.path.join(PROJECT_DIR, "lib", "mesos", "plugins", "config"),
os.path.join(PROJECT_DIR, "lib", "mesos", "plugins", "task")
os.path.join(PROJECT_DIR, "lib", "mesos", "plugins", "task"),
os.path.join(PROJECT_DIR, "lib", "mesos", "plugins", "framework")
]

DEFAULT_MESOS_CLI_CONFIG = os.path.join(
Expand Down
16 changes: 4 additions & 12 deletions src/python/cli_new/lib/cli/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ def read_endpoint(addr, endpoint, config, query=None):
"""
Read the specified endpoint and return the results.
"""

try:
addr = cli.util.sanitize_address(addr)

except Exception as exception:
raise CLIException("Unable to sanitize address '{addr}': {error}"
.format(addr=addr, error=str(exception)))
Expand Down Expand Up @@ -64,13 +64,11 @@ def read_endpoint(addr, endpoint, config, query=None):
.format(url=url, error=str(exception)))


def get_json(addr, endpoint, config, condition=None, query=None):
def get_json(addr, endpoint, config, query=None):
"""
Return the contents of the 'endpoint' at 'addr' as JSON data
subject to the condition specified in 'condition'. If we are
unable to read the data we throw an error.
Return the contents of the 'endpoint' at 'addr' as JSON data.
If we are unable to read the data we throw an error.
"""

data = read_endpoint(addr, endpoint, config, query)

try:
Expand All @@ -79,10 +77,4 @@ def get_json(addr, endpoint, config, condition=None, query=None):
raise CLIException("Could not load JSON from '{data}': {error}"
.format(data=data, error=str(exception)))

if not condition:
return data

if condition(data):
return data

return data
44 changes: 36 additions & 8 deletions src/python/cli_new/lib/cli/mesos.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,8 @@ def get_agent_address(agent_id, master, config):
Given a master and an agent id, return the agent address
by checking the /slaves endpoint of the master.
"""
try:
agents = http.get_json(master, "slaves", config)["slaves"]
except Exception as exception:
raise CLIException("Could not open '/slaves'"
" endpoint at '{addr}': {error}"
.format(addr=master,
error=exception))
agents = get_agents(master, config)

for agent in agents:
if agent["id"] == agent_id:
return agent["pid"].split("@")[1]
Expand All @@ -66,8 +61,40 @@ def get_agents(master, config):
"""
Get the agents in a Mesos cluster.
"""

endpoint = "slaves"
key = "slaves"
return get_key_endpoint(key, endpoint, master, config)

def get_framework_address(framework_id, master, config):
"""
Given a master and an framework id, return the framework address
by checking the /master/frameworks endpoint of the master.
"""
frameworks = get_frameworks(master, config)

for framework in frameworks:
if framework["id"] == framework_id:
return framework["webui_url"]
# pylint: disable=line-too-long
raise CLIException("Unable to find framework '{id}'".format(id=framework_id))


def get_frameworks(master, config):
"""
Get the frameworks in a Mesos cluster.
"""

endpoint = "master/frameworks/"
key = "frameworks"
return get_key_endpoint(key, endpoint, master, config)


def get_key_endpoint(key, endpoint, master, config):
"""
Get the json key of the given endpoint
"""

try:
data = http.get_json(master, endpoint, config)
except Exception as exception:
Expand All @@ -84,6 +111,7 @@ def get_agents(master, config):
return data[key]



def get_container_id(task):
"""
Get the container ID of a task.
Expand Down Expand Up @@ -121,7 +149,7 @@ def get_tasks(master, config, query=None):
key = "tasks"

if query is None:
query = {'order':'asc'}
query = {'order':'asc', 'limit':'-1'}

try:
data = http.get_json(master, endpoint, config, query=query)
Expand Down
22 changes: 22 additions & 0 deletions src/python/cli_new/lib/cli/plugins/framework/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.

"""
Framework module.
"""

# pylint: disable=wildcard-import
from .main import *
119 changes: 119 additions & 0 deletions src/python/cli_new/lib/cli/plugins/framework/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.

"""
The framework plugin.
"""

import json

from cli.exceptions import CLIException
from cli.mesos import get_frameworks
from cli.plugins import PluginBase
from cli.util import Table


PLUGIN_NAME = "framework"
PLUGIN_CLASS = "Framework"

VERSION = "v0.1.0"

SHORT_HELP = "Interacts with the Mesos Frameworks"


class Framework(PluginBase):
"""
The framework plugin.
"""

COMMANDS = {
"list": {
"arguments": [],
"flags": {
"-a --all": "list also non active frameworks"
},
"short_help": "List the Mesos frameworks.",
"long_help": "List information about the Mesos frameworks."
},
"inspect": {
"arguments": ['<framework_id>'],
"flags": {},
"short_help": "Return low-level information of the framework.",
"long_help": "Return low-level information of the framework."
}
}

def list(self, argv):
"""
Show a list of running M3s frameworks
"""

try:
master = self.config.master()
config = self.config
except Exception as exception:
raise CLIException("Unable to get leading master address: {error}"
.format(error=exception))

data = get_frameworks(master, config)
try:
table = Table(["ID", "Active", "Hostname", "Name"])
for framework in data:
if (not argv["--all"] and framework["active"] is not True):
continue

active = "False"
if framework["active"]:
active = "True"

table.add_row([framework["id"],
active,
framework["hostname"],
framework["name"]])
except Exception as exception:
raise CLIException("Unable to build table of frameworks: {error}"
.format(error=exception))

print(str(table))

def inspect(self, argv):
"""
Show the low-level information of the framework.
"""

try:
master = self.config.master()
config = self.config
except Exception as exception:
raise CLIException("Unable to get leading master address: {error}"
.format(error=exception))

data = get_frameworks(master, config)
try:
for framework in data:
if framework["id"] != argv["<framework_id>"]:
continue

# remove not helpfull information
framework.pop('tasks', None)
framework.pop('unreachable_tasks', None)
framework.pop('completed_tasks', None)

print(json.dumps(framework, indent=4))

except Exception as exception:
raise CLIException("Unable to build table of frameworks: {error}"
.format(error=exception))
43 changes: 41 additions & 2 deletions src/python/cli_new/lib/cli/plugins/task/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
The task plugin.
"""

import json

from cli.exceptions import CLIException
from cli.mesos import get_tasks
from cli.plugins import PluginBase
Expand Down Expand Up @@ -59,12 +61,18 @@ class Task(PluginBase):
"long_help": "Execute commands in a task's container"
},
"list": {
"arguments": [],
"arguments": ['[<framework_id>]'],
"flags": {
"-a --all": "list all tasks, not only running [default: False]"
"-a --all": "list all tasks, not only running [default: False]",
},
"short_help": "List all running tasks in a Mesos cluster",
"long_help": "List all running tasks in a Mesos cluster"
},
"inspect": {
"arguments": ['<task_id>'],
"flags": {},
"short_help": "Return low-level information of the task.",
"long_help": "Return low-level information of the task."
}
}

Expand Down Expand Up @@ -134,6 +142,12 @@ def list(self, argv):
if not argv["--all"] and task_state != "TASK_RUNNING":
continue

if (
(argv["<framework_id>"]) and
(task["framework_id"] != argv["<framework_id>"])
):
continue

table.add_row([task["id"],
task_state,
task["framework_id"],
Expand All @@ -143,3 +157,28 @@ def list(self, argv):
.format(error=exception))

print(str(table))


def inspect(self, argv):
"""
Show the low-level information of the task.
"""

try:
master = self.config.master()
config = self.config
except Exception as exception:
raise CLIException("Unable to get leading master address: {error}"
.format(error=exception))

data = get_tasks(master, config)
try:
for task in data:
if task["id"] != argv["<task_id>"]:
continue

print(json.dumps(task, indent=4))

except Exception as exception:
raise CLIException("Unable to build table of task: {error}"
.format(error=exception))

0 comments on commit 0a894b0

Please sign in to comment.