Skip to content

Commit

Permalink
Merge pull request #96 from sassoftware/develop
Browse files Browse the repository at this point in the history
Merge develop to main branch for release
  • Loading branch information
kevinlinglesas authored Apr 29, 2021
2 parents 670f0b1 + 553d89b commit 9225483
Show file tree
Hide file tree
Showing 25 changed files with 1,015 additions and 46 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Tool support for the latest release of SAS Viya:
* [SAS Viya Deployment Report](deployment_report)
* [SAS Viya Log Download Tool](download_pod_logs)
* [Pre-installation of SAS Viya System Requirements](pre_install_report)
* [SAS Viya LDAP Validator](ldap_validator)

## Contributing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,11 +385,19 @@ def test_define_service_to_ingress_relationships(gathered_resources: Dict) -> No

# makes sure relationship is defined and exists
assert ReportKeys.ResourceDetails.Ext.RELATIONSHIPS_LIST in service[ReportKeys.ResourceDetails.EXT_DICT]
assert len(service[ReportKeys.ResourceDetails.EXT_DICT][ReportKeys.ResourceDetails.Ext.RELATIONSHIPS_LIST]) == 1
assert len(service[ReportKeys.ResourceDetails.EXT_DICT][ReportKeys.ResourceDetails.Ext.RELATIONSHIPS_LIST]) == 2

# get the relationship
# get the first relationship
rel: Dict = service[ReportKeys.ResourceDetails.EXT_DICT][ReportKeys.ResourceDetails.Ext.RELATIONSHIPS_LIST][0]

# make sure the relationship attributes are correct
assert rel[ReportKeys.ResourceDetails.Ext.Relationship.KIND] == KubernetesResource.Kinds.INGRESS
assert rel[ReportKeys.ResourceDetails.Ext.Relationship.NAME] == \
TestVals.COMPONENT_SAS_ANNOTATIONS_INGRESS_NAME_DEPRECATED_DEFINITION

# get the second relationship
rel: Dict = service[ReportKeys.ResourceDetails.EXT_DICT][ReportKeys.ResourceDetails.Ext.RELATIONSHIPS_LIST][1]

# make sure the relationship attributes are correct
assert rel[ReportKeys.ResourceDetails.Ext.Relationship.KIND] == KubernetesResource.Kinds.INGRESS
assert rel[ReportKeys.ResourceDetails.Ext.Relationship.NAME] == TestVals.COMPONENT_SAS_ANNOTATIONS_INGRESS_NAME
Expand Down
21 changes: 17 additions & 4 deletions deployment_report/model/utils/viya_deployment_report_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def gather_resource_details(kubectl: KubectlInterface, gathered_resources: Dict,
owner_reference[KubernetesResource.Keys.NAME])

resource_relationship_list.append(relationship)
elif owner_references is None and is_owning_resource:
else:
# if this resource doesn't have any owner references, but it does own resources, use it as the #
# resource to determine a component name as this must be the resource furthest upstream #
# (i.e. a probable controller) #
Expand Down Expand Up @@ -162,9 +162,22 @@ def define_service_to_ingress_relationships(services: Dict, ingresses: Dict) ->

# iterate over all http paths to process each backend defined #
for http_path in http_paths:
# get the Service name for this path #
service_name: Text = \
http_path[KubernetesResource.Keys.BACKEND][KubernetesResource.Keys.SERVICE_NAME]

# init the service name var
service_name: Text = ""

# check if this is the current Ingress definition schema
if ingress.get_api_version().startswith("networking.k8s.io"):
# get the Service name for this path #
service_name = \
http_path[KubernetesResource.Keys.BACKEND][KubernetesResource.Keys.SERVICE][
KubernetesResource.Keys.NAME]

# otherwise, use the old definition schema
else:
# get the Service name for this path
service_name = \
http_path[KubernetesResource.Keys.BACKEND][KubernetesResource.Keys.SERVICE_NAME]

