Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(#8551): removes python from cht-deploy and some bug fixes #9074

Open
wants to merge 36 commits into
base: master
Choose a base branch
from

Conversation

henokgetachew
Copy link
Contributor

@henokgetachew henokgetachew commented Apr 29, 2024

Description

Handles the following tickets:

#8551 Remove python - establishing feature parity. No major refactoring.
#8604 Catch Missing Values
#8605 Show URL when done execution
#8608 Add a get-all-logs troubleshooting command

Code review checklist

  • Readable: Concise, well named, follows the style guide, documented if necessary.
  • Documented: Configuration and user documentation on cht-docs
  • Backwards compatible: Works with existing data and configuration or includes a migration. Any breaking changes documented in the release notes.

Compose URLs

If Build CI hasn't passed, these may 404:

License

The software is provided under AGPL-3.0. Contributions to this project are accepted under the same license.

scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
Copy link
Contributor

@mrjones-plip mrjones-plip left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work here! Nice to see a migration to node for user/developer facing scripts. As well, I saw you closed some other issues with this PR like #8604, #8605 and #8608 - sweet!

I found two errors - one I'm requesting a change for and the other is in master, but persists in this branch. Let's make the change per my request and then wait til the other issue fixed and we'll dive back into this PR!

@@ -1,40 +1,43 @@
#!/bin/bash
#!/usr/bin/env node
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

before the script does anything else, I think we need to check for the node version. The reason is bash is very universal, but who knows what version of node folks have. My desktop defaults to 12.0.0 which pretty ensures it'll break everything, for example. Per this post, looks like we can easily get the SemVer of node back to old versions.

here's my shell session when debugging this:

➜  deploy git:(cht-deploy-fixes) ✗ ./cht-deploy 
/home/mrjones/Documents/MedicMobile/cht-core/node_modules/axios/index.js:1
import axios from './lib/axios.js';
       ^^^^^

SyntaxError: Unexpected identifier
    at Module._compile (internal/modules/cjs/loader.js:703:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:770:10)
    at Module.load (internal/modules/cjs/loader.js:628:32)
    at Function.Module._load (internal/modules/cjs/loader.js:555:12)
    at Module.require (internal/modules/cjs/loader.js:666:19)
    at require (internal/modules/cjs/helpers.js:16:16)
    at Object.<anonymous> (/home/mrjones/Documents/MedicMobile/cht-core/scripts/deploy/src/install.js:3:15)
    at Module._compile (internal/modules/cjs/loader.js:759:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:770:10)
    at Module.load (internal/modules/cjs/loader.js:628:32)

➜  deploy git:(cht-deploy-fixes) ✗ node
Welcome to Node.js v12.0.0.
Type ".help" for more information.
> process.versions.node.split('.').map(Number)
[ 12, 0, 0 ]
> 

➜  deploy git:(cht-deploy-fixes) ✗ nvm use 18
Now using node v18.16.0 (npm v9.5.1)

➜  deploy git:(cht-deploy-fixes) ✗ ./cht-deploy
No values file provided. Please specify a values file using -f <file>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this was fixed and then a regression was caused, but this doesn't work for me, all be it with a different error than when I first ran it:

➜  deploy git:(cht-deploy-fixes) ✗ nvm use 12.0.0
Now using node v12.0.0 (npm v6.9.0)


➜  deploy git:(cht-deploy-fixes) ✗ ./cht-deploy 
/home/mrjones/Documents/MedicMobile/cht-core/scripts/deploy/cht-deploy:3
import { install } from './src/install.js';
       ^

SyntaxError: Unexpected token {
    at Module._compile (internal/modules/cjs/loader.js:703:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:770:10)
    at Module.load (internal/modules/cjs/loader.js:628:32)
    at Function.Module._load (internal/modules/cjs/loader.js:555:12)
    at Function.Module.runMain (internal/modules/cjs/loader.js:826:10)
    at internal/main/run_main_module.js:17:11

➜  deploy git:(cht-deploy-fixes) ✗ nvm use 20
Now using node v20.11.0 (npm v10.2.4)

➜  deploy git:(cht-deploy-fixes) ✗ ./cht-deploy
No values file provided. Please specify a values file using -f <file>

scripts/deploy/src/install.js Outdated Show resolved Hide resolved
Copy link
Contributor

@nydr nydr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great initiative! I'm happy to see significant progress in replacing the old script.

I would love to see a test, even if it's just trying to import the module or testing the easiest to test function as it can catch some syntax errors and make it easier to add more tests later. Since the old script didn't have any tests I don't consider this a blocker, even in the current state I consider it an significant improvement.

I think some jsdoc style comments on most functions would be great

scripts/deploy/package.json Outdated Show resolved Hide resolved
scripts/deploy/src/install.js Outdated Show resolved Hide resolved
scripts/deploy/src/install.js Outdated Show resolved Hide resolved
scripts/deploy/src/install.js Outdated Show resolved Hide resolved
scripts/deploy/src/install.js Outdated Show resolved Hide resolved
scripts/deploy/src/install.js Outdated Show resolved Hide resolved
scripts/deploy/package.json Show resolved Hide resolved
scripts/deploy/package.json Outdated Show resolved Hide resolved
Copy link
Contributor

@mrjones-plip mrjones-plip left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking better - thanks for iterating!

Confirmed that #9076 is fixed with the latest changes. As well, sad path and happy paths are well covered!

Requesting some security and changes to new save all logs script.

scripts/deploy/troubleshooting/get-all-logs Outdated Show resolved Hide resolved
scripts/deploy/troubleshooting/get-all-logs Outdated Show resolved Hide resolved
scripts/deploy/troubleshooting/get-all-logs Show resolved Hide resolved
scripts/deploy/troubleshooting/get-all-logs Outdated Show resolved Hide resolved
scripts/deploy/troubleshooting/get-all-logs Outdated Show resolved Hide resolved
scripts/deploy/troubleshooting/get-all-logs Outdated Show resolved Hide resolved
scripts/deploy/troubleshooting/get-all-logs Outdated Show resolved Hide resolved
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
@jonathanvq jonathanvq added this to Awaiting Triage in Site Reliability Support Dashboard via automation May 21, 2024
@jonathanvq jonathanvq moved this from Awaiting Triage to This Week's Priorities in Site Reliability Support Dashboard May 21, 2024
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Dismissed Show dismissed Hide dismissed
scripts/deploy/src/install.js Dismissed Show dismissed Hide dismissed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Fixed Show fixed Hide fixed
scripts/deploy/src/install.js Dismissed Show dismissed Hide dismissed
scripts/deploy/src/install.js Dismissed Show dismissed Hide dismissed
scripts/deploy/src/install.js Dismissed Show dismissed Hide dismissed
@henokgetachew
Copy link
Contributor Author

henokgetachew commented May 25, 2024

Comments addressed. A few tests added and build is passing. Also integrated with CI. This puts us in a better spot that we can iterate on.

Copy link
Contributor

@nydr nydr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job! One small comment for displaying of errors

I'd like to see this package published to a registry or be in it's own repo so it can be called directly using npx or similar, but not a requirement for this PR, still a great step forward!

scripts/deploy/cht-deploy Outdated Show resolved Hide resolved
Co-authored-by: Daniel <nydr@users.noreply.github.com>
@henokgetachew
Copy link
Contributor Author

@nydr yes, I've actually already published this to npm. https://www.npmjs.com/package/@medic/cht-deploy. It can be run via npx @medic/cht-deploy -f <path-to-your-yaml>

Copy link
Contributor

@mrjones-plip mrjones-plip left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work here! Love the follow through.

A few small things to fix up!

@@ -1,40 +1,43 @@
#!/bin/bash
#!/usr/bin/env node
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this was fixed and then a regression was caused, but this doesn't work for me, all be it with a different error than when I first ran it:

➜  deploy git:(cht-deploy-fixes) ✗ nvm use 12.0.0
Now using node v12.0.0 (npm v6.9.0)


➜  deploy git:(cht-deploy-fixes) ✗ ./cht-deploy 
/home/mrjones/Documents/MedicMobile/cht-core/scripts/deploy/cht-deploy:3
import { install } from './src/install.js';
       ^

SyntaxError: Unexpected token {
    at Module._compile (internal/modules/cjs/loader.js:703:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:770:10)
    at Module.load (internal/modules/cjs/loader.js:628:32)
    at Function.Module._load (internal/modules/cjs/loader.js:555:12)
    at Function.Module.runMain (internal/modules/cjs/loader.js:826:10)
    at internal/main/run_main_module.js:17:11

➜  deploy git:(cht-deploy-fixes) ✗ nvm use 20
Now using node v20.11.0 (npm v10.2.4)

➜  deploy git:(cht-deploy-fixes) ✗ ./cht-deploy
No values file provided. Please specify a values file using -f <file>

echo
echo "Note: Logs may contain Personally Identifiable Information (PII). Handle and store them securely."
exit 1
}qq
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

calling this now I get an error instead of the usage() output:

➜  deploy git:(cht-deploy-fixes) ✗ ./troubleshooting/get-all-logs 
./troubleshooting/get-all-logs: line 55: syntax error: unexpected end of file

Aha! There's two errant qqs that need to be removed:

Suggested change
}qq
}

