Beispiel #1
0
    def _get_profile_data(profile, profile_name, target_name):
        if 'outputs' not in profile:
            raise DbtProfileError(
                "outputs not specified in profile '{}'".format(profile_name))
        outputs = profile['outputs']

        if target_name not in outputs:
            outputs = '\n'.join(' - {}'.format(output) for output in outputs)
            msg = ("The profile '{}' does not have a target named '{}'. The "
                   "valid target names for this profile are:\n{}".format(
                       profile_name, target_name, outputs))
            raise DbtProfileError(msg, result_type='invalid_target')
        profile_data = outputs[target_name]
        return profile_data
Beispiel #2
0
 def render_schema_source(self, as_parsed):
     try:
         return deep_map(self._render_schema_source_data, as_parsed)
     except RecursionException:
         raise DbtProfileError(
             'Cycle detected: schema.yml input has a reference to itself',
             project=as_parsed)
Beispiel #3
0
 def validate(self):
     if self.credentials:
         self.credentials.validate()
     try:
         ProfileConfig(**self.to_profile_info(serialize_credentials=True))
     except ValidationException as exc:
         raise DbtProfileError(str(exc))
Beispiel #4
0
    def _credentials_from_profile(profile, profile_name, target_name):
        # credentials carry their 'type' in their actual type, not their
        # attributes. We do want this in order to pick our Credentials class.
        if 'type' not in profile:
            raise DbtProfileError(
                'required field "type" not found in profile {} and target {}'.
                format(profile_name, target_name))

        typename = profile.pop('type')
        try:
            credentials = create_credentials(typename, profile)
        except dbt.exceptions.RuntimeException as e:
            raise DbtProfileError(
                'Credentials in profile "{}", target "{}" invalid: {}'.format(
                    profile_name, target_name, str(e)))
        return credentials
Beispiel #5
0
 def render_profile_data(self, as_parsed):
     """Render the chosen profile entry, as it was parsed."""
     try:
         return deep_map(self._render_profile_data, as_parsed)
     except RecursionException:
         raise DbtProfileError(
             'Cycle detected: Profile input has a reference to itself',
             project=as_parsed)
Beispiel #6
0
 def validate(self):
     try:
         if self.credentials:
             self.credentials.to_dict(validate=True)
         ProfileConfig.from_dict(
             self.to_profile_info(serialize_credentials=True))
     except ValidationError as exc:
         raise DbtProfileError(validator_error_message(exc)) from exc
Beispiel #7
0
 def validate(self):
     try:
         if self.credentials:
             dct = self.credentials.to_dict(omit_none=True)
             self.credentials.validate(dct)
         dct = self.to_profile_info(serialize_credentials=True)
         ProfileConfig.validate(dct)
     except ValidationError as exc:
         raise DbtProfileError(validator_error_message(exc)) from exc
Beispiel #8
0
    def _get_profile_data(profile: Dict[str, Any], profile_name: str,
                          target_name: str) -> Dict[str, Any]:
        if 'outputs' not in profile:
            raise DbtProfileError(
                "outputs not specified in profile '{}'".format(profile_name))
        outputs = profile['outputs']

        if target_name not in outputs:
            outputs = '\n'.join(' - {}'.format(output) for output in outputs)
            msg = ("The profile '{}' does not have a target named '{}'. The "
                   "valid target names for this profile are:\n{}".format(
                       profile_name, target_name, outputs))
            raise DbtProfileError(msg, result_type='invalid_target')
        profile_data = outputs[target_name]

        if not isinstance(profile_data, dict):
            msg = (f"output '{target_name}' of profile '{profile_name}' is "
                   f"misconfigured in profiles.yml")
            raise DbtProfileError(msg, result_type='invalid_target')

        return profile_data
