tim_frazer
11/23/2021, 7:53 PMThe above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/meltano/cli/__init__.py", line 45, in main
cli(obj={"project": None})
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/meltano/cli/params.py", line 23, in decorate
return func(*args, **kwargs)
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/meltano/cli/params.py", line 56, in decorate
func(project, *args, **kwargs)
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/meltano/core/utils/__init__.py", line 72, in wrapper
return run_async(func(*args, **kwargs))
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/meltano/core/utils/__init__.py", line 51, in run_async
loop.run_until_complete(future)
File "/Users/timfrazer/.pyenv/versions/3.8.11/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
return future.result()
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/meltano/cli/elt.py", line 138, in elt
await _run_job(project, job, session, context_builder, force=force)
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/meltano/cli/elt.py", line 217, in _run_job
await _run_elt(project, context_builder, output_logger)
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/meltano/cli/elt.py", line 251, in _run_elt
raise CliError(f"ELT could not be completed: {err}") from err
meltano.cli.utils.CliError: ELT could not be completed: Extractor failed
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/timfrazer/Projects/meltano-projects/data-to-bigquery/.venv/lib/python3.8/site-packages/meltano/cli/__init__.py", line 53, in main
raise CliError(str(err)) from err
meltano.cli.utils.CliError: ELT could not be completed: Extractor failed
ELT could not be completed: Extractor failed
tim_frazer
11/23/2021, 7:59 PMmeltano config tap-okta test
tim_frazer
11/23/2021, 7:59 PMmeltano config tap-okta test 1 ↵
Plugin configuration is invalid
{"type": "SCHEMA", "stream": "users", "schema": {"type": "object", "properties": {"id": {"type": ["null", "string"]}, "status": {"type": ["null", "string"]}, "created": {"type": ["null", "string"], "format": "date-time"}, "activated": {"type": ["null", "string"]}, "statusChanged": {"type": ["null", "string"], "format": "date-time"}, "lastLogin": {"type": ["null", "string"], "format": "date-time"}, "lastUpdated": {"type": ["null", "string"], "format": "date-time"}, "passwordChanged": {"type": ["null", "string"], "format": "date-time"}, "profile": {"type": ["null", "object"], "properties": {"ssoid": {"type": ["null", "string"]}, "firstName": {"type": ["null", "string"]}, "lastName": {"type": ["null", "string"]}, "mobilePhone": {"type": ["null", "string"]}, "secondEmail": {"type": ["null", "string"]}, "grpList": {"type": ["null", "string"]}, "login": {"type": ["null", "string"]}, "email": {"type": ["null", "string"]}}}}}, "key_properties": ["id"]}
tim_frazer
11/23/2021, 8:00 PMPlugin configuration is invalid
but not really pointing me towards what is invalidpat_nadolny
11/23/2021, 8:06 PMmeltano --log-level=debug config tap-okta test
and see if the logs tell you anything else. You might just be missing a required config key or somethingtim_frazer
11/23/2021, 8:34 PMvisch
11/24/2021, 1:30 PMmeltano.yml
that would be helpful potentiallytim_frazer
11/24/2021, 1:53 PMversion: 1
send_anonymous_usage_stats: true
project_id: 253fc4ee-65ff-46dd-99d5-fbadaaf4009e
plugins:
extractors:
- name: tap-okta
namespace: tap_okta
pip_url: git+<https://github.com/isabella232/tap-okta.git>
executable: tap-okta
capabilities:
- catalog
- discover
settings:
- name: api_key
- name: service_url
loaders:
- name: target-csv
variant: hotgluexyz
pip_url: git+<https://github.com/hotgluexyz/target-csv.git@0.3.3>
tim_frazer
11/24/2021, 1:53 PMvisch
11/24/2021, 2:05 PMvisch
11/24/2021, 2:13 PMmeltano --log-level=debug elt tap-okta target-csv
with bogus okta creds to get an error, recieved a similar error message as youpat_nadolny
11/24/2021, 2:22 PMException: Config is missing required keys: ['api_key', 'service_url']
with the yaml above but if I add those two required keys where I set testing
as my service_url I get a log message like requests.exceptions.MissingSchema: Invalid URL 'testingusers': No schema supplied. Perhaps you meant <http://testingusers>?
but it looks like the tap was running. @tim_frazer what else are you seeing in the logs?tim_frazer
11/24/2021, 2:31 PMnext_page_token
logictim_frazer
11/24/2021, 2:32 PMvisch
11/24/2021, 2:38 PMmeltano invoke tap-okta
, which outputs the schema propery (this is fine, the tap probably needs a catalog provided)
meltano invoke tap-okta -d > catalog.json
meltano invoke tap-okta -c catalog.json
visch@visch-ubuntu:~/git/sandbox/oktatest$ meltano invoke tap-okta -d > catalog.json
INFO Loading schemas
INFO End Date Time : 2021-11-24 09:14:10.289267
visch@visch-ubuntu:~/git/sandbox/oktatest$ meltano invoke tap-okta -c catalog.json
Traceback (most recent call last):
File "/home/visch/git/sandbox/oktatest/.meltano/extractors/tap-okta/venv/bin/tap-okta", line 8, in <module>
sys.exit(main())
File "/home/visch/git/sandbox/oktatest/.meltano/extractors/tap-okta/venv/lib/python3.8/site-packages/tap_okta/__init__.py", line 158, in main
args = singer.utils.parse_args(REQUIRED_CONFIG_KEYS)
File "/home/visch/git/sandbox/oktatest/.meltano/extractors/tap-okta/venv/lib/python3.8/site-packages/singer/utils.py", line 178, in parse_args
check_config(args.config, required_config_keys)
File "/home/visch/git/sandbox/oktatest/.meltano/extractors/tap-okta/venv/lib/python3.8/site-packages/singer/utils.py", line 186, in check_config
raise Exception("Config is missing required keys: {}".format(missing_keys))
Exception: Config is missing required keys: ['api_key', 'service_url']
I'd check on your config keys and run this command.
What makes no sense to me is why when we run meltano elt tap-okta target-csv
we don't get this error message listed.
I almost wonder if tap-okta is sending the error to stdout instead of stderrvisch
11/24/2021, 2:38 PMvisch
11/24/2021, 2:39 PMTraceback (most recent call last):
File "/home/visch/git/sandbox/oktatest/.meltano/extractors/tap-okta/venv/bin/tap-okta", line 8, in <module>
sys.exit(main())
File "/home/visch/git/sandbox/oktatest/.meltano/extractors/tap-okta/venv/lib/python3.8/site-packages/tap_okta/__init__.py", line 158, in main
args = singer.utils.parse_args(REQUIRED_CONFIG_KEYS)
File "/home/visch/git/sandbox/oktatest/.meltano/extractors/tap-okta/venv/lib/python3.8/site-packages/singer/utils.py", line 178, in parse_args
check_config(args.config, required_config_keys)
File "/home/visch/git/sandbox/oktatest/.meltano/extractors/tap-okta/venv/lib/python3.8/site-packages/singer/utils.py", line 186, in check_config
raise Exception("Config is missing required keys: {}".format(missing_keys))
Exception: Config is missing required keys: ['api_key', 'service_url']
Is sent to stderr, so why meltano isn't showing it is a bit concerning to mepat_nadolny
11/24/2021, 2:40 PM--log-level=debug
pat_nadolny
11/24/2021, 2:40 PM, line 186, in check_config
tap-okta | discovery | raise Exception("Config is missing required keys: {}".format(missing_keys))
tap-okta | discovery | Exception: Config is missing required keys: ['api_key', 'service_url']
tap-okta | discovery |
visch
11/24/2021, 2:40 PMvisch
11/24/2021, 2:41 PMvisch
11/24/2021, 2:43 PMpat_nadolny
11/24/2021, 2:47 PMmeltano --log-level=debug elt tap-okta target-csv
?visch
11/24/2021, 2:47 PMpat_nadolny
11/24/2021, 2:48 PMpat_nadolny
11/24/2021, 2:49 PMpat_nadolny
11/24/2021, 2:50 PMException: Config is missing required keys: ['api_key', 'service_url']
as part of discovery and yours doesnt look like its doing discovery? idkvisch
11/24/2021, 2:50 PMvisch
11/24/2021, 2:57 PMpat_nadolny
11/24/2021, 2:57 PMTAP_OKTA_SERVICE_URL
and TAP_OKTA_API_KEY
set in your ENVvisch
11/24/2021, 2:58 PMversion: 1
send_anonymous_usage_stats: true
project_id: 253fc4ee-65ff-46dd-99d5-fbadaaf4009e
plugins:
extractors:
- name: tap-okta
namespace: tap_okta
pip_url: git+<https://github.com/isabella232/tap-okta.git>
executable: tap-okta
capabilities:
- catalog
- discover
settings:
- name: api_key
- name: service_url
config:
api_key: abc
service_url: <https://abc.com/>
select:
- '*.*'
loaders:
- name: target-csv
variant: hotgluexyz
pip_url: git+<https://github.com/hotgluexyz/target-csv.git@0.3.3>
visch
11/24/2021, 2:58 PMvisch
11/24/2021, 2:58 PMmeltano invoke tap-okta
{"type": "SCHEMA", "stream": "users", "schema": {"type": "object", "properties": {"id": {"type": ["null", "string"]}, "status": {"type": ["null", "string"]}, "created": {"type": ["null", "string"], "format": "date-time"}, "activated": {"type": ["null", "string"]}, "statusChanged": {"type": ["null", "string"], "format": "date-time"}, "lastLogin": {"type": ["null", "string"], "format": "date-time"}, "lastUpdated": {"type": ["null", "string"], "format": "date-time"}, "passwordChanged": {"type": ["null", "string"], "format": "date-time"}, "profile": {"type": ["null", "object"], "properties": {"ssoid": {"type": ["null", "string"]}, "firstName": {"type": ["null", "string"]}, "lastName": {"type": ["null", "string"]}, "mobilePhone": {"type": ["null", "string"]}, "secondEmail": {"type": ["null", "string"]}, "grpList": {"type": ["null", "string"]}, "login": {"type": ["null", "string"]}, "email": {"type": ["null", "string"]}}}}}, "key_properties": ["id"]}
This doesn't failvisch
11/24/2021, 2:59 PMvisch
11/24/2021, 3:00 PMvisch
11/24/2021, 3:00 PMmeltano invoke tap-okta --catalog catalog.json
This is the proper commandvisch
11/24/2021, 3:00 PMmeltano invoke tap-okta -c catalog.json
is bogus from https://meltano.slack.com/archives/C013EKWA2Q1/p1637764690089100?thread_ts=1637697194.083200&cid=C013EKWA2Q1visch
11/24/2021, 3:01 PMvisch
11/24/2021, 3:01 PMvisch
11/24/2021, 3:02 PMvisch
11/24/2021, 3:03 PMmeltano invoke tap-okta --catalog catalog.json
{"type": "SCHEMA", "stream": "users", "schema": {"type": "object", "properties": {"id": {"type": ["null", "string"]}, "status": {"type": ["null", "string"]}, "created": {"type": ["null", "string"], "format": "date-time"}, "activated": {"type": ["null", "string"]}, "statusChanged": {"type": ["null", "string"], "format": "date-time"}, "lastLogin": {"type": ["null", "string"], "format": "date-time"}, "lastUpdated": {"type": ["null", "string"], "format": "date-time"}, "passwordChanged": {"type": ["null", "string"], "format": "date-time"}, "profile": {"type": ["null", "object"], "properties": {"ssoid": {"type": ["null", "string"]}, "firstName": {"type": ["null", "string"]}, "lastName": {"type": ["null", "string"]}, "mobilePhone": {"type": ["null", "string"]}, "secondEmail": {"type": ["null", "string"]}, "grpList": {"type": ["null", "string"]}, "login": {"type": ["null", "string"]}, "email": {"type": ["null", "string"]}}}}}, "key_properties": ["id"]}
(.venv) visch@visch-ubuntu:~/git/sandbox/oktatest$ echo $?
1
visch
11/24/2021, 3:03 PMpat_nadolny
11/24/2021, 3:04 PMpat_nadolny
11/24/2021, 3:05 PMpat_nadolny
11/24/2021, 3:07 PMvisch
11/24/2021, 3:34 PMpath
based on context
. The issue is to do this you kind of have to bastardize the path, context "auto fill" that happens. By doing something like
@property
def path:
return "{dynamicurl}"
And set the initial context.dynamicurl
equal to the first url, and update that based on the rel
somewhere like in post_process()
That would do the trick I thinktim_frazer
11/24/2021, 4:10 PMtim_frazer
11/24/2021, 4:10 PMdef get_next_page_token(
self,
response: requests.Response,
previous_token: Optional[Any]
) -> Optional[Any]:
"""Return a token for identifying next page or None if no more pages."""
response_links = requests.utils.parse_header_links(response.headers['Link'].rstrip('>').replace('>,<', ',<'))
for link in response_links:
if link['rel'] == 'next':
next_page_token = link['url']
else:
next_page_token = None
return next_page_token
tim_frazer
11/24/2021, 4:11 PMtim_frazer
11/24/2021, 4:13 PMtim_frazer
11/24/2021, 7:45 PMtim_frazer
11/24/2021, 7:45 PM"""REST client handling, including oktaStream base class."""
import requests
from pathlib import Path
from typing import Any, Dict, Optional, Union, List, Iterable
from memoization import cached
from singer_sdk.helpers.jsonpath import extract_jsonpath
from singer_sdk.streams import RESTStream
from singer_sdk.authenticators import APIKeyAuthenticator
SCHEMAS_DIR = Path(__file__).parent / Path("./schemas")
class oktaStream(RESTStream):
"""okta stream class."""
limit: int = 10
@property
def url_base(self) -> str:
"""Return the API URL root, configurable via tap settings."""
return self.config["api_url"]
@property
def authenticator(self) -> APIKeyAuthenticator:
"""Return a new authenticator object."""
return APIKeyAuthenticator.create_for_stream(
self,
key="apikey",
value=self.config.get("api_key"),
location="header"
)
@property
def http_headers(self) -> dict:
"""Return the http headers needed."""
headers = {}
headers["Authorization"] = "SSWS " + self.config.get("api_key")
return headers
def get_next_page_token(
self,
response: requests.Response,
previous_token: Optional[Any]
) -> Optional[Any]:
"""Return a token for identifying next page or None if no more pages."""
response_links = requests.utils.parse_header_links(response.headers['Link'].rstrip('>').replace('>,<', ',<'))
for link in response_links:
if link['rel'] == 'next':
next_page_token = link['url']
else:
next_page_token = None
return next_page_token
def get_url_params(
self,
context: Optional[dict],
next_page_token: Optional[Any]
) -> Dict[str, Any]:
"""Return a dictionary of values to be used in URL parameterization."""
params: dict = {}
params["limit"] = self.limit
if next_page_token:
params["page"] = next_page_token
if self.replication_key:
params["sort"] = "asc"
params["order_by"] = self.replication_key
return params
tim_frazer
11/24/2021, 7:46 PMRuntimeError: Loop detected in pagination. Pagination token
tim_frazer
11/24/2021, 7:47 PMtim_frazer
11/24/2021, 7:47 PMpat_nadolny
11/24/2021, 8:02 PMtim_frazer
11/24/2021, 8:02 PM<https://staging-auth.xxx.com/api/v1/users?limit=10>
2nd pass gets
<https://staging-auth.xxx.com/api/v1/users?after=200u13gd20mpR1CELg1d7&limit=10>
tim_frazer
11/24/2021, 8:03 PMpat_nadolny
11/24/2021, 8:09 PMget_url
instead of get_next_page_token
since youre really retrieving the whole link from the header linkstim_frazer
11/24/2021, 8:11 PMvisch
11/24/2021, 10:01 PMtim_frazer
11/24/2021, 10:17 PMtim_frazer
11/24/2021, 10:17 PMpat_nadolny
11/24/2021, 10:30 PMrequest_records
and get_url
methods to store the link and keep reusing it until its out of recordspat_nadolny
11/24/2021, 10:30 PMmonika_rajput
06/09/2022, 3:40 PMmonika_rajput
06/09/2022, 3:40 PMtim_frazer
06/09/2022, 3:41 PMtim_frazer
06/09/2022, 3:41 PMmonika_rajput
06/09/2022, 4:21 PMsean_glynn
06/09/2022, 4:37 PMmonika_rajput
06/09/2022, 4:41 PMmonika_rajput
06/09/2022, 4:43 PMmonika_rajput
06/14/2022, 7:13 PMreturn self.scan_once(s, idx=_w(s, idx).end())
target-csv | simplejson.scanner.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
tap-shopify | Traceback (most recent call last):
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/bin/tap-shopify", line 8, in <module>
tap-shopify | sys.exit(Tapshopify.cli())
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/lib/python3.8/site-packages/click/core.py", line 1130, in __call__
tap-shopify | return self.main(*args, **kwargs)
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/lib/python3.8/site-packages/click/core.py", line 1055, in main
tap-shopify | rv = self.invoke(ctx)
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/lib/python3.8/site-packages/click/core.py", line 1404, in invoke
tap-shopify | return ctx.invoke(self.callback, **ctx.params)
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/lib/python3.8/site-packages/click/core.py", line 760, in invoke
tap-shopify | return __callback(*args, **kwargs)
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/lib/python3.8/site-packages/singer_sdk/tap_base.py", line 499, in cli
tap-shopify | tap.sync_all()
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/lib/python3.8/site-packages/singer_sdk/tap_base.py", line 379, in sync_all
tap-shopify | stream.sync()
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/lib/python3.8/site-packages/singer_sdk/streams/core.py", line 1020, in sync
tap-shopify | self._sync_records(context)
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/lib/python3.8/site-packages/singer_sdk/streams/core.py", line 946, in _sync_records
tap-shopify | for record_result in self.get_records(current_context):
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/lib/python3.8/site-packages/singer_sdk/streams/rest.py", line 424, in get_records
tap-shopify | for record in self.request_records(context):
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/tap_shopify/client.py", line 111, in request_records
tap-shopify | resp = decorated_request(prepared_request, context)
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/lib/python3.8/site-packages/backoff/_sync.py", line 94, in retry
tap-shopify | ret = target(*args, **kwargs)
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/lib/python3.8/site-packages/singer_sdk/streams/rest.py", line 235, in _request
tap-shopify | self.validate_response(response)
tap-shopify | File "/Users/monika/Desktop/tap-shopify-users/.meltano/extractors/tap-shopify/venv/lib/python3.8/site-packages/singer_sdk/streams/rest.py", line 165, in validate_response
tap-shopify | raise FatalAPIError(msg)
tap-shopify | singer_sdk.exceptions.FatalAPIError: 400 Client Error: Bad Request for path: /users.json
meltano | DEBUG Deleted configuration at /Users/monika/Desktop/tap-shopify-users/.meltano/run/elt/2022-06-14T183046--tap-shopify--target-csv/8bb65e72-0e2f-4189-8499-982a3abd68af/target.002fca8f-ba7f-42cc-b617-c4f3203e6e45.config.json
tim_frazer
06/14/2022, 7:20 PMsean_glynn
06/15/2022, 8:59 AMsean_glynn
06/15/2022, 9:01 AMusers
stream is invalid. You should check that the schema defined in your users.json
conforms to the API's data model. I would recommend testing the API with a simple python requests script and parse the json response to ensure you are getting the expected object. Even a curl command or postmanmonika_rajput
07/04/2022, 8:10 AMmonika_rajput
07/04/2022, 8:27 AMmonika_rajput
07/04/2022, 8:36 AM