done

# Create a tar.gz archive of the log files
tar -czf "$NAMESPACE-logs_$TIMESTAMP.tar.gz" -C "$LOG_DIR" .
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This syntax causes the log files to be exploded in the current directory when uncompressed, which was a surprise. With a small tweak we can make it be created it in a sub directory:

Suggested change
tar -czf "$NAMESPACE-logs_$TIMESTAMP.tar.gz" -C "$LOG_DIR" .
tar -czf "$NAMESPACE-logs_$TIMESTAMP.tar.gz" "$LOG_DIR"

child_process.execSync(`helm install ${project_name} ${CHT_CHART_NAME}` + //NoSONAR
` --version ${chart_version} --namespace ${namespace} ${createNamespaceFlag}` + //NoSONAR
` --values ${valuesFile} --set cht_image_tag=${image_tag}`, { stdio: 'inherit' }); //NoSONAR
console.log(`Instance at ${values.ingress.host} installed successfully.`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's nice to make this a full link:

Suggested change
console.log(`Instance at ${values.ingress.host} installed successfully.`);
console.log(`Instance installed successfully: https://${values.ingress.host}`);

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const readFile = function(f) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if it's worth defending against, but I passed in a project_name and namespace of this:

project_name: mrjones-delete
namespace: "mrjones-delete"
...
   host: "mrjones-delete.dev.medicmobile.org"

And it created it OK apparently:

➜  deploy git:(cht-deploy-fixes) ✗ ./cht-deploy -f  ~/Documents/MedicMobile/medic-infrastructure/terraform/aws/dev/cht-projects/mrjones-dev-cht-deploy-values.yaml
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "medic" chart repository
Update Complete. ⎈Happy Helming!⎈
Release does not exist. Performing install.
NAME: mrjones-delete
LAST DEPLOYED: Tue May 28 15:28:12 2024
NAMESPACE: mrjones-delete
STATUS: deployed
REVISION: 1
TEST SUITE: None
Instance at mrjones-delete.dev.medicmobile.org installed successfully.

But I can't get to it at https://mrjones-delete.dev.medicmobile.org/ - it just 404s. I think this is something endemic to our EKS setup and most other folks won't benefit from improvements here - but wanted to mention it in case it was helpful!

Switching to sane values it worked as expected \o/

project_name: mrjones-dev
namespace: "mrjones-dev"
...
   host: "mrjones.dev.medicmobile.org"

Copy link
Member

@dianabarsan dianabarsan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool stuff! This makes for a much easier read!

invoke install $@
#!/usr/bin/env node

import { install } from './src/install.js';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it isn't linted with our rules.
These are our linting rules: https://github.com/medic/cht-core/blob/master/.eslintrc

process.exit(1);
}
} catch (err) {
return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, if we fail to parse package.json, we'll just go ahead?

return args;
}

