def test_should_return_to_initial_state_dev(mock_get_imports,
                                            looker_client: LookerClient):
    # Set up starting branch and workspace
    looker_client.update_workspace("dev")

    manager = LookerBranchManager(looker_client, LOOKER_PROJECT)
    assert manager.init_state.workspace == "dev"
    with manager():
        assert looker_client.get_workspace() == "production"
    assert looker_client.get_workspace() == "dev"
def test_manage_other_branch_with_import_projects(mock_time_hash,
                                                  looker_client: LookerClient):
    """User is on branch A, checkout branch B and test.

    The manager should checkout branch B, test, then checkout branch A.

    We are setting import projects to True. The manager should create a temp branch
    in the dependent project, and clean it up at the end.

    """
    # Set up starting branch and workspace
    looker_client.update_workspace("dev")
    starting_branch = "pytest"
    looker_client.checkout_branch(LOOKER_PROJECT, starting_branch)
    dependent_project = "welcome_to_looker"

    new_branch = "pytest-additional"
    assert new_branch != starting_branch
    manager = LookerBranchManager(looker_client, LOOKER_PROJECT)
    assert manager.init_state.branch == starting_branch

    manager(branch=new_branch).__enter__()
    assert not manager.is_temp_branch
    dependent_project_manager = manager.import_managers[0]
    assert dependent_project_manager.is_temp_branch
    temp_branch = dependent_project_manager.branch
    assert looker_client.get_active_branch_name(LOOKER_PROJECT) == new_branch
    assert looker_client.get_active_branch_name(
        dependent_project) == temp_branch
    manager.__exit__()
    assert looker_client.get_active_branch_name(
        LOOKER_PROJECT) == starting_branch
    assert (looker_client.get_active_branch_name(dependent_project) ==
            dependent_project_manager.init_state.branch)
    assert temp_branch not in looker_client.get_all_branches(dependent_project)
def test_manage_prod_with_advanced_deploy(mock_get_imports,
                                          looker_client: LookerClient):
    # Set up starting branch and workspace
    project = "spectacles-advanced-deploy"
    looker_client.update_workspace("production")
    commit = looker_client.get_active_branch(project)["ref"]

    manager = LookerBranchManager(looker_client, project)
    assert manager.init_state.workspace == "production"
    assert manager.init_state.commit == commit
    with manager():
        assert looker_client.get_workspace() == "production"
Exemplo n.º 4
0
def looker_client(record_mode) -> Iterable[LookerClient]:
    with vcr.use_cassette(
        "tests/cassettes/init_client.yaml",
        filter_post_data_parameters=["client_id", "client_secret"],
        filter_headers=["Authorization"],
        record_mode=record_mode,
    ):
        client = LookerClient(
            base_url="https://spectacles.looker.com",
            client_id=os.environ.get("LOOKER_CLIENT_ID", ""),
            client_secret=os.environ.get("LOOKER_CLIENT_SECRET", ""),
        )
        client.update_workspace(project="eye_exam", workspace="production")
        yield client
Exemplo n.º 5
0
 def __init__(
     self,
     base_url: str,
     project: str,
     branch: str,
     client_id: str,
     client_secret: str,
     port: int = 19999,
     api_version: float = 3.1,
     remote_reset: bool = False,
 ):
     self.project = project
     self.client = LookerClient(base_url, client_id, client_secret, port,
                                api_version)
     self.client.update_session(project, branch, remote_reset)
Exemplo n.º 6
0
def test_bad_authentication_request_should_raise_looker_api_error():
    with pytest.raises(LookerApiError):
        LookerClient(
            base_url="https://spectacles.looker.com",
            client_id=os.environ.get("LOOKER_CLIENT_ID"),
            client_secret="xxxxxxxxxxxxxx",
        )
Exemplo n.º 7
0
def looker_client() -> Iterable[LookerClient]:
    with vcr.use_cassette(
            "tests/cassettes/init_client.yaml",
            filter_post_data_parameters=["client_id", "client_secret"],
            filter_headers=["Authorization"],
            record_mode="all",
            before_record_response=filter_access_token,
            decode_compressed_response=True,
    ):
        client = LookerClient(
            base_url="https://spectacles.looker.com",
            client_id=os.environ.get("LOOKER_CLIENT_ID", ""),
            client_secret=os.environ.get("LOOKER_CLIENT_SECRET", ""),
        )
        client.update_workspace("production")
        yield client
def test_manage_with_ref_not_present_in_local_repo(
    mock_time_hash,
    mock_get_imports,
    remote_repo,
    test_remote_branch,
    looker_client: LookerClient,
):
    # Create a commit on an external branch directly on the GitHub remote
    content = remote_repo.get_contents("README.md", ref="master")
    result = remote_repo.update_file(
        content.path,
        message="Updating file",
        content=".",
        sha=content.sha,
        branch=TMP_REMOTE_BRANCH,
    )
    commit = result["commit"].sha

    manager = LookerBranchManager(looker_client, LOOKER_PROJECT)
    with manager(commit=commit):
        assert manager.is_temp_branch
        assert manager.commit == commit
        branch_info = looker_client.get_active_branch(LOOKER_PROJECT)
        assert branch_info["ref"] == branch_info["remote_ref"]
        assert branch_info["ref"] == commit
