{"id":19940763,"url":"https://github.com/spectolabs/myna","last_synced_at":"2025-05-03T15:31:34.590Z","repository":{"id":57457288,"uuid":"58844802","full_name":"SpectoLabs/myna","owner":"SpectoLabs","description":"Myna is a testing tool that captures and replays the output of command line programs. ","archived":false,"fork":false,"pushed_at":"2016-08-11T13:14:21.000Z","size":25,"stargazers_count":26,"open_issues_count":2,"forks_count":0,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-04-27T05:21:22.248Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SpectoLabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-05-15T04:55:38.000Z","updated_at":"2023-03-27T20:52:26.000Z","dependencies_parsed_at":"2022-09-05T17:51:59.439Z","dependency_job_id":null,"html_url":"https://github.com/SpectoLabs/myna","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpectoLabs%2Fmyna","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpectoLabs%2Fmyna/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpectoLabs%2Fmyna/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpectoLabs%2Fmyna/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SpectoLabs","download_url":"https://codeload.github.com/SpectoLabs/myna/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224365484,"owners_count":17299156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T00:06:51.067Z","updated_at":"2024-11-13T00:06:51.697Z","avatar_url":"https://github.com/SpectoLabs.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# myna\n\n*\"Process virtualization for the people by the people with people.\" - People*\n\nMyna is a testing tool that captures and replays the output of command line programs.\nIt's heavily inspired by [SpectoLab's Hoverfly](https://github.com/SpectoLabs/hoverfly), \nwhich does capture and playback for http(s) web services.\n\nMyna is written in Go and makes use of Boltdb for storage.  It was\ninitially built to facilitate testing of [KubeFuse](https://github.com/bspaans/kubefuse). \n\nIt does not work with interactive programs at this point in time, but it's\npretty baller with the rest :sparkles:\n\n## Installation\n\nMyna uses the Glide build tool so you can just do:\n\n```\nglide install \ngo build\n```\n\nAnd you're laughing.\n\n\n## Usage\n\nCapture the output of `ls -al /`\n\n```sh\nmyna --capture ls -al /\n```\n\nOr by setting the CAPTURE environment variable:\n\n```sh\nCAPTURE=1 myna ls -al /\n```\n\nPlay back the output of `ls -al /`\n\n```sh\nmyna ls -al /\n```\n\nBy default myna will save all its state in a file called `processes.db`, \nbut we can override that by setting the `DATABASE_LOCATION` environment \nvariable:\n\n```sh\nDATABASE_LOCATION=/tmp/my.db myna --capture ls -al /\nDATABASE_LOCATION=/tmp/my.db myna ls -al /\n```\n\nTo use the simulated process from our tests we can update our code to use myna\nin place of the usual binary, but by writing a wrapper `ls` file and putting\nthis on the PATH we can seamlessly use myna from our tests without having to\nchange a single thing:\n\n```sh\ncat \u003e ls \u003c\u003cEOF \n#!/bin/bash \nmyna \"\\$0\" \"\\$@\"\nEOF\n\nchmod +x ls  \nexport PATH=\"`pwd`:$PATH\"\n```\n\n## Usage from the Shell\n\nWe can also specify a cheeky little alias to work with myna from the\ncommand line, which is less useful for automated testing, but still manages to\nprovide fun for the whole family :family:\n\n```sh\n$ alias ls=\"myna ls\"\n$ ls /\n./myna does not know this process. Run the command in capture mode first.\n$ export CAPTURE=1\n$ ls /\ndrwxr-xr-x  24 root root      4096 May 14 12:29 .\ndrwxr-xr-x  24 root root      4096 May 14 12:29 ..\ndrwxr-xr-x   2 root root     12288 Mar 20 12:37 bin\ndrwxr-xr-x   4 root root      4096 May 14 12:30 boot\ndrwxrwxr-x   2 root root      4096 Aug 10  2015 cdrom\ndrwxr-xr-x  19 root root      4880 May 14 10:17 dev\ndrwxr-xr-x 159 root root     12288 May 14 12:29 etc\ndrwxr-xr-x   4 root root      4096 Aug 10  2015 home\nlrwxrwxrwx   1 root root        32 May 14 12:29 initrd.img -\u003e boot/initrd.img-4.2.0-36-generic\nlrwxrwxrwx   1 root root        32 Apr  6 18:58 initrd.img.old -\u003e boot/initrd.img-4.2.0-35-generic\ndrwxr-xr-x  29 root root      4096 Feb 17 21:13 lib\ndrwxr-xr-x   2 root root      4096 Feb 17 21:13 lib32\ndrwxr-xr-x   2 root root      4096 Feb 17 21:13 lib64\ndrwx------   2 root root     16384 Aug 10  2015 lost+found\ndrwxr-xr-x   3 root root      4096 Aug 10  2015 media\ndrwxr-xr-x   2 root root      4096 Apr 17  2015 mnt\ndrwxr-xr-x   5 root root      4096 Apr  5 00:07 opt\ndr-xr-xr-x 297 root root         0 May 13 22:34 proc\ndrwx------   8 root root      4096 Nov 12  2015 root\ndrwxr-xr-x  30 root root       960 May 15 03:05 run\ndrwxr-xr-x   2 root root     12288 Mar 20 12:37 sbin\ndrwxr-xr-x   2 root root      4096 Apr 22  2015 srv\ndr-xr-xr-x  13 root root         0 May 15 03:31 sys\ndrwxrwxrwt  12 root root     12288 May 15 04:49 tmp\ndrwxr-xr-x  12 root root      4096 Jan 30 15:09 usr\ndrwxr-xr-x  13 root root      4096 Apr 22  2015 var\nlrwxrwxrwx   1 root root        29 May 14 12:29 vmlinuz -\u003e boot/vmlinuz-4.2.0-36-generic\nlrwxrwxrwx   1 root root        29 Apr  6 18:58 vmlinuz.old -\u003e boot/vmlinuz-4.2.0-35-generic\n$ export CAPTURE=0\n$ ls /\ndrwxr-xr-x  24 root root      4096 May 14 12:29 .\ndrwxr-xr-x  24 root root      4096 May 14 12:29 ..\ndrwxr-xr-x   2 root root     12288 Mar 20 12:37 bin\ndrwxr-xr-x   4 root root      4096 May 14 12:30 boot\ndrwxrwxr-x   2 root root      4096 Aug 10  2015 cdrom\ndrwxr-xr-x  19 root root      4880 May 14 10:17 dev\ndrwxr-xr-x 159 root root     12288 May 14 12:29 etc\ndrwxr-xr-x   4 root root      4096 Aug 10  2015 home\nlrwxrwxrwx   1 root root        32 May 14 12:29 initrd.img -\u003e boot/initrd.img-4.2.0-36-generic\nlrwxrwxrwx   1 root root        32 Apr  6 18:58 initrd.img.old -\u003e boot/initrd.img-4.2.0-35-generic\ndrwxr-xr-x  29 root root      4096 Feb 17 21:13 lib\ndrwxr-xr-x   2 root root      4096 Feb 17 21:13 lib32\ndrwxr-xr-x   2 root root      4096 Feb 17 21:13 lib64\ndrwx------   2 root root     16384 Aug 10  2015 lost+found\ndrwxr-xr-x   3 root root      4096 Aug 10  2015 media\ndrwxr-xr-x   2 root root      4096 Apr 17  2015 mnt\ndrwxr-xr-x   5 root root      4096 Apr  5 00:07 opt\ndr-xr-xr-x 297 root root         0 May 13 22:34 proc\ndrwx------   8 root root      4096 Nov 12  2015 root\ndrwxr-xr-x  30 root root       960 May 15 03:05 run\ndrwxr-xr-x   2 root root     12288 Mar 20 12:37 sbin\ndrwxr-xr-x   2 root root      4096 Apr 22  2015 srv\ndr-xr-xr-x  13 root root         0 May 15 03:31 sys\ndrwxrwxrwt  12 root root     12288 May 15 04:49 tmp\ndrwxr-xr-x  12 root root      4096 Jan 30 15:09 usr\ndrwxr-xr-x  13 root root      4096 Apr 22  2015 var\nlrwxrwxrwx   1 root root        29 May 14 12:29 vmlinuz -\u003e boot/vmlinuz-4.2.0-36-generic\nlrwxrwxrwx   1 root root        29 Apr  6 18:58 vmlinuz.old -\u003e boot/vmlinuz-4.2.0-35-generic\n```\n\n\n## A Continuous Integration Workflow\n\n\nFor [KubeFuse](https://github.com/bspaans/kubefuse) I have to generate more\nthan one test case.  To keep this process repeatable I added a `capture` step\nto my build system that I would run whenever the command under test (`kubectl`\nin this case) was updated.\n\nThe build step looks something like this:\n\n```sh\n#!/bin/bash \n\n# Put myna into capture mode \nexport CAPTURE=1\n\n# Remove the old myna database if it exists\nrm -f processes.db\n\n# Run the commands I need for testing:\nmyna kubectl get namespaces\nmyna kubectl get pods --all-namespaces\nmyna kubectl get svc --all-namespaces\nmyna kubectl get rc --all-namespaces\n....\n\n# Export the results\nmyna --export | python -m json.tool \u003e kubectl.json\n```\n\nBefore I start running my tests I need to create the kubectl shim and import\nthe definition:\n\n```sh\ncat \u003e bin/kubectl \u003c\u003cEOF \n#!/bin/bash \n\nunset CAPTURE\nmyna kubectl \"\\$@\"\nEOF\n\nchmod +x bin/kubectl\nrm processes.db\nmyna --import kubectl.json\n```\n\nAnd then I can start my tests with a modified PATH so that the tests pick \nup the shim first:\n\n```sh\nPATH=\"bin/:$PATH\" nosetests\n```\n\nAnd that's it. Your uncle is Bob.\n\n\n## Using Myna in your Python Unit Tests\n\nI actually kind of lied in the previous section, because since the release \nof `python-myna` (see the `contrib/python-myna/` directory) I don't have to \nwrite any shims or modify my path, because I let this library take care of it \nfor me.\n\nFor this example I'm using `nose` and `python-myna`, which you can both install \nusing pip.\n\nThe KubeFuse repository is roughly structured like this:\n\n```\nkubefuse/kubefuse.py\nkubefuse/all_the_rest.py\ntests/test_kubefuse.py\ntests/test_all_the_rest.py\ntests/__init__.py\n```\n\nThe kubefuse directory contains all the source code and the tests directory the \ntests. I run the suite by starting `nosetests` in the root.\n\nTo make my tests work with Myna I use package level `setUp` and `tearDown` \nfunctions that take care of handling the shim creation and PATH jumbling \nfor me. Luckily I can just import these functions straight from the `python-myna`\nlibrary, so my `__init__.py` looks like this:\n\n```python\nfrom myna import *\n```\n\nThe only thing that is missing now is to create and then later import the \nsimulations. This is similar to the steps describe above, and something \nfor which I use Make, because I love Make and Make is awesome. \n\n```make\nmyna:\n\t./kubectl.myna.sh\n\ntest:\n\tDATABASE_LOCATION=\"`pwd`/kubectl.db\" myna --import tests/kubectl.json\n\tDATABASE_LOCATION=\"`pwd`/kubectl.db\" nosetests\n```\n\n\n## License\n\nApache License version 2.0 [See LICENSE for details](./blob/master/LICENSE).\n\n(c) [SpectoLabs](https://specto.io) 2016.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspectolabs%2Fmyna","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspectolabs%2Fmyna","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspectolabs%2Fmyna/lists"}