function validateFileExists(filePath) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think validateArguments can also call this function, and only return if the file exists. This way, the main function doesn't even need to know what the arguments are, and becomes cleaner.


main().catch((err) => {
console.error('An error occurred:', err.message);
console.error(JSON.stringify(err));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should process.exit(1) here as well.

import fetch from 'node-fetch';
import UserRuntimeError from './error.js';

const obtainCertificateAndKey = async function (values) { //NoSONAR
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think ideally we would never disable sonar for new code.

const fakeImageTag = 'latest';

beforeEach(() => {
execSyncStub = sinon.stub(child_process, 'execSync');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to save these stub names. I'm pretty much against passing this variable to tests and then having trouble knowing what it is.
You can always access it as:

sinon.stub(child_process, 'execSync');
child_process.execSync.withArgs(`helm list -n ${fakeNamespace}`).returns(Buffer.from('test-project'));

` --install test-project medic/cht-chart-4x` +
` --version 5.0.0 --namespace test-namespace` +
` --values ${fakeValuesFile} --set cht_image_tag=${fakeImageTag}`;
expect(execSyncStub.calledWith(expectedCommand)).to.be.true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also need to assess that execSync was not called with other arguments.

expect(execSyncStub.calledOnceWith(expectedCommand)).to.be.true;

it('should install a new release when no release exists', () => {
// Mock the response to simulate no existing release
execSyncStub.withArgs(`helm list -n ${fakeNamespace}`).returns(Buffer.from(''));
execSyncStub.returns(Buffer.from('Install successful'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will overwrite your previous rule of withArgs. You should call them in the reverse order.

child_process.execSync.returns(Buffer.from('Install successful'));
child_process.execSync.withArgs(`helm list -n ${fakeNamespace}`).returns(Buffer.from(''));

const expectedCommand = `helm install test-project medic/cht-chart-4x` +
` --version 5.0.0 --namespace test-namespace --create-namespace` +
` --values ${fakeValuesFile} --set cht_image_tag=${fakeImageTag}`;
expect(execSyncStub.calledWith(expectedCommand)).to.be.true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expect(child_process.execSync.calledOnceWith(expectedCommand)).to.be.true;

function usage() {
echo "Usage: $0 <namespace> [since]"
echo
echo "This script saves logs from all pods within the specified namespace into local files and then creates a tar.gz archive of these logs."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's useful to mention here that if a pod crashed, its logs will not be retrieved.
So people can't, unfortunately, use this to debug failing pods.

I think this script can also pessimistically always try to get the logs from the previously failed pod as well as the current one.

@@ -0,0 +1,8 @@
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should find a way to have these files get linted by our default linting rules: https://github.com/medic/cht-core/blob/master/.eslintrc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants