cortexapps-cli 0.26.3__tar.gz → 0.26.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cortexapps-cli
3
- Version: 0.26.3
3
+ Version: 0.26.4
4
4
  Summary: Command Line Interface for cortexapps
5
5
  License: MIT
6
6
  Author: Cortex Apps
@@ -12,7 +12,8 @@ Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Requires-Dist: pyyaml (>=6.0.1,<7)
15
- Requires-Dist: requests (>=2.3.0,<3)
15
+ Requires-Dist: requests (>=2.32.3,<3)
16
+ Requires-Dist: urllib3 (>=2.2.2)
16
17
  Project-URL: Bug Tracker, https://github.com/cortexapps/cli/issues
17
18
  Project-URL: Changes, https://github.com/cortexapps/cli/blob/main/HISTORY.md
18
19
  Project-URL: Documentation, https://github.com/cortexapps/cli/blob/main/README.rst
@@ -100,7 +101,7 @@ If you have multiple Cortex instances, you can create a section for each, for ex
100
101
  api_key = REPLACE_WITH_YOUR_CORTEX_API_KEY
101
102
  base_url = https://app.cortex.mycompany.com
102
103
 
103
- **NOTE:** if not supplied, base_url defaults to :code:`https://app.getcortexapp.com`.
104
+ **NOTE:** if not supplied, base_url defaults to :code:`https://api.getcortexapp.com`.
104
105
 
105
106
  The CLI will retrieve configuration data from the :code:`[default]` section unless you pass the :code:`-t/--tenant` flag.
106
107
 
@@ -120,7 +121,7 @@ Environment Variables
120
121
  The CLI supports the following environment variables. If provided, the Cortex config file will not be read.
121
122
 
122
123
  - CORTEX_API_KEY
123
- - CORTEX_BASE_URL - this is optional if using Cortex cloud; defaults to `https://app.getcortexapp.com`
124
+ - CORTEX_BASE_URL - this is optional if using Cortex cloud; defaults to `https://api.getcortexapp.com`
124
125
 
125
126
  Example:
126
127
 
@@ -638,6 +639,136 @@ This recipe is helpful if you want to remove all Workday teams and import from s
638
639
  cortex teams delete -t ${team}
639
640
  done
640
641
 
