Implement glue tags methods (#5127)
This commit is contained in:
parent
07b7d77611
commit
5389a4e9e2
@ -3,6 +3,7 @@ from collections import OrderedDict
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from moto.core import BaseBackend, BaseModel
|
from moto.core import BaseBackend, BaseModel
|
||||||
|
from moto.core.models import get_account_id
|
||||||
from moto.glue.exceptions import CrawlerRunningException, CrawlerNotRunningException
|
from moto.glue.exceptions import CrawlerRunningException, CrawlerNotRunningException
|
||||||
from .exceptions import (
|
from .exceptions import (
|
||||||
JsonRESTError,
|
JsonRESTError,
|
||||||
@ -20,6 +21,7 @@ from .exceptions import (
|
|||||||
)
|
)
|
||||||
from .utils import PartitionFilter
|
from .utils import PartitionFilter
|
||||||
from ..utilities.paginator import paginate
|
from ..utilities.paginator import paginate
|
||||||
|
from ..utilities.tagging_service import TaggingService
|
||||||
|
|
||||||
|
|
||||||
class GlueBackend(BaseBackend):
|
class GlueBackend(BaseBackend):
|
||||||
@ -43,6 +45,7 @@ class GlueBackend(BaseBackend):
|
|||||||
self.crawlers = OrderedDict()
|
self.crawlers = OrderedDict()
|
||||||
self.jobs = OrderedDict()
|
self.jobs = OrderedDict()
|
||||||
self.job_runs = OrderedDict()
|
self.job_runs = OrderedDict()
|
||||||
|
self.tagger = TaggingService()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def default_vpc_endpoint_service(service_region, zones):
|
def default_vpc_endpoint_service(service_region, zones):
|
||||||
@ -137,6 +140,7 @@ class GlueBackend(BaseBackend):
|
|||||||
configuration=configuration,
|
configuration=configuration,
|
||||||
crawler_security_configuration=crawler_security_configuration,
|
crawler_security_configuration=crawler_security_configuration,
|
||||||
tags=tags,
|
tags=tags,
|
||||||
|
backend=self,
|
||||||
)
|
)
|
||||||
self.crawlers[name] = crawler
|
self.crawlers[name] = crawler
|
||||||
|
|
||||||
@ -209,6 +213,7 @@ class GlueBackend(BaseBackend):
|
|||||||
glue_version,
|
glue_version,
|
||||||
number_of_workers,
|
number_of_workers,
|
||||||
worker_type,
|
worker_type,
|
||||||
|
backend=self,
|
||||||
)
|
)
|
||||||
return name
|
return name
|
||||||
|
|
||||||
@ -230,6 +235,16 @@ class GlueBackend(BaseBackend):
|
|||||||
def list_jobs(self):
|
def list_jobs(self):
|
||||||
return [job for _, job in self.jobs.items()]
|
return [job for _, job in self.jobs.items()]
|
||||||
|
|
||||||
|
def get_tags(self, resource_id):
|
||||||
|
return self.tagger.get_tag_dict_for_resource(resource_id)
|
||||||
|
|
||||||
|
def tag_resource(self, resource_arn, tags):
|
||||||
|
tags = TaggingService.convert_dict_to_tags_input(tags or {})
|
||||||
|
self.tagger.tag_resource(resource_arn, tags)
|
||||||
|
|
||||||
|
def untag_resource(self, resource_arn, tag_keys):
|
||||||
|
self.tagger.untag_resource_using_names(resource_arn, tag_keys)
|
||||||
|
|
||||||
|
|
||||||
class FakeDatabase(BaseModel):
|
class FakeDatabase(BaseModel):
|
||||||
def __init__(self, database_name, database_input):
|
def __init__(self, database_name, database_input):
|
||||||
@ -368,6 +383,7 @@ class FakeCrawler(BaseModel):
|
|||||||
configuration,
|
configuration,
|
||||||
crawler_security_configuration,
|
crawler_security_configuration,
|
||||||
tags,
|
tags,
|
||||||
|
backend,
|
||||||
):
|
):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.role = role
|
self.role = role
|
||||||
@ -382,13 +398,15 @@ class FakeCrawler(BaseModel):
|
|||||||
self.lineage_configuration = lineage_configuration
|
self.lineage_configuration = lineage_configuration
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
self.crawler_security_configuration = crawler_security_configuration
|
self.crawler_security_configuration = crawler_security_configuration
|
||||||
self.tags = tags
|
|
||||||
self.state = "READY"
|
self.state = "READY"
|
||||||
self.creation_time = datetime.utcnow()
|
self.creation_time = datetime.utcnow()
|
||||||
self.last_updated = self.creation_time
|
self.last_updated = self.creation_time
|
||||||
self.version = 1
|
self.version = 1
|
||||||
self.crawl_elapsed_time = 0
|
self.crawl_elapsed_time = 0
|
||||||
self.last_crawl_info = None
|
self.last_crawl_info = None
|
||||||
|
self.arn = f"arn:aws:glue:us-east-1:{get_account_id()}:crawler/{self.name}"
|
||||||
|
self.backend = backend
|
||||||
|
self.backend.tag_resource(self.arn, tags)
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
return self.name
|
return self.name
|
||||||
@ -486,6 +504,7 @@ class FakeJob:
|
|||||||
glue_version=None,
|
glue_version=None,
|
||||||
number_of_workers=None,
|
number_of_workers=None,
|
||||||
worker_type=None,
|
worker_type=None,
|
||||||
|
backend=None,
|
||||||
):
|
):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.description = description
|
self.description = description
|
||||||
@ -502,13 +521,15 @@ class FakeJob:
|
|||||||
self.state = "READY"
|
self.state = "READY"
|
||||||
self.max_capacity = max_capacity
|
self.max_capacity = max_capacity
|
||||||
self.security_configuration = security_configuration
|
self.security_configuration = security_configuration
|
||||||
self.tags = tags
|
|
||||||
self.notification_property = notification_property
|
self.notification_property = notification_property
|
||||||
self.glue_version = glue_version
|
self.glue_version = glue_version
|
||||||
self.number_of_workers = number_of_workers
|
self.number_of_workers = number_of_workers
|
||||||
self.worker_type = worker_type
|
self.worker_type = worker_type
|
||||||
self.created_on = datetime.utcnow()
|
self.created_on = datetime.utcnow()
|
||||||
self.last_modified_on = datetime.utcnow()
|
self.last_modified_on = datetime.utcnow()
|
||||||
|
self.arn = f"arn:aws:glue:us-east-1:{get_account_id()}:job/{self.name}"
|
||||||
|
self.backend = backend
|
||||||
|
self.backend.tag_resource(self.arn, tags)
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -328,7 +328,7 @@ class GlueResponse(BaseResponse):
|
|||||||
return [
|
return [
|
||||||
crawler.get_name()
|
crawler.get_name()
|
||||||
for crawler in crawlers
|
for crawler in crawlers
|
||||||
if self.is_tags_match(crawler.tags, tags)
|
if self.is_tags_match(self, crawler.arn, tags)
|
||||||
]
|
]
|
||||||
|
|
||||||
def start_crawler(self):
|
def start_crawler(self):
|
||||||
@ -420,13 +420,33 @@ class GlueResponse(BaseResponse):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_tags(self):
|
||||||
|
resource_arn = self.parameters.get("ResourceArn")
|
||||||
|
tags = self.glue_backend.get_tags(resource_arn)
|
||||||
|
return 200, {}, json.dumps({"Tags": tags})
|
||||||
|
|
||||||
|
def tag_resource(self):
|
||||||
|
resource_arn = self.parameters.get("ResourceArn")
|
||||||
|
tags = self.parameters.get("TagsToAdd", {})
|
||||||
|
self.glue_backend.tag_resource(resource_arn, tags)
|
||||||
|
return 201, {}, "{}"
|
||||||
|
|
||||||
|
def untag_resource(self):
|
||||||
|
resource_arn = self._get_param("ResourceArn")
|
||||||
|
tag_keys = self.parameters.get("TagsToRemove")
|
||||||
|
self.glue_backend.untag_resource(resource_arn, tag_keys)
|
||||||
|
return 200, {}, "{}"
|
||||||
|
|
||||||
def filter_jobs_by_tags(self, jobs, tags):
|
def filter_jobs_by_tags(self, jobs, tags):
|
||||||
if not tags:
|
if not tags:
|
||||||
return [job.get_name() for job in jobs]
|
return [job.get_name() for job in jobs]
|
||||||
return [job.get_name() for job in jobs if self.is_tags_match(job.tags, tags)]
|
return [
|
||||||
|
job.get_name() for job in jobs if self.is_tags_match(self, job.arn, tags)
|
||||||
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_tags_match(glue_resource_tags, tags):
|
def is_tags_match(self, resource_arn, tags):
|
||||||
|
glue_resource_tags = self.glue_backend.get_tags(resource_arn)
|
||||||
mutual_keys = set(glue_resource_tags).intersection(tags)
|
mutual_keys = set(glue_resource_tags).intersection(tags)
|
||||||
for key in mutual_keys:
|
for key in mutual_keys:
|
||||||
if glue_resource_tags[key] == tags[key]:
|
if glue_resource_tags[key] == tags[key]:
|
||||||
|
@ -192,6 +192,30 @@ def test_list_jobs_with_tags():
|
|||||||
response["JobNames"].should.have.length_of(1)
|
response["JobNames"].should.have.length_of(1)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_glue
|
||||||
|
def test_list_jobs_after_tagging():
|
||||||
|
client = create_glue_client()
|
||||||
|
job_name = create_test_job(client)
|
||||||
|
resource_arn = f"arn:aws:glue:us-east-1:123456789012:job/{job_name}"
|
||||||
|
|
||||||
|
client.tag_resource(ResourceArn=resource_arn, TagsToAdd={"key1": "value1"})
|
||||||
|
|
||||||
|
response = client.list_jobs(Tags={"key1": "value1"})
|
||||||
|
response["JobNames"].should.have.length_of(1)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_glue
|
||||||
|
def test_list_jobs_after_removing_tag():
|
||||||
|
client = create_glue_client()
|
||||||
|
job_name = create_test_job(client, {"key1": "value1"})
|
||||||
|
resource_arn = f"arn:aws:glue:us-east-1:123456789012:job/{job_name}"
|
||||||
|
|
||||||
|
client.untag_resource(ResourceArn=resource_arn, TagsToRemove=["key1"])
|
||||||
|
|
||||||
|
response = client.list_jobs(Tags={"key1": "value1"})
|
||||||
|
response["JobNames"].should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
@mock_glue
|
@mock_glue
|
||||||
def test_list_jobs_next_token_logic_does_not_create_infinite_loop():
|
def test_list_jobs_next_token_logic_does_not_create_infinite_loop():
|
||||||
client = create_glue_client()
|
client = create_glue_client()
|
||||||
@ -281,6 +305,30 @@ def test_list_crawlers_with_tags():
|
|||||||
response["CrawlerNames"].should.have.length_of(1)
|
response["CrawlerNames"].should.have.length_of(1)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_glue
|
||||||
|
def test_list_crawlers_after_tagging():
|
||||||
|
client = create_glue_client()
|
||||||
|
crawler_name = create_test_crawler(client)
|
||||||
|
resource_arn = f"arn:aws:glue:us-east-1:123456789012:crawler/{crawler_name}"
|
||||||
|
|
||||||
|
client.tag_resource(ResourceArn=resource_arn, TagsToAdd={"key1": "value1"})
|
||||||
|
|
||||||
|
response = client.list_crawlers(Tags={"key1": "value1"})
|
||||||
|
response["CrawlerNames"].should.have.length_of(1)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_glue
|
||||||
|
def test_list_crawlers_after_removing_tag():
|
||||||
|
client = create_glue_client()
|
||||||
|
crawler_name = create_test_crawler(client, {"key1": "value1"})
|
||||||
|
resource_arn = f"arn:aws:glue:us-east-1:123456789012:crawler/{crawler_name}"
|
||||||
|
|
||||||
|
client.untag_resource(ResourceArn=resource_arn, TagsToRemove=["key1"])
|
||||||
|
|
||||||
|
response = client.list_crawlers(Tags={"key1": "value1"})
|
||||||
|
response["CrawlerNames"].should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
@mock_glue
|
@mock_glue
|
||||||
def test_list_crawlers_next_token_logic_does_not_create_infinite_loop():
|
def test_list_crawlers_next_token_logic_does_not_create_infinite_loop():
|
||||||
client = create_glue_client()
|
client = create_glue_client()
|
||||||
@ -291,3 +339,113 @@ def test_list_crawlers_next_token_logic_does_not_create_infinite_loop():
|
|||||||
response = client.list_crawlers(NextToken=next_token)
|
response = client.list_crawlers(NextToken=next_token)
|
||||||
next_token = response.get("NextToken")
|
next_token = response.get("NextToken")
|
||||||
assert not next_token
|
assert not next_token
|
||||||
|
|
||||||
|
|
||||||
|
@mock_glue
|
||||||
|
def test_get_tags_job():
|
||||||
|
client = create_glue_client()
|
||||||
|
job_name = create_test_job(client, {"key1": "value1", "key2": "value2"})
|
||||||
|
resource_arn = f"arn:aws:glue:us-east-1:123456789012:job/{job_name}"
|
||||||
|
|
||||||
|
resp = client.get_tags(ResourceArn=resource_arn)
|
||||||
|
|
||||||
|
resp.should.have.key("Tags").equals({"key1": "value1", "key2": "value2"})
|
||||||
|
|
||||||
|
|
||||||
|
@mock_glue
|
||||||
|
def test_get_tags_jobs_no_tags():
|
||||||
|
client = create_glue_client()
|
||||||
|
job_name = create_test_job(client)
|
||||||
|
resource_arn = f"arn:aws:glue:us-east-1:123456789012:job/{job_name}"
|
||||||
|
|
||||||
|
resp = client.get_tags(ResourceArn=resource_arn)
|
||||||
|
|
||||||
|
resp.should.have.key("Tags").equals({})
|
||||||
|
|
||||||
|
|
||||||
|
@mock_glue
|
||||||
|
def test_tag_glue_job():
|
||||||
|
client = create_glue_client()
|
||||||
|
job_name = create_test_job(client)
|
||||||
|
resource_arn = f"arn:aws:glue:us-east-1:123456789012:job/{job_name}"
|
||||||
|
|
||||||
|
client.tag_resource(
|
||||||
|
ResourceArn=resource_arn, TagsToAdd={"key1": "value1", "key2": "value2"}
|
||||||
|
)
|
||||||
|
|
||||||
|
resp = client.get_tags(ResourceArn=resource_arn)
|
||||||
|
|
||||||
|
resp.should.have.key("Tags").equals({"key1": "value1", "key2": "value2"})
|
||||||
|
|
||||||
|
|
||||||
|
@mock_glue
|
||||||
|
def test_untag_glue_job():
|
||||||
|
client = create_glue_client()
|
||||||
|
job_name = create_test_job(client)
|
||||||
|
resource_arn = f"arn:aws:glue:us-east-1:123456789012:job/{job_name}"
|
||||||
|
|
||||||
|
client.tag_resource(
|
||||||
|
ResourceArn=resource_arn,
|
||||||
|
TagsToAdd={"key1": "value1", "key2": "value2", "key3": "value3"},
|
||||||
|
)
|
||||||
|
|
||||||
|
client.untag_resource(ResourceArn=resource_arn, TagsToRemove=["key2"])
|
||||||
|
|
||||||
|
resp = client.get_tags(ResourceArn=resource_arn)
|
||||||
|
|
||||||
|
resp.should.have.key("Tags").equals({"key1": "value1", "key3": "value3"})
|
||||||
|
|
||||||
|
|
||||||
|
@mock_glue
|
||||||
|
def test_get_tags_crawler():
|
||||||
|
client = create_glue_client()
|
||||||
|
crawler_name = create_test_crawler(client, {"key1": "value1", "key2": "value2"})
|
||||||
|
resource_arn = f"arn:aws:glue:us-east-1:123456789012:crawler/{crawler_name}"
|
||||||
|
|
||||||
|
resp = client.get_tags(ResourceArn=resource_arn)
|
||||||
|
|
||||||
|
resp.should.have.key("Tags").equals({"key1": "value1", "key2": "value2"})
|
||||||
|
|
||||||
|
|
||||||
|
@mock_glue
|
||||||
|
def test_get_tags_crawler_no_tags():
|
||||||
|
client = create_glue_client()
|
||||||
|
crawler_name = create_test_crawler(client)
|
||||||
|
resource_arn = f"arn:aws:glue:us-east-1:123456789012:crawler/{crawler_name}"
|
||||||
|
|
||||||
|
resp = client.get_tags(ResourceArn=resource_arn)
|
||||||
|
|
||||||
|
resp.should.have.key("Tags").equals({})
|
||||||
|
|
||||||
|
|
||||||
|
@mock_glue
|
||||||
|
def test_tag_glue_crawler():
|
||||||
|
client = create_glue_client()
|
||||||
|
crawler_name = create_test_crawler(client)
|
||||||
|
resource_arn = f"arn:aws:glue:us-east-1:123456789012:crawler/{crawler_name}"
|
||||||
|
|
||||||
|
client.tag_resource(
|
||||||
|
ResourceArn=resource_arn, TagsToAdd={"key1": "value1", "key2": "value2"}
|
||||||
|
)
|
||||||
|
|
||||||
|
resp = client.get_tags(ResourceArn=resource_arn)
|
||||||
|
|
||||||
|
resp.should.have.key("Tags").equals({"key1": "value1", "key2": "value2"})
|
||||||
|
|
||||||
|
|
||||||
|
@mock_glue
|
||||||
|
def test_untag_glue_crawler():
|
||||||
|
client = create_glue_client()
|
||||||
|
crawler_name = create_test_crawler(client)
|
||||||
|
resource_arn = f"arn:aws:glue:us-east-1:123456789012:crawler/{crawler_name}"
|
||||||
|
|
||||||
|
client.tag_resource(
|
||||||
|
ResourceArn=resource_arn,
|
||||||
|
TagsToAdd={"key1": "value1", "key2": "value2", "key3": "value3"},
|
||||||
|
)
|
||||||
|
|
||||||
|
client.untag_resource(ResourceArn=resource_arn, TagsToRemove=["key2"])
|
||||||
|
|
||||||
|
resp = client.get_tags(ResourceArn=resource_arn)
|
||||||
|
|
||||||
|
resp.should.have.key("Tags").equals({"key1": "value1", "key3": "value3"})
|
||||||
|
Loading…
Reference in New Issue
Block a user