本文整理汇总了Python中utils.dockerutil.DockerUtil类的典型用法代码示例。如果您正苦于以下问题:Python DockerUtil类的具体用法?Python DockerUtil怎么用?Python DockerUtil使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了DockerUtil类的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Python代码示例。
示例1: test_healthcheck
def test_healthcheck(self):
config = {
"init_config": {},
"instances": [{
"url": "unix://var/run/docker.sock",
"health_service_check_whitelist": ["docker_image:nginx", "docker_image:redis"],
},
],
}
DockerUtil().set_docker_settings(config['init_config'], config['instances'][0])
self.run_check(config, force_reload=True)
self.assertServiceCheck('docker.container_health', count=2)
config = {
"init_config": {},
"instances": [{
"url": "unix://var/run/docker.sock",
"health_service_check_whitelist": [],
},
],
}
DockerUtil._drop()
DockerUtil(init_config=config['init_config'], instance=config['instances'][0])
self.run_check(config, force_reload=True)
self.assertServiceCheck('docker.container_health', count=0)
开发者ID:ross,项目名称:dd-agent,代码行数:29,代码来源:test_docker_daemon.py
示例2: agent_container_inspect
def agent_container_inspect():
# Self inspection based on cgroups
# On all platforms, the container ID is the last part of the path.
REGEX_PATTERN = '(.*/)+([a-z0-9]{64})$'
dockerutil = DockerUtil()
cgroup_path = '/proc/self/cgroup'
container_id = None
with open(cgroup_path, 'r') as f:
for ind in f:
id_match = re.search(REGEX_PATTERN, ind)
if id_match:
container_id = id_match.group(2)
break
if container_id is None:
print("The container_id could not be found. Refer to the docker log of the container running the agent")
return 1
try:
inspect = dockerutil.inspect_container(container_id)
key_indices = [i for i, k in enumerate(inspect['Config']['Env']) if 'API_KEY' in k]
for ind in key_indices:
inspect['Config']['Env'][ind] = '%s=%s' % (inspect['Config']['Env'][ind].split('=', 1)[0], 'redacted')
print json.dumps(inspect, indent=4)
return 0
except Exception as e:
print "Could not inspect container: %s" % e
开发者ID:serverdensity,项目名称:sd-agent,代码行数:27,代码来源:configcheck.py
示例3: test_parse_subsystem
def test_parse_subsystem(self):
lines = [
# (line, expected_result)
(
# Kubernetes < 1.6
['10', 'memory', '/2ea504688cad325b9105f183b0d7831266a05f95b513c7327a6e9989ce8a450a'],
'2ea504688cad325b9105f183b0d7831266a05f95b513c7327a6e9989ce8a450a'
), (
# New CoreOS / most systems
['10', 'memory', '/docker/2ea504688cad325b9105f183b0d7831266a05f95b513c7327a6e9989ce8a450a'],
'docker/2ea504688cad325b9105f183b0d7831266a05f95b513c7327a6e9989ce8a450a'
), (
# Unidentified legacy system?
['10', 'memory', '2ea504688cad325b9105f183b0d7831266a05f95b513c7327a6e9989ce8a450a'],
'2ea504688cad325b9105f183b0d7831266a05f95b513c7327a6e9989ce8a450a'
), (
# Rancher
['10', 'memory', '/docker/864daa0a0b19aa4703231b6c76f85c6f369b2452a5a7f777f0c9101c0fd5772a/docker/3bac629503293d1bb61e74f3e25b6c525f0c262f22974634c5d6988bb4b07927'],
'docker/3bac629503293d1bb61e74f3e25b6c525f0c262f22974634c5d6988bb4b07927'
), (
# Legacy CoreOS 7xx
['7', 'memory', '/system.slice/docker-71116698eb215f2a5819f11ece7ea721f0e8d45169c7484d1cd7812596fad454.scope'],
'system.slice/docker-71116698eb215f2a5819f11ece7ea721f0e8d45169c7484d1cd7812596fad454.scope'
), (
# Kubernetes >= 1.6 QoS cgroups
['7', 'memory', '/kubepods/burstable/poda0f63163-3fa8-11e7-a098-42010a840216/7e071d0086ebe623dcbf3a7e0005f23eb08d7ea4df4bb42075df43c9359ce078'],
'kubepods/burstable/poda0f63163-3fa8-11e7-a098-42010a840216/7e071d0086ebe623dcbf3a7e0005f23eb08d7ea4df4bb42075df43c9359ce078'
)
]
du = DockerUtil()
for line, exp_res in lines:
self.assertEquals(du._parse_subsystem(line), exp_res)
开发者ID:tschellhorn,项目名称:dd-agent,代码行数:33,代码来源:test_dockerutil.py
示例4: test_docker_host_tags_ok
def test_docker_host_tags_ok(self):
du = DockerUtil()
mock_isswarm = mock.MagicMock(name='is_swarm', return_value=False)
du._client = mock.MagicMock()
du.is_swarm = mock_isswarm
self.assertEqual([], DockerUtil().get_host_tags())
开发者ID:DataDog,项目名称:dd-agent,代码行数:7,代码来源:test_dockerutil.py
示例5: init
def init(self):
try:
instance = self.instances[0]
self.docker_util = DockerUtil()
self.docker_client = self.docker_util.client
self.docker_gateway = DockerUtil.get_gateway()
if Platform.is_k8s():
self.kubeutil = KubeUtil()
# We configure the check with the right cgroup settings for this host
# Just needs to be done once
self._mountpoints = self.docker_util.get_mountpoints(CGROUP_METRICS)
self.cgroup_listing_retries = 0
self._latest_size_query = 0
self._filtered_containers = set()
self._disable_net_metrics = False
# Set tagging options
self.custom_tags = instance.get("tags", [])
self.collect_labels_as_tags = instance.get("collect_labels_as_tags", [])
self.kube_labels = {}
self.use_histogram = _is_affirmative(instance.get('use_histogram', False))
performance_tags = instance.get("performance_tags", DEFAULT_PERFORMANCE_TAGS)
self.tag_names = {
CONTAINER: instance.get("container_tags", DEFAULT_CONTAINER_TAGS),
PERFORMANCE: performance_tags,
IMAGE: instance.get('image_tags', DEFAULT_IMAGE_TAGS)
}
# Set filtering settings
if not instance.get("exclude"):
self._filtering_enabled = False
if instance.get("include"):
self.log.warning("You must specify an exclude section to enable filtering")
else:
self._filtering_enabled = True
include = instance.get("include", [])
exclude = instance.get("exclude", [])
self._exclude_patterns, self._include_patterns, _filtered_tag_names = get_filters(include, exclude)
self.tag_names[FILTERED] = _filtered_tag_names
# Other options
self.collect_image_stats = _is_affirmative(instance.get('collect_images_stats', False))
self.collect_container_size = _is_affirmative(instance.get('collect_container_size', False))
self.collect_events = _is_affirmative(instance.get('collect_events', True))
self.collect_image_size = _is_affirmative(instance.get('collect_image_size', False))
self.collect_disk_stats = _is_affirmative(instance.get('collect_disk_stats', False))
self.collect_ecs_tags = _is_affirmative(instance.get('ecs_tags', True)) and Platform.is_ecs_instance()
self.ecs_tags = {}
except Exception as e:
self.log.critical(e)
self.warning("Initialization failed. Will retry at next iteration")
else:
self.init_success = True
开发者ID:AltSchool,项目名称:dd-agent,代码行数:59,代码来源:docker_daemon.py
示例6: test_image_name_from_image_repodigests
def test_image_name_from_image_repodigests(self):
du = DockerUtil()
du._client = mock.MagicMock()
du._client.inspect_image = mock.MagicMock(name='inspect_image', return_value = {'RepoTags': [],
'RepoDigests': ['[email protected]:4f2d8bbad359e3e6f23c0498e009aaa3e2f31996cbea7269b78f92ee43647811']})
co = {'Image': 'sha256:e48e77eee11b6d9ac9fc35a23992b4158355a8ec3fd3725526eba3f467e4b6d9'}
self.assertEqual('alpine', du.image_name_extractor(co))
开发者ID:tschellhorn,项目名称:dd-agent,代码行数:8,代码来源:test_dockerutil.py
示例7: test_docker_host_metadata_invalid_response
def test_docker_host_metadata_invalid_response(self):
mock_version = mock.MagicMock(name='version', return_value=None)
du = DockerUtil()
du._client = mock.MagicMock()
du._client.version = mock_version
du.swarm_node_state = 'inactive'
self.assertEqual({'docker_swarm': 'inactive'}, DockerUtil().get_host_metadata())
mock_version.assert_called_once()
开发者ID:tschellhorn,项目名称:dd-agent,代码行数:8,代码来源:test_dockerutil.py
示例8: test_docker_host_metadata_ok
def test_docker_host_metadata_ok(self):
mock_version = mock.MagicMock(name='version', return_value={'Version': '1.13.1'})
du = DockerUtil()
du._client = mock.MagicMock()
du._client.version = mock_version
du.swarm_node_state = 'inactive'
self.assertEqual({'docker_version': '1.13.1', 'docker_swarm': 'inactive'}, du.get_host_metadata())
mock_version.assert_called_once()
开发者ID:tschellhorn,项目名称:dd-agent,代码行数:8,代码来源:test_dockerutil.py
示例9: test_docker_host_tags_swarm_ok
def test_docker_host_tags_swarm_ok(self):
du = DockerUtil()
mock_info = mock.MagicMock(name='info', return_value={'Swarm': {'ControlAvailable' : True}})
mock_isswarm = mock.MagicMock(name='is_swarm', return_value=True)
du._client = mock.MagicMock()
du._client.info = mock_info
du.is_swarm = mock_isswarm
self.assertEqual(['docker_swarm_node_role:manager'], DockerUtil().get_host_tags())
mock_info.assert_called_once()
开发者ID:DataDog,项目名称:dd-agent,代码行数:10,代码来源:test_dockerutil.py
示例10: test_docker_host_metadata_swarm_ok
def test_docker_host_metadata_swarm_ok(self):
du = DockerUtil()
mock_version = mock.MagicMock(name='version', return_value={'Version': '1.13.1'})
mock_isswarm = mock.MagicMock(name='is_swarm', return_value=True)
du._client = mock.MagicMock()
du._client.version = mock_version
du.is_swarm = mock_isswarm
self.assertEqual({'docker_version': '1.13.1', 'docker_swarm': 'active'}, DockerUtil().get_host_metadata())
mock_version.assert_called_once()
开发者ID:tschellhorn,项目名称:dd-agent,代码行数:10,代码来源:test_dockerutil.py
示例11: test_include_filter
def test_include_filter(self):
expected_metrics = [
('docker.containers.running', ['docker_image:nginx:latest', 'image_name:nginx', 'image_tag:latest']),
('docker.containers.running', ['docker_image:redis:latest', 'image_name:redis', 'image_tag:latest']),
('docker.containers.stopped', ['docker_image:nginx:latest', 'image_name:nginx', 'image_tag:latest']),
('docker.containers.stopped', ['docker_image:redis:latest', 'image_name:redis', 'image_tag:latest']),
('docker.cpu.system', ['container_name:test-new-redis-latest', 'docker_image:redis:latest', 'image_name:redis', 'image_tag:latest']),
('docker.cpu.user', ['container_name:test-new-redis-latest', 'docker_image:redis:latest', 'image_name:redis', 'image_tag:latest']),
('docker.image.size', ['image_name:redis', 'image_tag:latest']),
('docker.image.size', ['image_name:nginx', 'image_tag:latest']),
('docker.image.virtual_size', ['image_name:nginx', 'image_tag:latest']),
('docker.image.virtual_size', ['image_name:redis', 'image_tag:latest']),
('docker.images.available', None),
('docker.images.intermediate', None),
('docker.io.read_bytes', ['container_name:test-new-redis-latest', 'docker_image:redis:latest', 'image_name:redis', 'image_tag:latest']),
('docker.io.write_bytes', ['container_name:test-new-redis-latest', 'docker_image:redis:latest', 'image_name:redis', 'image_tag:latest']),
('docker.mem.cache', ['container_name:test-new-redis-latest', 'docker_image:redis:latest', 'image_name:redis', 'image_tag:latest']),
('docker.mem.rss', ['container_name:test-new-redis-latest', 'docker_image:redis:latest', 'image_name:redis', 'image_tag:latest']),
('docker.net.bytes_rcvd', ['container_name:test-new-redis-latest', 'docker_image:redis:latest', 'image_name:redis', 'image_tag:latest']),
('docker.net.bytes_sent', ['container_name:test-new-redis-latest', 'docker_image:redis:latest', 'image_name:redis', 'image_tag:latest'])
]
config = {
"init_config": {},
"instances": [{
"url": "unix://var/run/docker.sock",
"include": ["image_name:redis"],
"exclude": [".*"],
"collect_images_stats": True,
"collect_image_size": True,
},
],
}
DockerUtil._drop()
DockerUtil(init_config=config['init_config'], instance=config['instances'][0])
self.run_check_twice(config, force_reload=True)
for mname, tags in expected_metrics:
self.assertMetric(mname, tags=tags, count=1, at_least=1)
perf_metrics = [
"docker.cpu.system",
"docker.cpu.user",
"docker.io.read_bytes",
"docker.io.write_bytes",
"docker.mem.cache",
"docker.mem.rss",
"docker.net.bytes_rcvd",
"docker.net.bytes_sent"
]
nginx_tags = ['container_name:test-new-nginx-latest', 'docker_image:nginx:latest', 'image_name:nginx', 'image_tag:latest']
for m in perf_metrics:
self.assertMetric(mname, tags=nginx_tags, count=0)
开发者ID:ross,项目名称:dd-agent,代码行数:54,代码来源:test_docker_daemon.py
示例12: test_auto_inspect
def test_auto_inspect(self):
du = DockerUtil()
du._client = mock.MagicMock()
mock_inspect = mock.MagicMock(name='inspect_container', return_value = {'RepoTags': ["redis:3.2"], 'RepoDigests': []})
du._client.inspect_container = mock_inspect
dummy = self.NeedLabelsUtil()
dummy.reset_cache()
dummy.get_container_tags(cid=CO_ID)
mock_inspect.assert_called_once()
开发者ID:DataDog,项目名称:dd-agent,代码行数:11,代码来源:test_orchestrator.py
示例13: print_containers
def print_containers():
dockerutil = DockerUtil()
containers = dockerutil.client.containers()
print("\nContainers info:\n")
print("Number of containers found: %s" % len(containers))
for co in containers:
c_id = 'ID: %s' % co.get('Id')[:12]
c_image = 'image: %s' % dockerutil.image_name_extractor(co)
c_name = 'name: %s' % dockerutil.container_name_extractor(co)[0]
print("\t- %s %s %s" % (c_id, c_image, c_name))
print('\n')
开发者ID:serverdensity,项目名称:sd-agent,代码行数:11,代码来源:configcheck.py
示例14: test_image_name_from_image_repotags
def test_image_name_from_image_repotags(self):
du = DockerUtil()
du._client = mock.MagicMock()
mock_img = mock.MagicMock(name='inspect_image', return_value = {'RepoTags': ["redis:3.2"], 'RepoDigests': []})
du._client.inspect_image = mock_img
sha = 'sha256:e48e77eee11b6d9ac9fc35a23992b4158355a8ec3fd3725526eba3f467e4b6c9'
co = {'Image': sha}
self.assertEqual('redis:3.2', DockerUtil().image_name_extractor(co))
mock_img.assert_called_once_with(sha)
# Make sure cache is used insead of call again inspect_image
DockerUtil().image_name_extractor(co)
mock_img.assert_called_once()
开发者ID:tschellhorn,项目名称:dd-agent,代码行数:13,代码来源:test_dockerutil.py
示例15: test_image_tags_extraction
def test_image_tags_extraction(self):
entities = [
# ({'Image': image_name}, [expected_image_name, expected_image_tag])
({'Image': 'nginx:latest'}, [['nginx'], ['latest']]),
({'Image': 'localhost/nginx:latest'}, [['localhost/nginx'], ['latest']]),
({'Image': 'localhost:5000/nginx:latest'}, [['localhost:5000/nginx'], ['latest']]),
({'RepoTags': ['redis:latest']}, [['redis'], ['latest']]),
({'RepoTags': ['localhost/redis:latest']}, [['localhost/redis'], ['latest']]),
({'RepoTags': ['localhost:5000/redis:latest']}, [['localhost:5000/redis'], ['latest']]),
({'RepoTags': ['localhost:5000/redis:latest', 'localhost:5000/redis:v1.1']}, [['localhost:5000/redis'], ['latest', 'v1.1']]),
]
for entity in entities:
self.assertEqual(sorted(DockerUtil.image_tag_extractor(entity[0], 0)), sorted(entity[1][0]))
self.assertEqual(sorted(DockerUtil.image_tag_extractor(entity[0], 1)), sorted(entity[1][1]))
开发者ID:7040210,项目名称:dd-agent,代码行数:14,代码来源:test_docker_daemon.py
示例16: TestProxy
class TestProxy(AsyncTestCase):
@attr(requires='core_integration')
def test_proxy(self):
config = {
"endpoints": {"https://app.datadoghq.com": ["foo"]},
"proxy_settings": {
"host": "localhost",
"port": PROXY_PORT,
"user": None,
"password": None
}
}
app = Application()
app.skip_ssl_validation = True
app._agentConfig = config
trManager = TransactionManager(MAX_WAIT_FOR_REPLAY, MAX_QUEUE_SIZE, THROTTLING_DELAY)
trManager._flush_without_ioloop = True # Use blocking API to emulate tornado ioloop
CustomAgentTransaction.set_tr_manager(trManager)
app.use_simple_http_client = False # We need proxy capabilities
app.agent_dns_caching = False
# _test is the instance of this class. It is needed to call the method stop() and deal with the asynchronous
# calls as described here : http://www.tornadoweb.org/en/stable/testing.html
CustomAgentTransaction._test = self
CustomAgentTransaction.set_application(app)
CustomAgentTransaction.set_endpoints(config['endpoints'])
CustomAgentTransaction('body', {}, "") # Create and flush the transaction
self.wait()
del CustomAgentTransaction._test
access_log = self.docker_client.exec_start(
self.docker_client.exec_create(CONTAINER_NAME, 'cat /var/log/squid/access.log')['Id'])
self.assertTrue("CONNECT" in access_log) # There should be an entry in the proxy access log
self.assertEquals(len(trManager._endpoints_errors), 1) # There should be an error since we gave a bogus api_key
def setUp(self):
super(TestProxy, self).setUp()
self.docker_client = DockerUtil().client
self.docker_client.pull(CONTAINER_TO_RUN)
self.container = self.docker_client.create_container(CONTAINER_TO_RUN, detach=True, name=CONTAINER_NAME,
ports=[PROXY_PORT], host_config=self.docker_client.create_host_config(port_bindings={3128: PROXY_PORT}))
log.info("Starting container: {0}".format(CONTAINER_TO_RUN))
self.docker_client.start(CONTAINER_NAME)
for line in self.docker_client.logs(CONTAINER_NAME, stdout=True, stream=True):
if "Accepting HTTP Socket connections" in line:
break # Wait for the container to properly start, otherwise we get 'Proxy CONNECT aborted'
def tearDown(self):
log.info("Stopping container: {0}".format(CONTAINER_TO_RUN))
self.docker_client.remove_container(CONTAINER_NAME, force=True)
super(TestProxy, self).tearDown()
开发者ID:alq666,项目名称:dd-agent,代码行数:54,代码来源:test_proxy.py
示例17: _report_performance_metrics
def _report_performance_metrics(self, containers_by_id):
containers_without_proc_root = []
for container in containers_by_id.itervalues():
if self._is_container_excluded(container) or not self._is_container_running(container):
continue
tags = self._get_tags(container, PERFORMANCE)
try:
self._report_cgroup_metrics(container, tags)
if "_proc_root" not in container:
containers_without_proc_root.append(DockerUtil.container_name_extractor(container)[0])
continue
self._report_net_metrics(container, tags)
except BogusPIDException as e:
self.log.warning('Unable to report cgroup metrics: %s', e)
if containers_without_proc_root:
message = "Couldn't find pid directory for containers: {0}. They'll be missing network metrics".format(
", ".join(containers_without_proc_root))
if not Platform.is_k8s():
self.warning(message)
else:
# On kubernetes, this is kind of expected. Network metrics will be collected by the kubernetes integration anyway
self.log.debug(message)
开发者ID:dblackdblack,项目名称:integrations-core,代码行数:26,代码来源:check.py
示例18: TestDockerutil
class TestDockerutil(unittest.TestCase):
def setUp(self):
self.dockerutil = DockerUtil()
@mock.patch("utils.dockerutil.DockerUtil.client")
def test_get_events(self, mocked_client):
mocked_client.events.return_value = [
{"status": "stop", "id": "1234567890", "from": "1234567890", "time": 1423247867}
]
events_generator, _ = self.dockerutil.get_events()
self.assertEqual(len(events_generator), 1)
# bug in dockerpy, we should be resilient
mocked_client.events.return_value = [u"an error from Docker API here"]
events_generator, _ = self.dockerutil.get_events()
self.assertEqual(len(list(events_generator)), 0)
开发者ID:MinerKasch,项目名称:dd-agent,代码行数:16,代码来源:test_docker.py
示例19: __init__
def __init__(self, instance=None):
self.docker_util = DockerUtil()
if instance is None:
try:
config_file_path = get_conf_path(KUBERNETES_CHECK_NAME)
check_config = check_yaml(config_file_path)
instance = check_config['instances'][0]
# kubernetes.yaml was not found
except IOError as ex:
log.error(ex.message)
instance = {}
except Exception:
log.error('Kubernetes configuration file is invalid. '
'Trying connecting to kubelet with default settings anyway...')
instance = {}
self.method = instance.get('method', KubeUtil.DEFAULT_METHOD)
self.host = instance.get("host") or self.docker_util.get_hostname()
self._node_ip = self._node_name = None # lazy evaluation
self.host_name = os.environ.get('HOSTNAME')
self.cadvisor_port = instance.get('port', KubeUtil.DEFAULT_CADVISOR_PORT)
self.kubelet_port = instance.get('kubelet_port', KubeUtil.DEFAULT_KUBELET_PORT)
self.kubelet_api_url = '%s://%s:%d' % (self.method, self.host, self.kubelet_port)
self.cadvisor_url = '%s://%s:%d' % (self.method, self.host, self.cadvisor_port)
self.kubernetes_api_url = 'https://%s/api/v1' % (os.environ.get('KUBERNETES_SERVICE_HOST') or self.DEFAULT_MASTER_NAME)
self.metrics_url = urljoin(self.cadvisor_url, KubeUtil.METRICS_PATH)
self.pods_list_url = urljoin(self.kubelet_api_url, KubeUtil.PODS_LIST_PATH)
self.kube_health_url = urljoin(self.kubelet_api_url, 'healthz')
# keep track of the latest k8s event we collected and posted
# default value is 0 but TTL for k8s events is one hour anyways
self.last_event_collection_ts = defaultdict(int)
开发者ID:AltSchool,项目名称:dd-agent,代码行数:35,代码来源:kubeutil.py
示例20: __init__
def __init__(self):
self.docker_util = DockerUtil()
try:
config_file_path = get_conf_path(KUBERNETES_CHECK_NAME)
check_config = check_yaml(config_file_path)
instance = check_config['instances'][0]
# kubernetes.yaml was not found
except IOError as ex:
log.error(ex.message)
instance = {}
except Exception:
log.error('Kubernetes configuration file is invalid. '
'Trying connecting to kubelet with default settings anyway...')
instance = {}
self.method = instance.get('method', KubeUtil.DEFAULT_METHOD)
self.host = instance.get("host") or self.docker_util.get_hostname()
self.cadvisor_port = instance.get('port', KubeUtil.DEFAULT_CADVISOR_PORT)
self.kubelet_port = instance.get('kubelet_port', KubeUtil.DEFAULT_KUBELET_PORT)
self.metrics_url = urljoin(
'%s://%s:%d' % (self.method, self.host, self.cadvisor_port), KubeUtil.METRICS_PATH)
self.pods_list_url = urljoin(
'%s://%s:%d' % (self.method, self.host, self.kubelet_port), KubeUtil.PODS_LIST_PATH)
self.kube_health_url = '%s://%s:%d/healthz' % (self.method, self.host, self.kubelet_port)
开发者ID:DylanFrese,项目名称:dd-agent,代码行数:27,代码来源:kubeutil.py
注:本文中的utils.dockerutil.DockerUtil类示例由纯净天空整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论