Beispiel #9
0
    def _credentials_from_profile(profile, profile_name, target_name):
        # avoid an import cycle
        from dbt.adapters.factory import load_plugin
        # credentials carry their 'type' in their actual type, not their
        # attributes. We do want this in order to pick our Credentials class.
        if 'type' not in profile:
            raise DbtProfileError(
                'required field "type" not found in profile {} and target {}'.
                format(profile_name, target_name))

        typename = profile.pop('type')
        try:
            cls = load_plugin(typename)
            credentials = cls.from_dict(profile)
        except (RuntimeException, ValidationError) as e:
            msg = str(e) if isinstance(e, RuntimeException) else e.message
            raise DbtProfileError(
                'Credentials in profile "{}", target "{}" invalid: {}'.format(
                    profile_name, target_name, msg)) from e

        return credentials
Beispiel #10
0
def read_profile(profiles_dir: str) -> Dict[str, Any]:
    path = os.path.join(profiles_dir, 'profiles.yml')

    contents = None
    if os.path.isfile(path):
        try:
            contents = load_file_contents(path, strip=False)
            yaml_content = load_yaml_text(contents)
            if not yaml_content:
                msg = f'The profiles.yml file at {path} is empty'
                raise DbtProfileError(
                    INVALID_PROFILE_MESSAGE.format(error_string=msg))
            return yaml_content
        except ValidationException as e:
            msg = INVALID_PROFILE_MESSAGE.format(error_string=e)
            raise ValidationException(msg) from e

    return {}
Beispiel #11
0
    def from_raw_profiles(
        cls,
        raw_profiles: Dict[str, Any],
        profile_name: str,
        renderer: ProfileRenderer,
        target_override: Optional[str] = None,
        threads_override: Optional[int] = None,
    ) -> 'Profile':
        """
        :param raw_profiles: The profile data, from disk as yaml.
        :param profile_name: The profile name to use.
        :param renderer: The config renderer.
        :param target_override: The target to use, if provided on the command
            line.
        :param threads_override: The thread count to use, if provided on the
            command line.
        :raises DbtProjectError: If there is no profile name specified in the
            project or the command line arguments
        :raises DbtProfileError: If the profile is invalid or missing, or the
            target could not be found
        :returns: The new Profile object.
        """
        if profile_name not in raw_profiles:
            raise DbtProjectError(
                "Could not find profile named '{}'".format(profile_name))

        # First, we've already got our final decision on profile name, and we
        # don't render keys, so we can pluck that out
        raw_profile = raw_profiles[profile_name]
        if not raw_profile:
            msg = (f'Profile {profile_name} in profiles.yml is empty')
            raise DbtProfileError(
                INVALID_PROFILE_MESSAGE.format(error_string=msg))
        user_cfg = raw_profiles.get('config')

        return cls.from_raw_profile_info(
            raw_profile=raw_profile,
            profile_name=profile_name,
            renderer=renderer,
            user_cfg=user_cfg,
            target_override=target_override,
            threads_override=threads_override,
        )
Beispiel #12
0
    def render_profile(
        cls,
        raw_profile: Dict[str, Any],
        profile_name: str,
        target_override: Optional[str],
        renderer: ProfileRenderer,
    ) -> Tuple[str, Dict[str, Any]]:
        """This is a containment zone for the hateful way we're rendering
        profiles.
        """
        # rendering profiles is a bit complex. Two constraints cause trouble:
        # 1) users should be able to use environment/cli variables to specify
        #    the target in their profile.
        # 2) Missing environment/cli variables in profiles/targets that don't
        #    end up getting selected should not cause errors.
        # so first we'll just render the target name, then we use that rendered
        # name to extract a profile that we can render.
        if target_override is not None:
            target_name = target_override
        elif 'target' in raw_profile:
            # render the target if it was parsed from yaml
            target_name = renderer.render_value(raw_profile['target'])
        else:
            target_name = 'default'
            logger.debug(
                "target not specified in profile '{}', using '{}'".format(
                    profile_name, target_name))

        raw_profile_data = cls._get_profile_data(raw_profile, profile_name,
                                                 target_name)

        try:
            profile_data = renderer.render_data(raw_profile_data)
        except CompilationException as exc:
            raise DbtProfileError(str(exc)) from exc
        return target_name, profile_data