Exemplo n.º 9
0
 def __init__(
     self,
     base_url: str,
     project: str,
     branch: str,
     client_id: str,
     client_secret: str,
     port: int = 19999,
     api_version: float = 3.1,
     remote_reset: bool = False,
     import_projects: bool = False,
     commit_ref: Optional[str] = None,
 ):
     self.project = project
     self.import_projects = import_projects
     self.client = LookerClient(base_url, client_id, client_secret, port,
                                api_version)
     self.branch_manager = LookerBranchManager(
         self.client,
         project,
         branch,
         remote_reset=remote_reset,
         import_projects=import_projects,
         commit_ref=commit_ref,
     )
Exemplo n.º 10
0
class Runner:
    """Runs validations and returns JSON-style dictionaries with validation results.

    Args:
        base_url: Base URL for the Looker instance, e.g. https://mycompany.looker.com.
        project: Name of the Looker project to use.
        branch: Name of the Git branch to check out.
        client_id: Looker API client ID.
        client_secret: Looker API client secret.
        port: Desired API port to use for requests.
        api_version: Desired API version to use for requests.

    Attributes:
        client: Looker API client used for making requests.

    """
    def __init__(
        self,
        base_url: str,
        project: str,
        branch: str,
        client_id: str,
        client_secret: str,
        port: int = 19999,
        api_version: float = 3.1,
        remote_reset: bool = False,
    ):
        self.project = project
        self.client = LookerClient(base_url, client_id, client_secret, port,
                                   api_version)
        self.client.update_session(project, branch, remote_reset)

    @log_duration
    def validate_sql(self,
                     selectors: List[str],
                     mode: str = "batch",
                     concurrency: int = 10) -> List[dict]:
        sql_validator = SqlValidator(self.client, self.project, concurrency)
        sql_validator.build_project(selectors)
        errors = sql_validator.validate(mode)
        return [vars(error) for error in errors]

    @log_duration
    def validate_data_tests(self):
        data_test_validator = DataTestValidator(self.client, self.project)
        errors = data_test_validator.validate()
        return [vars(error) for error in errors]
Exemplo n.º 11
0
def test_unsupported_api_version_should_raise_error():
    with pytest.raises(SpectaclesException):
        LookerClient(
            base_url="https://spectacles.looker.com",
            client_id=os.environ.get("LOOKER_CLIENT_ID"),
            client_secret=os.environ.get("LOOKER_CLIENT_SECRET"),
            api_version=3.0,
        )
Exemplo n.º 12
0
def test_manage_current_branch_with_ref(mock_time_hash, mock_get_imports,
                                        looker_client: LookerClient):
    """User is on branch A, checkout branch A with a commit ref and test.

    The manager should create a new temp branch based on branch A, checkout the temp
    branch, test, checkout branch A, and delete the temp branch.

    """
    # Set up starting branch and workspace
    looker_client.update_workspace("dev")
    starting_branch = "pytest"
    looker_client.checkout_branch(LOOKER_PROJECT, starting_branch)
    commit = "e2d21d"

    manager = LookerBranchManager(looker_client, LOOKER_PROJECT)
    assert manager.init_state.branch == starting_branch

    manager(commit=commit).__enter__()
    assert manager.is_temp_branch
    temp_branch = manager.branch
    branch_info = looker_client.get_active_branch(LOOKER_PROJECT)
    assert branch_info["name"] == temp_branch
    assert branch_info["ref"][:6] == commit
    manager.__exit__()
    branch_info = looker_client.get_active_branch(LOOKER_PROJECT)
    assert branch_info["name"] == starting_branch
    assert branch_info["ref"][:6] != commit
    assert temp_branch not in looker_client.get_all_branches(LOOKER_PROJECT)
Exemplo n.º 13
0
def test_authenticate_should_set_session_headers(mock_post, monkeypatch):
    mock_looker_version = Mock(spec=LookerClient.get_looker_release_version)
    mock_looker_version.return_value("1.2.3")
    monkeypatch.setattr(LookerClient, "get_looker_release_version", mock_looker_version)

    mock_post_response = Mock(spec=requests.Response)
    mock_post_response.json.return_value = dict(
        access_token="test_access_token", token_type="Bearer", expires_in=3600
    )
    mock_post.return_value = mock_post_response
    client = LookerClient("base_url", "client_id", "client_secret")
    assert client.session.headers == {"Authorization": "token test_access_token"}
Exemplo n.º 14
0
def client(monkeypatch):
    mock_authenticate = Mock(spec=LookerClient.authenticate)
    mock_validate_looker_release_version = Mock(
        spec=LookerClient.validate_looker_release_version)
    mock_validate_looker_release_version.return_value = True
    monkeypatch.setattr(LookerClient, "authenticate", mock_authenticate)
    monkeypatch.setattr(
        LookerClient,
        "validate_looker_release_version",
        mock_validate_looker_release_version,
    )
    return LookerClient(TEST_BASE_URL, TEST_CLIENT_ID, TEST_CLIENT_SECRET)