try:
# get the Service associated with this path #
Expand Down
38 changes: 28 additions & 10 deletions download_pod_logs/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def download_logs(self, selected_components: Optional[List[Text]] = None, tail:
error_pods: List[Tuple[Text, Text]] = list()
for process in write_log_processes:
try:
err_info: List[Tuple[Optional[Text], Text]] = process.get_process().get(timeout=self._wait)
err_info: Optional[List[Tuple[Optional[Text], Text]]] = process.get_process().get(timeout=self._wait)

# add the error message, if returned
if err_info:
Expand All @@ -159,7 +159,7 @@ def download_logs(self, selected_components: Optional[List[Text]] = None, tail:

@staticmethod
def _write_log(kubectl: KubectlInterface, pod: KubernetesResource, tail: int, output_dir: Text,
noparse: bool = False) -> List[Tuple[Optional[Text], Text]]:
noparse: bool = False) -> Optional[List[Tuple[Optional[Text], Text]]]:
"""
Internal method used for gathering the status and log for each container in the provided pod and writing
the gathered information to an on-disk log file.
Expand Down Expand Up @@ -216,15 +216,33 @@ def _write_log(kubectl: KubectlInterface, pod: KubernetesResource, tail: int, ou
output_file.writelines(("#" * 50) + "\n\n")

# call kubectl to get the log for this container

log: List[AnyStr] = list()
try:
log: List[AnyStr] = kubectl.logs(pod_name=f"{pod.get_name()} {container_status.get_name()}",
all_containers=False, prefix=False, tail=tail)

except CalledProcessError:
err_msg = (f"ERROR: A log could not be retrieved for the container [{container_status.get_name()}] "
f"in pod [{pod.get_name()}] in namespace [{kubectl.get_namespace()}]")
log: List[AnyStr] = [err_msg]
err_info.append((container_status.get_name(), pod.get_name()))
log = kubectl.logs(pod_name=pod.get_name(), container_name=container_status.get_name(),
prefix=False, tail=tail, ignore_errors=False)
except CalledProcessError as e:
# container log has error, we'll retrieve log from initContainers
# add log from previous container call
log += [e.output.decode("utf-8")]
initcontainers: Optional[List[Dict]]
initcontainers = pod.get_spec_value(KubernetesResource.Keys.INIT_CONTAINERS)

if initcontainers:
for initcontainer in initcontainers:
container_name: Optional[Text] = initcontainer.get("name")
log += ["\n" + "#" * 50] + [f"# Log from initContainer: {container_name}"] + ["#" * 50]
try:
log += kubectl.logs(pod_name=pod.get_name(),
container_name=container_name, ignore_errors=True, prefix=False,
tail=tail)

except CalledProcessError:
err_msg = (f"ERROR: A log could not be retrieved for the container "
f"[{container_status.get_name()}] "
f"in pod [{pod.get_name()}] in namespace [{kubectl.get_namespace()}]")
err_info.append((container_status.get_name(), pod.get_name()))
log += [err_msg]

# parse any structured logging
if noparse:
Expand Down
51 changes: 51 additions & 0 deletions ldap_validator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# SAS Viya LDAP Validator

This tool validates the accuracy of the LDAP properties represented in a
sitedefault.yaml file by connecting to the LDAP server and fetching some of the
Users and Groups attributes. When finished, the tool displays a message that
indicates if the validation was successful or not. If the tool fails to validate
connection using the settings in the provided sitedefault.yaml file, a non-zero
code is returned.
You must _run the tool as an Administrator_.

**Important:** This tool validates the LDAP settings in the sitedefault.yaml file
only. It does not validate the entire sitedefault.yaml file. If you use a
sitedefault.yaml file, this tool indicates if the tested LDAP settings are correct.
However, that is still not a full guarantee of success since the tool is not able
to check every parameter in the sitedefault.yaml file for accuracy.

**Note:** SAS recommends that you do not use the sitedefault.yaml file for the
initial deployment of your SAS Viya software. For more information, see [Add a sitedefault File to Your Deployment](http://documentation.sas.com/?cdcId=itopscdc&cdcVersion=default&docsetId=dplyml0phy0dkr&docsetTarget=n08u2yg8tdkb4jn18u8zsi6yfv3d.htm#n19f4zubzxljtdn12lo0nkv4n4cf).

## Prerequisites

The validator tool requires Python 3.6 or higher.

### Required Python Packages

SAS Viya ARK tools require third-party packages be installed before use. All required packages can be installed using the
provided `requirements.txt`:

```commandline
$ python3 -m pip install -r requirements.txt
```

Download the latest version of this tool and update required packages with every new software order.

## Usage

The following command provides usage details:

```
$ python3 viya-ark.py ldap_validator --help
```
The following example executes the LDAP Validation script against the specified sitedefault.yaml.

```commandline
$ python3 viya-ark.py ldap_validator -s /path/to/sitedefault.yaml
```

## Log Output

The tool generates a plain text log file,`ldap_validator_<timestamp>.log.

Empty file added ldap_validator/__init__.py
Empty file.
Loading

0 comments on commit 9225483

Please sign in to comment.