642
+ -----------------------------------------------------------------------------
643
+ Add provider for all group type owners where provider is not listed
644
+ -----------------------------------------------------------------------------
645
+
646
+ This recipe adds the value of variable named ``provider`` to any owner for which **type = GROUP** and the provider field is not listed. This recipe can be used to address this issue from Cortex release notes:
647
+ ``Starting July 2nd (2024), any group type owners in the x-cortex-owners section of an entity descriptor will require a provider to be explicitly defined.``
648
+
649
+ Adjust the value of ``provider`` accordingly. It must be one of the providers listed in our `public docs <https://docs.cortex.io/docs/reference/basics/ownership>`_.
650
+
651
+ This recipe does the following:
652
+
653
+ - It runs the Cortex query as documented in the release notes to find all group type owners where the provider is not defined. The ``cortex queries`` parameter ``-f-`` indicates that the query input comes from stdin, provided by the here document (the content provided between the two 'EOF' delimiters).
654
+ - The recipe waits 10 minutes (denoted by parameter ``-x 600``) for the query to complete.
655
+ - It loops over the results of the Cortex query, adding the provider listed in the ``provider`` variable for any group owner where the provider is not defined in the entity.
656
+ - The contents of the entity descriptor are changed using yq and then passed as stdin to the cortex catalog subcommand to update the entity.
657
+
658
+ .. code:: bash
659
+
660
+ provider="GITHUB"
661
+ query_output="query.json"
662
+
663
+ cortex queries run -f- -w -x 600 > ${query_output} << EOF
664
+ jq(entity.descriptor(), "[.info.\"x-cortex-owners\" | .[] | select(.type | ascii_downcase == \"group\") | select(.provider == null)] | length") > 0
665
+ EOF
666
+
667
+ for entity in `cat ${query_output} | jq -r ".result[].tag"`
668
+ do
669
+ echo "entity = $entity"
670
+ cortex catalog descriptor -y -t ${entity} | yq "with(.info.x-cortex-owners[]; select(.type | downcase == \"group\") | select(.provider == null) | .provider = \"${provider}\" )" | cortex catalog create -f-
671
+ done
672
+
673
+ -----------------------------------------------------------------------------
674
+ Obfuscating a Cortex export
675
+ -----------------------------------------------------------------------------
676
+
677
+ This script will obfuscate a Cortex backup. This can be helpful for on-premise customers who may need to provide data to Cortex to help identify performance or usability issues.
678
+
679
+ .. code:: bash
680
+
681
+ # Works off an existing cortex CLI backup.
682
+ # - Create a backup with cortex CLI command: cortex backup export -z 10000
683
+ set -e
684
+ input=$1
685
+ output=$2
686
+
687
+ all_file=${output}/all.yaml
688
+ obfuscated_file=${output}/obfuscated.yaml
689
+
690
+ echo "Output directory: ${output}"
691
+ translate_file="${output}/translate.csv"
692
+
693
+ if [ ! -d ${output} ]; then
694
+ mkdir -p ${output}
695
+ fi
696
+
697
+ for yaml in `ls -1 ${input}/catalog/*`
698
+ do
699
+ entity=$(yq ${yaml} | yq ".info.x-cortex-tag")
700
+ new_entity=$(echo ${entity} | md5sum | cut -d' ' -f 1)
701
+ echo "${entity},${new_entity}" >> ${translate_file}
702
+ echo "Creating: $new_entity"
703
+ cat ${yaml} |\
704
+ yq ".info.\"x-cortex-tag\" = \"${new_entity}\" | \
705
+ .info.title=\"${new_entity}\" | \
706
+ del(.info.description) | \
707
+ del(.info.\"x-cortex-link\") | \
708
+ del(.info.\"x-cortex-links\") | \
709
+ del(.info.\"x-cortex-groups\") | \
710
+ del(.info.\"x-cortex-custom-metadata\") | \
711
+ del(.info.\"x-cortex-issues\") | \
712
+ del(.info.\"x-cortex-git\") | \
713
+ del(.info.\"x-cortex-slack\") | \
714
+ del(.info.\"x-cortex-oncall\") | \
715
+ with(.info; \
716
+ select(.\"x-cortex-team\".members != null) | .\"x-cortex-team\".members = {\"name\": \"Cortex User\", \"email\": \"user@example.com\"} \
717
+ )" >> ${all_file}
718
+ echo "---" >> ${all_file}
719
+ done
720
+
721
+ # The longer strings are translated first preventing substrings from being replaced in a longer string
722
+ cat ${translate_file} | sort -r > ${translate_file}.tmp && echo "entity,new_entity" > ${translate_file} && cat ${translate_file}.tmp >> ${translate_file} && rm ${translate_file}.tmp
723
+
724
+ python3 - ${all_file} ${translate_file} ${obfuscated_file} << EOF
725
+ import csv
726
+ import re
727
+ import sys
728
+
729
+ yaml_file = sys.argv[1]
730
+ translate_file = sys.argv[2]
731
+ output = sys.argv[3]
732
+
733
+ with open(yaml_file, 'r') as f:
734
+ bytes = f.read() # read entire file as bytes
735
+ with open(translate_file, newline='') as csvfile:
736
+ reader = csv.DictReader(csvfile)
737
+ for row in reader:
738
+ entity = row['entity']
739
+ new_entity = row['new_entity']
740
+ print("entity = " + entity + ", new_entity = " + new_entity)
741
+ bytes = bytes.replace("tag: " + entity, "tag: " + new_entity)
742
+ bytes = bytes.replace("name: " + entity, "name: " + new_entity)
743
+
744
+ f = open(output, "w")
745
+ f.write(bytes)
746
+ f.close()
747
+ EOF
748
+
749
+ # change all email addresses
750
+ sed -i 's/email:.*/email: user@example.com/' ${obfuscated_file}
751
+
752
+ # change all slack channel names
753
+ sed -i 's/channel:.*/channel: my-slack-channel/' ${obfuscated_file}
754
+
755
+ # copy export directory to new directory, without catalog YAML
756
+ rsync -av --exclude='catalog' ${input}/ ${output}
757
+ mkdir -p ${output}/catalog
758
+
759
+ # now split single file into multiple that can be passed as parameter to cortex catalog create -f
760
+ cd ${output}/catalog
761
+ yq --no-doc -s '"file_" + $index' ${obfuscated_file}
762
+
763
+ # tar it up
764
+ tar_file=$(basename ${output}).tar
765
+ cd ${output}
766
+ rm ${all_file}
767
+ rm ${translate_file}
768
+ tar -cvf ${tar_file} ./*
769
+
770
+ echo "Created: ${output}/${tar_file}"
771
+
641
772
  ====================================
642
773
 
643
774
  .. |PyPI download month| image:: https://img.shields.io/pypi/dm/cortexapps-cli.svg
@@ -79,7 +79,7 @@ If you have multiple Cortex instances, you can create a section for each, for ex
79
79
  api_key = REPLACE_WITH_YOUR_CORTEX_API_KEY
80
80
  base_url = https://app.cortex.mycompany.com
81
81
 
82
- **NOTE:** if not supplied, base_url defaults to :code:`https://app.getcortexapp.com`.
82
+ **NOTE:** if not supplied, base_url defaults to :code:`https://api.getcortexapp.com`.
83
83
 
84
84
  The CLI will retrieve configuration data from the :code:`[default]` section unless you pass the :code:`-t/--tenant` flag.
85
85
 
@@ -99,7 +99,7 @@ Environment Variables
99
99
  The CLI supports the following environment variables. If provided, the Cortex config file will not be read.
100
100
 
101
101
  - CORTEX_API_KEY
102
- - CORTEX_BASE_URL - this is optional if using Cortex cloud; defaults to `https://app.getcortexapp.com`
102
+ - CORTEX_BASE_URL - this is optional if using Cortex cloud; defaults to `https://api.getcortexapp.com`
103
103
 
104
104
  Example:
105
105
 
@@ -617,6 +617,136 @@ This recipe is helpful if you want to remove all Workday teams and import from s
617
617
  cortex teams delete -t ${team}
618
618
  done
619
619
 
620
+ -----------------------------------------------------------------------------
621
+ Add provider for all group type owners where provider is not listed
622
+ -----------------------------------------------------------------------------
623
+
624
+ This recipe adds the value of variable named ``provider`` to any owner for which **type = GROUP** and the provider field is not listed. This recipe can be used to address this issue from Cortex release notes:
625
+ ``Starting July 2nd (2024), any group type owners in the x-cortex-owners section of an entity descriptor will require a provider to be explicitly defined.``
626
+
627
+ Adjust the value of ``provider`` accordingly. It must be one of the providers listed in our `public docs <https://docs.cortex.io/docs/reference/basics/ownership>`_.
628
+
629
+ This recipe does the following:
630
+
631
+ - It runs the Cortex query as documented in the release notes to find all group type owners where the provider is not defined. The ``cortex queries`` parameter ``-f-`` indicates that the query input comes from stdin, provided by the here document (the content provided between the two 'EOF' delimiters).
632
+ - The recipe waits 10 minutes (denoted by parameter ``-x 600``) for the query to complete.
633
+ - It loops over the results of the Cortex query, adding the provider listed in the ``provider`` variable for any group owner where the provider is not defined in the entity.
634
+ - The contents of the entity descriptor are changed using yq and then passed as stdin to the cortex catalog subcommand to update the entity.
635
+
636
+ .. code:: bash
637
+
638
+ provider="GITHUB"
639
+ query_output="query.json"
640
+
641
+ cortex queries run -f- -w -x 600 > ${query_output} << EOF
642
+ jq(entity.descriptor(), "[.info.\"x-cortex-owners\" | .[] | select(.type | ascii_downcase == \"group\") | select(.provider == null)] | length") > 0
643
+ EOF
644
+
645
+ for entity in `cat ${query_output} | jq -r ".result[].tag"`
646
+ do
647
+ echo "entity = $entity"
648
+ cortex catalog descriptor -y -t ${entity} | yq "with(.info.x-cortex-owners[]; select(.type | downcase == \"group\") | select(.provider == null) | .provider = \"${provider}\" )" | cortex catalog create -f-
649
+ done
650
+
651
+ -----------------------------------------------------------------------------
652
+ Obfuscating a Cortex export
653
+ -----------------------------------------------------------------------------
654
+
655
+ This script will obfuscate a Cortex backup. This can be helpful for on-premise customers who may need to provide data to Cortex to help identify performance or usability issues.
656
+
657
+ .. code:: bash
658
+
659
+ # Works off an existing cortex CLI backup.
660
+ # - Create a backup with cortex CLI command: cortex backup export -z 10000
661
+ set -e
662
+ input=$1
663
+ output=$2
664
+
665
+ all_file=${output}/all.yaml
666
+ obfuscated_file=${output}/obfuscated.yaml
667
+
668
+ echo "Output directory: ${output}"
669
+ translate_file="${output}/translate.csv"
670
+
671
+ if [ ! -d ${output} ]; then
672
+ mkdir -p ${output}
673
+ fi
674
+
675
+ for yaml in `ls -1 ${input}/catalog/*`
676
+ do
677
+ entity=$(yq ${yaml} | yq ".info.x-cortex-tag")
678
+ new_entity=$(echo ${entity} | md5sum | cut -d' ' -f 1)
679
+ echo "${entity},${new_entity}" >> ${translate_file}
680
+ echo "Creating: $new_entity"
681
+ cat ${yaml} |\
682
+ yq ".info.\"x-cortex-tag\" = \"${new_entity}\" | \
683
+ .info.title=\"${new_entity}\" | \
684
+ del(.info.description) | \
685
+ del(.info.\"x-cortex-link\") | \
686
+ del(.info.\"x-cortex-links\") | \
687
+ del(.info.\"x-cortex-groups\") | \
688
+ del(.info.\"x-cortex-custom-metadata\") | \
689
+ del(.info.\"x-cortex-issues\") | \
690
+ del(.info.\"x-cortex-git\") | \
691
+ del(.info.\"x-cortex-slack\") | \
692
+ del(.info.\"x-cortex-oncall\") | \
693
+ with(.info; \
694
+ select(.\"x-cortex-team\".members != null) | .\"x-cortex-team\".members = {\"name\": \"Cortex User\", \"email\": \"user@example.com\"} \
695
+ )" >> ${all_file}
696
+ echo "---" >> ${all_file}
697
+ done
698
+
699
+ # The longer strings are translated first preventing substrings from being replaced in a longer string
700
+ cat ${translate_file} | sort -r > ${translate_file}.tmp && echo "entity,new_entity" > ${translate_file} && cat ${translate_file}.tmp >> ${translate_file} && rm ${translate_file}.tmp
701
+
702
+ python3 - ${all_file} ${translate_file} ${obfuscated_file} << EOF
703
+ import csv
704
+ import re
705
+ import sys
706
+
707
+ yaml_file = sys.argv[1]
708
+ translate_file = sys.argv[2]
709
+ output = sys.argv[3]
710
+
711
+ with open(yaml_file, 'r') as f:
712
+ bytes = f.read() # read entire file as bytes
713
+ with open(translate_file, newline='') as csvfile:
714
+ reader = csv.DictReader(csvfile)
715
+ for row in reader:
716
+ entity = row['entity']
717
+ new_entity = row['new_entity']
718
+ print("entity = " + entity + ", new_entity = " + new_entity)
719
+ bytes = bytes.replace("tag: " + entity, "tag: " + new_entity)
720
+ bytes = bytes.replace("name: " + entity, "name: " + new_entity)
721
+
722
+ f = open(output, "w")
723
+ f.write(bytes)
724
+ f.close()
725
+ EOF
726
+
727
+ # change all email addresses
728
+ sed -i 's/email:.*/email: user@example.com/' ${obfuscated_file}
729
+
730
+ # change all slack channel names
731
+ sed -i 's/channel:.*/channel: my-slack-channel/' ${obfuscated_file}
732
+
733
+ # copy export directory to new directory, without catalog YAML
734
+ rsync -av --exclude='catalog' ${input}/ ${output}
735
+ mkdir -p ${output}/catalog
736
+
737
+ # now split single file into multiple that can be passed as parameter to cortex catalog create -f
738
+ cd ${output}/catalog
739
+ yq --no-doc -s '"file_" + $index' ${obfuscated_file}
740
+
741
+ # tar it up
742
+ tar_file=$(basename ${output}).tar
743
+ cd ${output}
744
+ rm ${all_file}
745
+ rm ${translate_file}
746
+ tar -cvf ${tar_file} ./*
747
+
748
+ echo "Created: ${output}/${tar_file}"
749
+
620
750
  ====================================
621
751
 
622
752
  .. |PyPI download month| image:: https://img.shields.io/pypi/dm/cortexapps-cli.svg
@@ -26,7 +26,7 @@ def version():
26
26
  try:
27
27
  with open("pyproject.toml", "rb") as f:
28
28
  pyproject = tomllib.load(f)
29
- version = pyproject["project"]["version"]
29
+ version = pyproject["tool"]["poetry"]["version"]
30
30
  except Exception as e:
31
31
  version = importlib.metadata.version('cortexapps_cli')
32
32
  return version
@@ -1,7 +1,7 @@
1
1
  [tool.poetry]
2
2
  name = "cortexapps-cli"
3
3
  # version will be incremented via command line as part of github actions build
4
- version = "0.26.3"
4
+ version = "0.26.4"
5
5
  description = "Command Line Interface for cortexapps"
6
6
  license = "MIT"
7
7
  authors = [
@@ -17,20 +17,21 @@ classifiers = [
17
17
 
18
18
  [tool.poetry.dependencies]
19
19
  python = "^3.11"
20
- requests = ">= 2.3.0, < 3"
20
+ requests = ">= 2.32.3, < 3"
21
21
  pyyaml = ">= 6.0.1, < 7"
22
+ urllib3 = ">= 2.2.2"
22
23
 
23
24
  [tool.poetry.scripts]
24
25
  cortex = "cortexapps_cli.cortex:cli"
25
26
 
26
27
  [tool.poetry.group.test.dependencies]
27
- pytest = "^7.4.3"
28
- pytest-cov = "^4.1.0"
28
+ pytest = "^8.2.2"
29
+ pytest-cov = "^5.0.0"
29
30
 
30
31
 
31
32
  [tool.poetry.group.dev.dependencies]
32
- pytest-xdist = "^3.4.0"
33
- responses = "^0.24.1"
33
+ pytest-xdist = "^3.6.1"
34
+ responses = "^0.25.3"
34
35
 
35
36
  [build-system]
36
37
  requires = ["poetry-core"]
@@ -44,7 +45,7 @@ Homepage = "https://github.com/cortexapps/cli"
44
45
 
45
46
  [tool.pytest.ini_options]
46
47
  markers = [
47
- "serial",
48
+ "serial"
48
49
  ]
49
50
  minversion = "7.4.3"
50
51
  addopts = "--cov=cortexapps_cli --cov-append --cov-report term-missing"
File without changes
File without changes