Exemplo n.º 15
0
 def __init__(
     self,
     base_url: str,
     project: str,
     client_id: str,
     client_secret: str,
     port: int = 19999,
     api_version: float = 3.1,
     remote_reset: bool = False,
 ):
     self.project = project
     self.client = LookerClient(base_url, client_id, client_secret, port,
                                api_version)
     self.branch_manager = LookerBranchManager(self.client, project,
                                               remote_reset)
Exemplo n.º 16
0
def test_manage_current_branch_with_import_projects(
        mock_time_hash, looker_client: LookerClient):
    """User is on branch A, checkout branch A and test.

    We should not import any temp branches because we are staying in the production
    workspace.

    The manager should not perform any branch checkouts, just test.

    """
    # Set up starting branch and workspace
    starting_branch = "master"
    looker_client.update_workspace("production")

    manager = LookerBranchManager(looker_client, LOOKER_PROJECT)
    assert manager.init_state.branch == starting_branch

    manager().__enter__()
    assert not manager.is_temp_branch
    assert looker_client.get_active_branch_name(
        LOOKER_PROJECT) == starting_branch
    manager.__exit__()
    assert looker_client.get_active_branch_name(
        LOOKER_PROJECT) == starting_branch
Exemplo n.º 17
0
def test_manage_with_ref_import_projects(mock_time_hash,
                                         looker_client: LookerClient):
    """User is on branch A, checkout branch B and test.

    The manager should create a new temp branch based on branch B, checkout the temp
    branch, test, checkout branch A, and delete the temp branch.

    We are setting import projects to True. The manager should create a temp branch
    in the dependent project, and clean it up at the end.

    """
    # Set up starting branch and workspace
    looker_client.update_workspace("production")
    dependent_project = "welcome_to_looker"
    commit = "e2d21d"

    manager = LookerBranchManager(looker_client, LOOKER_PROJECT)
    assert manager.init_state.workspace == "production"
    branch_info = looker_client.get_active_branch(LOOKER_PROJECT)
    assert branch_info["ref"][:6] != commit

    with manager(commit=commit):
        assert manager.is_temp_branch
        assert manager.commit and manager.commit[:6] == commit
        branch_info = looker_client.get_active_branch(manager.project)
        assert branch_info["ref"][:6] == commit
        for import_manager in manager.import_managers:
            branch = looker_client.get_active_branch_name(
                import_manager.project)
            assert import_manager.branch == branch

    branch_info = looker_client.get_active_branch(LOOKER_PROJECT)
    assert branch_info["ref"][:6] != commit

    looker_client.update_workspace("dev")
    all_branches = set(looker_client.get_all_branches(dependent_project))
    # Confirm that no temp branches still remain
    temp_branches = set(import_manager.branch
                        for import_manager in manager.import_managers)
    assert temp_branches.isdisjoint(all_branches)
Exemplo n.º 18
0
def test_manage_current_branch(mock_get_imports, looker_client: LookerClient):
    """User is on branch A, checkout branch A and test.

    The manager should not perform any branch checkouts, just test.

    """
    # Set up starting branch and workspace
    looker_client.update_workspace("dev")
    branch = "pytest"
    looker_client.checkout_branch(LOOKER_PROJECT, branch)

    manager = LookerBranchManager(looker_client, LOOKER_PROJECT)
    assert manager.init_state.branch == branch
    manager(branch=branch).__enter__()
    assert looker_client.get_active_branch_name(LOOKER_PROJECT) == branch
    manager.__exit__()
    assert looker_client.get_active_branch_name(LOOKER_PROJECT) == branch
Exemplo n.º 19
0
def test_manage_other_branch(mock_get_imports, looker_client: LookerClient):
    """User is on branch A, checkout branch B and test.

    The manager should checkout branch B, test, then checkout branch A.

    """
    # Set up starting branch and workspace
    looker_client.update_workspace("dev")
    starting_branch = "pytest"
    looker_client.checkout_branch(LOOKER_PROJECT, starting_branch)

    new_branch = "pytest-additional"
    assert new_branch != starting_branch
    manager = LookerBranchManager(looker_client, LOOKER_PROJECT)
    assert manager.init_state.branch == starting_branch

    manager(branch=new_branch).__enter__()
    assert looker_client.get_active_branch_name(LOOKER_PROJECT) == new_branch
    manager.__exit__()
    assert looker_client.get_active_branch_name(
        LOOKER_PROJECT) == starting_branch
Exemplo n.º 20
0
def test_authenticate_sets_session_headers(mock_post):
    mock_response = Mock(spec=requests.Response)
    mock_response.json.return_value = {"access_token": "test_access_token"}
    mock_post.return_value = mock_response
    client = LookerClient(TEST_BASE_URL, TEST_CLIENT_ID, TEST_CLIENT_SECRET)
    assert client.session.headers == {"Authorization": f"token test_access_token"}